Update bootstrap: 2026-01-20 16:40:01

This commit is contained in:
2026-01-20 16:40:01 +09:00
parent 3050323ff6
commit 664f12656b
3 changed files with 309 additions and 91 deletions

View File

@@ -27,25 +27,49 @@ if [ ! -f "$NBCRYPT" ]; then
exit 1 exit 1
fi fi
# Load SSH Agent environment BEFORE running nbcrypt
# This ensures nbcrypt can find the Ed25519 key without prompting for BWS token
AGENT_ENV_FILE="/tmp/.nb_agent_env_${USER:-$(id -un)}"
if [ -f "$AGENT_ENV_FILE" ]; then
# Check if we already have a valid SSH_AUTH_SOCK (Agent Forward)
# But also verify it actually works with ssh-add -l
if [ -n "${SSH_AUTH_SOCK:-}" ] && [ -S "${SSH_AUTH_SOCK}" ]; then
# Test if the agent actually works
if ssh-add -l >/dev/null 2>&1; then
# Agent Forward exists and works, preserve it and skip file loading
echo "🔑 Using existing SSH Agent Forward (preserved)"
else
# Agent Forward exists but doesn't work (stale socket), load from file
echo "🔑 Existing SSH Agent Forward is stale, loading from file..."
source "$AGENT_ENV_FILE"
fi
else
# No valid agent, safe to load from file
echo "🔑 Loading SSH Agent environment..."
source "$AGENT_ENV_FILE"
fi
fi
# Ed25519 が無いときは BWS から鍵を取得して ssh-add--keep でディスクに残す)
if ! ssh-add -l 2>/dev/null | grep -q ED25519; then
"$NBCRYPT" keychain --keep
[ -f "$AGENT_ENV_FILE" ] && source "$AGENT_ENV_FILE"
fi
# Decrypt and execute # Decrypt and execute
echo "🔐 Decrypting ${TARGET}.sh..." echo "🔐 Decrypting ${TARGET}.sh..."
TEMP_SCRIPT="/tmp/${TARGET}-$$.sh" TEMP_SCRIPT="/tmp/${TARGET}-$$.sh"
if "$NBCRYPT" decrypt "$ENC_FILE" "$TEMP_SCRIPT"; then if "$NBCRYPT" decfile "$ENC_FILE" "$TEMP_SCRIPT"; then
chmod +x "$TEMP_SCRIPT" chmod +x "$TEMP_SCRIPT"
# Load SSH Agent environment if it was created by nbcrypt/BWS setup # Reload SSH Agent environment if it was updated by nbcrypt/BWS setup
# Only load if we don't already have a valid Agent Forward # (in case BWS setup created a new agent)
AGENT_ENV_FILE="/tmp/.nb_agent_env_${USER:-$(id -un)}"
if [ -f "$AGENT_ENV_FILE" ]; then if [ -f "$AGENT_ENV_FILE" ]; then
# Check if we already have a valid SSH_AUTH_SOCK (Agent Forward) # Check if we already have a valid SSH_AUTH_SOCK (Agent Forward)
if [ -z "${SSH_AUTH_SOCK:-}" ] || [ ! -S "${SSH_AUTH_SOCK}" ]; then if [ -z "${SSH_AUTH_SOCK:-}" ] || [ ! -S "${SSH_AUTH_SOCK}" ]; then
# No valid agent, safe to load from file # No valid agent, safe to load from file
echo "🔑 Loading SSH Agent environment..."
source "$AGENT_ENV_FILE" source "$AGENT_ENV_FILE"
else
# Agent Forward exists, preserve it and skip file loading
echo "🔑 Using existing SSH Agent Forward (preserved)"
fi fi
fi fi

356
nbcrypt
View File

