From e9c2ca5704c7057281ef757fcc19f363610cd3cf Mon Sep 17 00:00:00 2001 From: nodoka Date: Mon, 12 Jan 2026 10:34:04 +0000 Subject: [PATCH] Update bootstrap: 2026-01-12 10:34:04 --- install.sh | 44 ++++++++++ nbcrypt | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++ nbmain.sh.enc | Bin 0 -> 1088 bytes 3 files changed, 280 insertions(+) create mode 100755 install.sh create mode 100755 nbcrypt create mode 100644 nbmain.sh.enc diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..010c279 --- /dev/null +++ b/install.sh @@ -0,0 +1,44 @@ +#!/bin/bash +set -e + +# Bootstrap installer - Universal kickstart script +# Decrypts and executes target-specific setup scripts + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Default target is nbmain (nbase2) +TARGET="${1:-nbmain}" + +ENC_FILE="${SCRIPT_DIR}/${TARGET}.sh.enc" +NBCRYPT="${SCRIPT_DIR}/nbcrypt" + +echo "🚀 Bootstrap: Starting ${TARGET}..." + +# Check if encrypted script exists +if [ ! -f "$ENC_FILE" ]; then + echo "❌ Error: Target '${TARGET}' not found." + echo " Expected file: ${ENC_FILE}" + exit 1 +fi + +# Check if nbcrypt exists +if [ ! -f "$NBCRYPT" ]; then + echo "❌ Error: nbcrypt not found at ${NBCRYPT}" + exit 1 +fi + +# Decrypt and execute +echo "🔐 Decrypting ${TARGET}.sh..." +TEMP_SCRIPT="/tmp/${TARGET}-$$.sh" + +if "$NBCRYPT" decrypt "$ENC_FILE" "$TEMP_SCRIPT" 2>/dev/null; then + chmod +x "$TEMP_SCRIPT" + echo "✅ Executing ${TARGET} setup..." + exec bash "$TEMP_SCRIPT" +else + echo "❌ Decryption failed." + echo " Please ensure your Ed25519 key is loaded in SSH Agent." + rm -f "$TEMP_SCRIPT" + exit 1 +fi + diff --git a/nbcrypt b/nbcrypt new file mode 100755 index 0000000..d00d1c2 --- /dev/null +++ b/nbcrypt @@ -0,0 +1,236 @@ +#!/bin/bash +set -euo pipefail + +# nbcrypt - SSH Agent based encryption/decryption tool +# Uses Ed25519 signature for deterministic key derivation + +SCRIPT_NAME="$(basename "$0")" +KEY_SEED_MESSAGE="nbase2-secret-key-seed-v1" +KEY_IDENTITY="id_ed25519" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +error() { + echo -e "${RED}❌ Error: $*${NC}" >&2 + exit 1 +} + +info() { + echo -e "${GREEN}â„šī¸ $*${NC}" >&2 +} + +warn() { + echo -e "${YELLOW}âš ī¸ $*${NC}" >&2 +} + +usage() { + cat < [arguments] + +Commands: + encrypt Encrypt a file using SSH Agent key + decrypt Decrypt a file using SSH Agent key + check Check if SSH Agent has required key + help Show this help message + +Requirements: + - SSH Agent must be running with id_ed25519 key loaded + - ssh-keygen and openssl commands must be available + +Examples: + $SCRIPT_NAME encrypt secrets.txt secrets.enc + $SCRIPT_NAME decrypt secrets.enc secrets.txt + $SCRIPT_NAME check + +EOF + exit 0 +} + +check_dependencies() { + local missing=() + + for cmd in ssh-keygen openssl ssh-add; do + if ! command -v "$cmd" >/dev/null 2>&1; then + missing+=("$cmd") + fi + done + + if [ ${#missing[@]} -gt 0 ]; then + error "Missing required commands: ${missing[*]}" + fi +} + +check_ssh_agent() { + # Check if SSH_AUTH_SOCK is set + if [ -z "${SSH_AUTH_SOCK:-}" ]; then + error "SSH Agent is not running or SSH_AUTH_SOCK is not set" + fi + + # Check if ssh-add can connect to agent + if ! ssh-add -l >/dev/null 2>&1; then + local rc=$? + if [ $rc -eq 2 ]; then + error "Cannot connect to SSH Agent" + elif [ $rc -eq 1 ]; then + error "SSH Agent has no identities loaded" + fi + fi + + # Check if Ed25519 key is loaded + if ! ssh-add -l 2>/dev/null | grep -q "ED25519"; then + error "No Ed25519 key found in SSH Agent. Please add id_ed25519 with: ssh-add ~/.ssh/id_ed25519" + fi + + info "SSH Agent check passed (Ed25519 key found)" + return 0 +} + +derive_key() { + # Derive encryption key from Ed25519 signature + # Ed25519 signatures are deterministic, so same message = same signature + + local temp_message=$(mktemp) + local temp_sig=$(mktemp) + local temp_pubkey=$(mktemp) + + trap "rm -f '$temp_message' '$temp_sig' '$temp_pubkey'" EXIT + + # Create message to sign + echo -n "$KEY_SEED_MESSAGE" > "$temp_message" + + # Get public key from agent for the Ed25519 key + ssh-add -L 2>/dev/null | grep "ssh-ed25519" | head -1 > "$temp_pubkey" + + if [ ! -s "$temp_pubkey" ]; then + error "Could not extract Ed25519 public key from SSH Agent" + fi + + # Sign the message using ssh-keygen + # Note: ssh-keygen -Y sign requires the public key in "allowed signers" format + local temp_allowed=$(mktemp) + echo "key1 $(cat "$temp_pubkey")" > "$temp_allowed" + + # Sign the message + if ! ssh-keygen -Y sign -f "$temp_allowed" -n "nbase2" < "$temp_message" > "$temp_sig" 2>/dev/null; then + # If -Y sign doesn't work (older ssh-keygen), try alternative method + # We'll use ssh-agent's signing capability directly through a workaround + + # Extract just the signature data using ssh-agent protocol + # Since we can't easily do that in pure bash, we'll use a deterministic approach + # based on the public key itself as a fallback + + warn "ssh-keygen -Y sign not available, using fallback key derivation" + + # Fallback: Use public key hash as seed + cat "$temp_pubkey" | sha256sum | head -c 64 + rm -f "$temp_allowed" + return 0 + fi + + rm -f "$temp_allowed" + + # Extract signature and hash it to create 256-bit key + # The signature file contains base64-encoded signature data + cat "$temp_sig" | base64 -d 2>/dev/null | sha256sum | head -c 64 +} + +encrypt_file() { + local input="$1" + local output="$2" + + if [ ! -f "$input" ]; then + error "Input file not found: $input" + fi + + check_ssh_agent + + info "Deriving encryption key from SSH Agent..." + local key=$(derive_key) + + if [ -z "$key" ]; then + error "Failed to derive encryption key" + fi + + info "Encrypting $input -> $output..." + + # Use OpenSSL to encrypt with AES-256-CBC + # Pass the hex key directly to openssl + openssl enc -aes-256-cbc -salt -pbkdf2 -in "$input" -out "$output" -pass "pass:$key" + + if [ $? -eq 0 ]; then + info "✅ Encryption successful: $output" + else + error "Encryption failed" + fi +} + +decrypt_file() { + local input="$1" + local output="$2" + + if [ ! -f "$input" ]; then + error "Input file not found: $input" + fi + + check_ssh_agent + + info "Deriving decryption key from SSH Agent..." + local key=$(derive_key) + + if [ -z "$key" ]; then + error "Failed to derive decryption key" + fi + + info "Decrypting $input -> $output..." + + # Use OpenSSL to decrypt with AES-256-CBC + if openssl enc -aes-256-cbc -d -salt -pbkdf2 -in "$input" -out "$output" -pass "pass:$key" 2>/dev/null; then + info "✅ Decryption successful: $output" + else + error "Decryption failed (wrong key or corrupted file)" + fi +} + +# Main command dispatcher +main() { + if [ $# -eq 0 ]; then + usage + fi + + check_dependencies + + local command="$1" + shift + + case "$command" in + encrypt) + if [ $# -ne 2 ]; then + error "encrypt requires 2 arguments: " + fi + encrypt_file "$1" "$2" + ;; + decrypt) + if [ $# -ne 2 ]; then + error "decrypt requires 2 arguments: " + fi + decrypt_file "$1" "$2" + ;; + check) + check_ssh_agent + echo "✅ All checks passed" + ;; + help|--help|-h) + usage + ;; + *) + error "Unknown command: $command (use 'help' for usage)" + ;; + esac +} + +main "$@" + diff --git a/nbmain.sh.enc b/nbmain.sh.enc new file mode 100644 index 0000000000000000000000000000000000000000..b43c4dbbb1504fa5598ba0116ae6f762b4c83282 GIT binary patch literal 1088 zcmV-G1i$-JVQh3|WM5yfUyVkhtK82pf(b|Fi8QE(S4ZyhmS2`K|HxU_8{Zk@$)BnH)aiSO6`{(i$iShVk zPlxcFq62+jNX<*6T)#WEVUfxw7SIZiCm^6$B@arCYap(#6U(q>>?m|!Sy%@sj>*wS zy{bde4hPV_HR+U-`_MsqICfD%vFa;8PX=`vSbqPTky=uD4$K7 zBmm`t-1I(OpGB!O8G>K`W_dVgZ3Z^YD(q=%I^*sQBugcgTCv-Oo-giRLYCDJ`bG?% zEfcGBuQ(aYttHKzQeg4Hu#ok0WPwW4<^H^2YXHL5A@T~?AUu}xK}i2CRy<8p0;ECG zwO`wIvYHl6fsUmDi>3#QQ8w`7!=FSCu42_ToG#QF2mH22Qwo`We;PQ|lF7Q=%~s-F zr6`o*(H^Hl%Ne5+Qja;(q0R12{@=e0lb9+aDA<9zWo|sc9+YomNKr>n@5V#M+MVV*loqn})e$wzul(dz@&JId~t7bR?Ls>I@WfCL;a56&J+O65llmX8kzEahA9Mbfv@8 zg+E=I4rkqC8JlceWG?yT%7uJQs%|OZ-74K{A5z4SSAV}_n~aty_%bTYol~PA^KC@# zhk<{V&&K*$y2tJ>P{2C!v3>jkGYEypdY^8OxuoCeR5=CGsoT5BBjg$(OApT$*IeG> zN0oVH)#+eRW~;T%Tn&{3#+6Md)jD zr*n%zeNXhnh=xIaSU|y^!*V008Ocr9$k=Pi4mFrvhnf=-hkFuNz%CVus`9p9$--y3#Y8; zMuF=c|IgDP!Z>L780qky9?T-W2yAx0nMU;cDx#mT8N>939U|e}WA=3W%I(}Geg<0e zS53(hVtgdLEwXzQj#(==$phNWr=%lLsR(&lj%x{_#