@@ -1,18 +1,18 @@
#!/bin/bash #!/bin/bash
set -euo pipefail set -euo pipefail
# nbcrypt - SSH Agent based encryption/decryption tool # nbcrypt - SSH Agent ベースの暗号化/復号ツール
# Uses Ed25519 signature for deterministic key derivation # Ed25519 署名で決定的な鍵導出を行う
SCRIPT_NAME="$(basename "$0")" SCRIPT_NAME="$(basename "$0")"
KEY_SEED_MESSAGE="nbase2-secret-key-seed-v1" KEY_SEED_MESSAGE="nbase2-secret-key-seed-v1"
KEY_IDENTITY="id_ed25519" KEY_IDENTITY="id_ed25519"
# Colors for output # 出力用の色
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
NC='\033[0m' # No Color NC='\033[0m' # リセット
error() { error() {
echo -e "${RED}❌ Error: $*${NC}" >&2 echo -e "${RED}❌ Error: $*${NC}" >&2
@@ -27,29 +27,50 @@ warn() {
echo -e "${YELLOW}⚠️ $*${NC}" >&2 echo -e "${YELLOW}⚠️ $*${NC}" >&2
} }
print_source_agent_hint() {
local env_file="/tmp/.nb_agent_env_${USER:-$(id -un)}"
echo "" >&2
info "この agent を現在のシェルで使うには、次を実行:"
echo " source $env_file" >&2
}
usage() { usage() {
cat <<EOF cat <<EOF
Usage: $SCRIPT_NAME <command> [arguments] Usage: $SCRIPT_NAME <command> [arguments]
Commands: Commands:
encrypt <input> <output> Encrypt a file using SSH Agent key enc <text> Encrypt a text string (or use enctext)
decrypt [options] <input> <output> Decrypt a file using SSH Agent key dec <text> Decrypt a text string (or use dectext)
enctext <text> Encrypt a text string (alias for enc)
dectext <text> Decrypt a text string (alias for dec)
encfile <input> <output> Encrypt a file (or use encrypt)
decfile <input> <output> Decrypt a file (or use decrypt)
encrypt <input> <output> Encrypt a file (alias for encfile)
decrypt [options] <input> <output> Decrypt a file (alias for decfile)
keychain [-k|--keep] Fetch SSH keys from BWS and run ssh-add.
Default: remove key files after ssh-add. Use -k/--keep to keep.
install-bws Install Bitwarden Secrets Manager CLI (bws) install-bws Install Bitwarden Secrets Manager CLI (bws)
check Check if SSH Agent has required key check Check if SSH Agent has required key
help Show this help message help Show this help message
Options for decrypt: Options for decrypt/decfile:
-f, --force Force download nbloader from BWS and setup SSH Agent -f, --force Force download nbloader from BWS and setup SSH Agent
(skips SSH Agent check, requires BWS_ACCESS_TOKEN) (skips SSH Agent check, requires BWS_ACCESS_TOKEN)
Text commands support stdin:
echo "secret" | $SCRIPT_NAME enc -
echo "encrypted" | $SCRIPT_NAME dec -
Requirements: Requirements:
- SSH Agent must be running with id_ed25519 key loaded - SSH Agent with id_ed25519 key, or ~/.ssh/id_ed25519 file, or BWS_ACCESS_TOKEN
- ssh-keygen and openssl commands must be available - ssh-keygen and openssl commands must be available
Examples: Examples:
$SCRIPT_NAME encrypt secrets.txt secrets.enc $SCRIPT_NAME enc "secret text"
$SCRIPT_NAME decrypt secrets.enc secrets.txt $SCRIPT_NAME dec "ENC:U2FsdGVkX1..."
$SCRIPT_NAME decrypt -f secrets.enc secrets.txt # Force BWS download $SCRIPT_NAME encfile secrets.txt secrets.enc
$SCRIPT_NAME decfile secrets.enc secrets.txt
$SCRIPT_NAME keychain
$SCRIPT_NAME install-bws $SCRIPT_NAME install-bws
$SCRIPT_NAME check $SCRIPT_NAME check
@@ -71,12 +92,52 @@ check_dependencies() {
fi fi
} }
get_bws_token() {
# 1. すでに環境変数にある
if [ -n "${BWS_ACCESS_TOKEN:-}" ]; then
echo "$BWS_ACCESS_TOKEN"
return 0
fi
# 2. nbconf から取得を試みる
local nbase_root="${NBASE_HOME:-$(cd "$(dirname "$0")/.." && pwd)}"
local nbconf_cmd="${nbase_root}/bin/nbconf"
if [ -f "$nbconf_cmd" ] && [ -x "$nbconf_cmd" ]; then
local val
val=$("$nbconf_cmd" get BWS_ACCESS_TOKEN -d 2>/dev/null) || true
if [ -n "$val" ]; then
echo "$val"
return 0
fi
fi
return 1
}
check_ssh_agent() { check_ssh_agent() {
# Check if SSH_AUTH_SOCK is set and valid local env_file="/tmp/.nb_agent_env_${USER:-$(id -un)}"
# まず、以前の BWS セットアップで作られた env ファイルがあれば読む
# SSH_AUTH_SOCK の検査より前にやるenv にソケットパスが入っているため)
if [ -f "$env_file" ]; then
source "$env_file"
info "SSH Agent environment loaded from $env_file"
# 読んだあと ssh-add が動くか確認
if [ -n "${SSH_AUTH_SOCK:-}" ] && [ -S "${SSH_AUTH_SOCK}" ]; then
if ssh-add -l >/dev/null 2>&1; then
# Ed25519 が載っているか確認
if ssh-add -l 2>/dev/null | grep -q "ED25519"; then
info "SSH Agent check passed (Ed25519 key found)"
return 0
fi
fi
fi
fi
# 現在の環境の SSH_AUTH_SOCK がセットかつ有効か(すでにシェルに Agent がある場合)
if [ -n "${SSH_AUTH_SOCK:-}" ] && [ -S "${SSH_AUTH_SOCK}" ]; then if [ -n "${SSH_AUTH_SOCK:-}" ] && [ -S "${SSH_AUTH_SOCK}" ]; then
# Check if ssh-add can connect to agent # ssh-add で agent に接続できるか
if ssh-add -l >/dev/null 2>&1; then if ssh-add -l >/dev/null 2>&1; then
# Check if Ed25519 key is loaded # Ed25519 が載っているか確認
if ssh-add -l 2>/dev/null | grep -q "ED25519"; then if ssh-add -l 2>/dev/null | grep -q "ED25519"; then
info "SSH Agent check passed (Ed25519 key found)" info "SSH Agent check passed (Ed25519 key found)"
return 0 return 0
@@ -84,11 +145,13 @@ check_ssh_agent() {
fi fi
fi fi
# No valid agent or no Ed25519 key - try BWS bootstrap # ここに来た場合: (1) env ファイルがない (2) あっても ssh-add 失敗 (3) Ed25519 がない
# いずれも BWS から bootstrap を試す
info "No Ed25519 key found in SSH Agent. Attempting BWS bootstrap..." info "No Ed25519 key found in SSH Agent. Attempting BWS bootstrap..."
# Get BWS access token # BWS トークン取得環境変数、nbconf、または入力
local bws_token="${BWS_ACCESS_TOKEN:-}" local bws_token
bws_token=$(get_bws_token) || true
if [ -z "$bws_token" ]; then if [ -z "$bws_token" ]; then
echo -n "Enter BWS_ACCESS_TOKEN: " >&2 echo -n "Enter BWS_ACCESS_TOKEN: " >&2
read bws_token read bws_token
@@ -97,14 +160,29 @@ check_ssh_agent() {
fi fi
fi fi
# Try to load setup script from BWS # BWS からセットアップスクリプトを取得して実行
load_bws_setup "$bws_token" load_bws_setup "$bws_token"
# Re-check agent after BWS setup # BWS セットアップ後に agent を再確認env を読み直す)
if [ -f "$env_file" ]; then
source "$env_file"
fi
if [ -n "${SSH_AUTH_SOCK:-}" ] && [ -S "${SSH_AUTH_SOCK}" ]; then if [ -n "${SSH_AUTH_SOCK:-}" ] && [ -S "${SSH_AUTH_SOCK}" ]; then
if ssh-add -l >/dev/null 2>&1 && ssh-add -l 2>/dev/null | grep -q "ED25519"; then if ssh-add -l >/dev/null 2>&1; then
info "SSH Agent check passed (Ed25519 key found after BWS setup)" if ssh-add -l 2>/dev/null | grep -q "ED25519"; then
return 0 info "SSH Agent check passed (Ed25519 key found after BWS setup)"
return 0
fi
else
# BWS セットアップ後に ssh-add が失敗
if [ -f "$env_file" ]; then
warn "SSH Agent communication failed after BWS setup."
warn "Please run: source $env_file"
error "SSH Agent communication failed. Run 'source $env_file' and try again."
else
error "SSH Agent communication failed after BWS setup."
fi
fi fi
fi fi
@@ -117,23 +195,23 @@ load_bws_setup() {
info "Loading setup script from BWS (secret ID: $secret_id)..." info "Loading setup script from BWS (secret ID: $secret_id)..."
# Check if bws command exists, if not try to install it # bws が無ければインストールを試す
if ! command -v bws >/dev/null 2>&1; then if ! command -v bws >/dev/null 2>&1; then
warn "bws command not found. Attempting to install..." warn "bws command not found. Attempting to install..."
install_bws || error "Failed to install bws CLI" install_bws || error "Failed to install bws CLI"
fi fi
# Export token temporarily for bws command # bws 用にトークンを一時 export
export BWS_ACCESS_TOKEN="$token" export BWS_ACCESS_TOKEN="$token"
# Get the secret from BWS using secret ID # 秘密 ID で BWS から secret を取得
local loader_script local loader_script
if command -v jq >/dev/null 2>&1; then if command -v jq >/dev/null 2>&1; then
loader_script=$(bws secret get "$secret_id" 2>&1 | jq -r '.value // empty') loader_script=$(bws secret get "$secret_id" 2>&1 | jq -r '.value // empty')
elif command -v python3 >/dev/null 2>&1; then elif command -v python3 >/dev/null 2>&1; then
loader_script=$(bws secret get "$secret_id" 2>&1 | python3 -c "import sys, json; print(json.load(sys.stdin).get('value', ''))" 2>/dev/null) loader_script=$(bws secret get "$secret_id" 2>&1 | python3 -c "import sys, json; print(json.load(sys.stdin).get('value', ''))" 2>/dev/null)
else else
# Fallback: try to extract value with grep/sed (fragile but works for simple JSON) # フォールバック: grep/sed で value を取り出し(単純 JSON 用)
loader_script=$(bws secret get "$secret_id" 2>&1 | grep -o '"value": "[^"]*"' | sed 's/"value": "//;s/"$//' | head -1) loader_script=$(bws secret get "$secret_id" 2>&1 | grep -o '"value": "[^"]*"' | sed 's/"value": "//;s/"$//' | head -1)
fi fi
@@ -141,11 +219,11 @@ load_bws_setup() {
error "Failed to retrieve secret from BWS. Check your token and secret ID." error "Failed to retrieve secret from BWS. Check your token and secret ID."
fi fi
# Execute the loader script # ローダースクリプトを実行
info "Executing BWS setup script..." info "Executing BWS setup script..."
eval "$loader_script" eval "$loader_script"
# Load agent environment if it was created # 作成されていれば agent env を読む
local env_file="/tmp/.nb_agent_env_${USER:-$(id -un)}" local env_file="/tmp/.nb_agent_env_${USER:-$(id -un)}"
if [ -f "$env_file" ]; then if [ -f "$env_file" ]; then
source "$env_file" source "$env_file"
@@ -153,6 +231,32 @@ load_bws_setup() {
fi fi
} }
keychain_cmd() {
local keep_mode="$1"
info "Fetching SSH keys from BWS and running ssh-add..."
local bws_token
bws_token=$(get_bws_token) || true
if [ -z "$bws_token" ]; then
echo -n "Enter BWS_ACCESS_TOKEN: " >&2
read bws_token
if [ -z "$bws_token" ]; then
error "BWS_ACCESS_TOKEN is required"
fi
fi
load_bws_setup "$bws_token"
if [ "$keep_mode" != "true" ]; then
info "Removing key files from disk (use -k/--keep to keep)..."
rm -f ~/.ssh/id_rsa ~/.ssh/id_ecdsa ~/.ssh/id_ed25519
fi
info "SSH agent setup complete."
ssh-add -l
print_source_agent_hint
}
install_bws() { install_bws() {
local arch local arch
arch=$(uname -m) arch=$(uname -m)
@@ -163,7 +267,7 @@ install_bws() {
mkdir -p "$bws_bin_dir" mkdir -p "$bws_bin_dir"
export PATH="$bws_bin_dir:$PATH" export PATH="$bws_bin_dir:$PATH"
# Determine architecture # アーキテクチャ判定
case "$arch" in case "$arch" in
x86_64) x86_64)
arch="x86_64-unknown-linux-gnu" arch="x86_64-unknown-linux-gnu"
@@ -181,7 +285,7 @@ install_bws() {
info "Downloading bws v${bws_version} for ${arch}..." info "Downloading bws v${bws_version} for ${arch}..."
# Install dependencies if needed # 必要なら unzip 等を入れる
if ! command -v unzip >/dev/null 2>&1; then if ! command -v unzip >/dev/null 2>&1; then
if command -v apt-get >/dev/null 2>&1; then if command -v apt-get >/dev/null 2>&1; then
sudo apt-get update -qq && sudo apt-get install -y unzip >/dev/null 2>&1 sudo apt-get update -qq && sudo apt-get install -y unzip >/dev/null 2>&1
@@ -190,7 +294,7 @@ install_bws() {
fi fi
fi fi
# Download and extract # ダウンロードして展開
local temp_zip="/tmp/${zip_name}" local temp_zip="/tmp/${zip_name}"
if command -v wget >/dev/null 2>&1; then if command -v wget >/dev/null 2>&1; then
wget -q "$url" -O "$temp_zip" || return 1 wget -q "$url" -O "$temp_zip" || return 1
@@ -209,52 +313,50 @@ install_bws() {
} }
derive_key() { derive_key() {
# Derive encryption key from Ed25519 signature # Ed25519 署名から暗号鍵を導出(同じメッセージなら同じ署名で決定的)
# Ed25519 signatures are deterministic, so same message = same signature # 優先順位: 1. SSH Agent, 2. 秘密鍵ファイル, 3. BWS (check_ssh_agent で処理)
local temp_message=$(mktemp) local temp_message=$(mktemp)
local temp_sig=$(mktemp) local temp_sig=$(mktemp)
local temp_pubkey=$(mktemp) local temp_pubkey=$(mktemp)
local temp_allowed=$(mktemp)
trap "rm -f '$temp_message' '$temp_sig' '$temp_pubkey'" EXIT trap "rm -f '$temp_message' '$temp_sig' '$temp_pubkey' '$temp_allowed'" EXIT
# Create message to sign # 署名するメッセージを作成
echo -n "$KEY_SEED_MESSAGE" > "$temp_message" echo -n "$KEY_SEED_MESSAGE" > "$temp_message"
# Get public key from agent for the Ed25519 key # 1. SSH Agent から Ed25519 の公開鍵を取得を試みる
ssh-add -L 2>/dev/null | grep "ssh-ed25519" | head -1 > "$temp_pubkey" if ssh-add -L 2>/dev/null | grep "ssh-ed25519" | head -1 | awk '{print $1 " " $2}' > "$temp_pubkey" 2>/dev/null && [ -s "$temp_pubkey" ]; then
# Agent から取得できた場合
echo "key1 $(cat "$temp_pubkey")" > "$temp_allowed"
if [ ! -s "$temp_pubkey" ]; then # メッセージに署名Agent経由
error "Could not extract Ed25519 public key from SSH Agent" if ssh-keygen -Y sign -f "$temp_allowed" -n "nbase2" < "$temp_message" > "$temp_sig" 2>/dev/null; then
# 署名を抜き出してハッシュし 256bit 鍵に
cat "$temp_sig" | base64 -d 2>/dev/null | sha256sum | head -c 64
return 0
fi
fi fi
# Sign the message using ssh-keygen # 2. SSH Agent がない場合、秘密鍵ファイルから直接署名を試みる
# Note: ssh-keygen -Y sign requires the public key in "allowed signers" format local key_file="${NB_KEY_FILE:-${HOME}/.ssh/id_ed25519}"
local temp_allowed=$(mktemp) if [ -f "$key_file" ]; then
echo "key1 $(cat "$temp_pubkey")" > "$temp_allowed" # 公開鍵を抽出
if ssh-keygen -y -f "$key_file" 2>/dev/null | awk '{print $1 " " $2}' > "$temp_pubkey" 2>/dev/null && [ -s "$temp_pubkey" ]; then
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 ssh-keygen -Y sign -f "$key_file" -n "nbase2" < "$temp_message" > "$temp_sig" 2>/dev/null; then
# If -Y sign doesn't work (older ssh-keygen), try alternative method # 署名を抜き出してハッシュし 256bit 鍵に
# We'll use ssh-agent's signing capability directly through a workaround cat "$temp_sig" | base64 -d 2>/dev/null | sha256sum | head -c 64
return 0
# Extract just the signature data using ssh-agent protocol fi
# Since we can't easily do that in pure bash, we'll use a deterministic approach fi
# 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 fi
rm -f "$temp_allowed" # 3. どちらも失敗した場合、エラーBWS は check_ssh_agent で処理される)
error "Could not derive key from SSH Agent or private key file. Please ensure SSH Agent is running with Ed25519 key, or set NB_KEY_FILE to a valid private key path."
# 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() { encrypt_file() {
@@ -265,9 +367,13 @@ encrypt_file() {
error "Input file not found: $input" error "Input file not found: $input"
fi fi
check_ssh_agent # 秘密鍵ファイルがある場合は check_ssh_agent をスキップ
local key_file="${NB_KEY_FILE:-${HOME}/.ssh/id_ed25519}"
if [ ! -f "$key_file" ]; then
check_ssh_agent
fi
info "Deriving encryption key from SSH Agent..." info "Deriving encryption key..."
local key=$(derive_key) local key=$(derive_key)
if [ -z "$key" ]; then if [ -z "$key" ]; then
@@ -276,8 +382,7 @@ encrypt_file() {
info "Encrypting $input -> $output..." info "Encrypting $input -> $output..."
# Use OpenSSL to encrypt with AES-256-CBC # OpenSSL で AES-256-CBC 暗号化(鍵は hex で渡す)
# Pass the hex key directly to openssl
openssl enc -aes-256-cbc -salt -pbkdf2 -in "$input" -out "$output" -pass "pass:$key" openssl enc -aes-256-cbc -salt -pbkdf2 -in "$input" -out "$output" -pass "pass:$key"
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
@@ -296,10 +401,11 @@ decrypt_file() {
error "Input file not found: $input" error "Input file not found: $input"
fi fi
# Force mode: skip SSH Agent check and directly load from BWS # force: SSH Agent チェックを飛ばし BWS から直接読む
if [ "$force_mode" = "true" ]; then if [ "$force_mode" = "true" ]; then
info "Force mode: Loading setup script from BWS..." info "Force mode: Loading setup script from BWS..."
local bws_token="${BWS_ACCESS_TOKEN:-}" local bws_token
bws_token=$(get_bws_token) || true
if [ -z "$bws_token" ]; then if [ -z "$bws_token" ]; then
echo -n "Enter BWS_ACCESS_TOKEN: " >&2 echo -n "Enter BWS_ACCESS_TOKEN: " >&2
read bws_token read bws_token
@@ -308,7 +414,7 @@ decrypt_file() {
fi fi
fi fi
load_bws_setup "$bws_token" load_bws_setup "$bws_token"
# After BWS setup, check SSH Agent again # BWS セットアップ後に agent を再確認
if [ -z "${SSH_AUTH_SOCK:-}" ] || [ ! -S "${SSH_AUTH_SOCK}" ]; then if [ -z "${SSH_AUTH_SOCK:-}" ] || [ ! -S "${SSH_AUTH_SOCK}" ]; then
error "SSH Agent not available after BWS setup" error "SSH Agent not available after BWS setup"
fi fi
@@ -316,10 +422,14 @@ decrypt_file() {
error "Ed25519 key not found in SSH Agent after BWS setup" error "Ed25519 key not found in SSH Agent after BWS setup"
fi fi
else else
check_ssh_agent # 秘密鍵ファイルがある場合は check_ssh_agent をスキップ
local key_file="${NB_KEY_FILE:-${HOME}/.ssh/id_ed25519}"
if [ ! -f "$key_file" ]; then
check_ssh_agent
fi
fi fi
info "Deriving decryption key from SSH Agent..." info "Deriving decryption key..."
local key=$(derive_key) local key=$(derive_key)
if [ -z "$key" ]; then if [ -z "$key" ]; then
@@ -328,7 +438,7 @@ decrypt_file() {
info "Decrypting $input -> $output..." info "Decrypting $input -> $output..."
# Use OpenSSL to decrypt with AES-256-CBC # OpenSSL AES-256-CBC 復号
if openssl enc -aes-256-cbc -d -salt -pbkdf2 -in "$input" -out "$output" -pass "pass:$key" 2>/dev/null; then if openssl enc -aes-256-cbc -d -salt -pbkdf2 -in "$input" -out "$output" -pass "pass:$key" 2>/dev/null; then
info "✅ Decryption successful: $output" info "✅ Decryption successful: $output"
else else
@@ -336,7 +446,61 @@ decrypt_file() {
fi fi
} }
# Main command dispatcher encrypt_text() {
local input_text="$1"
# 秘密鍵ファイルがある場合は check_ssh_agent をスキップ
local key_file="${NB_KEY_FILE:-${HOME}/.ssh/id_ed25519}"
if [ ! -f "$key_file" ]; then
check_ssh_agent
fi
info "Deriving encryption key..."
local key=$(derive_key)
if [ -z "$key" ]; then
error "Failed to derive encryption key"
fi
# 標準入力から読み取る場合
if [ "$input_text" = "-" ]; then
local temp_input=$(mktemp)
cat > "$temp_input"
input_text=$(cat "$temp_input")
rm -f "$temp_input"
fi
# OpenSSL で暗号化して Base64 エンコード
echo -n "$input_text" | openssl enc -aes-256-cbc -salt -pbkdf2 -pass "pass:$key" | base64 -w 0
echo "" # 改行を追加
}
decrypt_text() {
local input_text="$1"
# 秘密鍵ファイルがある場合は check_ssh_agent をスキップ
local key_file="${NB_KEY_FILE:-${HOME}/.ssh/id_ed25519}"
if [ ! -f "$key_file" ]; then
check_ssh_agent
fi
info "Deriving decryption key..."
local key=$(derive_key)
if [ -z "$key" ]; then
error "Failed to derive decryption key"
fi
# 標準入力から読み取る場合
if [ "$input_text" = "-" ]; then
input_text=$(cat)
fi
# Base64 デコードして OpenSSL で復号
echo -n "$input_text" | base64 -d 2>/dev/null | openssl enc -aes-256-cbc -d -salt -pbkdf2 -pass "pass:$key" 2>/dev/null || error "Decryption failed (wrong key or corrupted data)"
}
# メインのコマンド分岐
main() { main() {
if [ $# -eq 0 ]; then if [ $# -eq 0 ]; then
usage usage
@@ -345,24 +509,36 @@ main() {
local command="$1" local command="$1"
shift shift
# install-bws コマンドの場合は check_dependencies をスキップ # install-bws, keychain の場合は check_dependencies をスキップ
if [ "$command" != "install-bws" ] && [ "$command" != "help" ] && [ "$command" != "--help" ] && [ "$command" != "-h" ]; then if [ "$command" != "install-bws" ] && [ "$command" != "keychain" ] && [ "$command" != "help" ] && [ "$command" != "--help" ] && [ "$command" != "-h" ]; then
check_dependencies check_dependencies
fi fi
case "$command" in case "$command" in
encrypt) enc|enctext)
if [ $# -lt 1 ]; then
error "enc requires 1 argument: <text> or '-' for stdin"
fi
encrypt_text "${1:-}"
;;
dec|dectext)
if [ $# -lt 1 ]; then
error "dec requires 1 argument: <text> or '-' for stdin"
fi
decrypt_text "${1:-}"
;;
encfile|encrypt)
if [ $# -ne 2 ]; then if [ $# -ne 2 ]; then
error "encrypt requires 2 arguments: <input> <output>" error "encfile requires 2 arguments: <input> <output>"
fi fi
encrypt_file "$1" "$2" encrypt_file "$1" "$2"
;; ;;
decrypt) decfile|decrypt)
local force_mode=false local force_mode=false
local input="" local input=""
local output="" local output=""
# Parse arguments # 引数解析
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case "$1" in case "$1" in
-f|--force) -f|--force)
@@ -386,7 +562,7 @@ main() {
done done
if [ -z "$input" ] || [ -z "$output" ]; then if [ -z "$input" ] || [ -z "$output" ]; then
error "decrypt requires 2 arguments: <input> <output>" error "decfile requires 2 arguments: <input> <output>"
fi fi
decrypt_file "$force_mode" "$input" "$output" decrypt_file "$force_mode" "$input" "$output"
@@ -395,6 +571,24 @@ main() {
check_ssh_agent check_ssh_agent
echo "✅ All checks passed" echo "✅ All checks passed"
;; ;;
keychain)
local keep_mode=false
while [ $# -gt 0 ]; do
case "$1" in
-k|--keep)
keep_mode=true
shift
;;
-*)
error "Unknown option: $1"
;;
*)
error "keychain accepts only -k/--keep"
;;
esac
done
keychain_cmd "$keep_mode"
;;
install-bws) install-bws)
install_bws install_bws
;; ;;

Binary file not shown.