diff --git a/nbcrypt b/nbcrypt index 71a77d5..4e196a0 100755 --- a/nbcrypt +++ b/nbcrypt @@ -4,9 +4,10 @@ set -euo pipefail # nbcrypt - SSH Agent ベースの暗号化/復号ツール # Ed25519 署名で決定的な鍵導出を行う # -# 環境変数: NB_SIGN_VIA_SSH, NB_SSH_PORT -# DevContainer 等で Agent が使えないとき、NB_SIGN_VIA_SSH=user@host を指定すると -# ホストの ~/.ssh/id_ed25519 で署名してもらう。NB_SSH_PORT でポート指定(未設定時 22)。 +# 重要: 単体動作を最優先する原則 +# - このスクリプトは extras/bootstrap の仕組みの中で単体処理として使われる +# - nbconf などの他の nbase2 ツールへの依存は避ける +# - 環境変数や kernel keyring などの標準的な仕組みのみを使用する SCRIPT_NAME="$(basename "$0")" KEY_SEED_MESSAGE="nbase2-secret-key-seed-v1" @@ -66,8 +67,7 @@ Text commands support stdin: echo "encrypted" | $SCRIPT_NAME dec - Requirements: - - SSH Agent with id_ed25519 key, or ~/.ssh/id_ed25519 file, or BWS_ACCESS_TOKEN, - or NB_SIGN_VIA_SSH (DevContainer: sign via host's ~/.ssh/id_ed25519; NB_SSH_PORT for port) + - SSH Agent with id_ed25519 key, or ~/.ssh/id_ed25519 file, or BWS_ACCESS_TOKEN - ssh-keygen and openssl commands must be available Examples: @@ -98,12 +98,7 @@ check_dependencies() { } get_bws_token() { - # 1. すでに環境変数にある - if [ -n "${BWS_ACCESS_TOKEN:-}" ]; then - echo "$BWS_ACCESS_TOKEN" - return 0 - fi - # 2. nbconf から取得を試みる + # 1. nbconf が利用可能な場合、nbconf から取得を試みる(keyring キャッシュも含む) local nbase_root="${NBASE_HOME:-$(cd "$(dirname "$0")/.." && pwd)}" local nbconf_cmd="${nbase_root}/bin/nbconf" if [ -f "$nbconf_cmd" ] && [ -x "$nbconf_cmd" ]; then @@ -114,6 +109,13 @@ get_bws_token() { return 0 fi fi + + # 2. すでに環境変数にある + if [ -n "${BWS_ACCESS_TOKEN:-}" ]; then + echo "$BWS_ACCESS_TOKEN" + return 0 + fi + return 1 } @@ -262,6 +264,33 @@ keychain_cmd() { print_source_agent_hint } +check_install_bws() { + # アーキテクチャチェック + local arch + arch=$(uname -m) + case "$arch" in + x86_64|aarch64|arm64) + ;; + *) + return 1 # サポートされていないアーキテクチャ + ;; + esac + + # wget または curl が利用可能か + if ! command -v wget >/dev/null 2>&1 && ! command -v curl >/dev/null 2>&1; then + return 1 + fi + + # unzip が利用可能か、またはインストール可能か + if ! command -v unzip >/dev/null 2>&1; then + if ! command -v apt-get >/dev/null 2>&1 && ! command -v yum >/dev/null 2>&1; then + return 1 + fi + fi + + return 0 +} + install_bws() { local arch arch=$(uname -m) @@ -319,7 +348,11 @@ install_bws() { derive_key() { # Ed25519 署名から暗号鍵を導出(同じメッセージなら同じ署名で決定的) - # 優先順位: 1. SSH Agent, 2. 秘密鍵ファイル, 3. NB_SIGN_VIA_SSH, 4. BWS (check_ssh_agent で処理) + # 優先順位: 1. SSH Agent, 2. 秘密鍵ファイル, 3. BWS (check_ssh_agent で処理) + local check_mode=false + if [ "${1:-}" = "--check" ]; then + check_mode=true + fi local temp_message=$(mktemp) local temp_sig=$(mktemp) @@ -335,13 +368,25 @@ derive_key() { ssh-add -L 2>/dev/null | grep "ssh-ed25519" | head -1 | awk '{print $1 " " $2}' > "$temp_pubkey" 2>/dev/null if [ -s "$temp_pubkey" ]; then # Agent から取得できた場合 - echo "key1 $(cat "$temp_pubkey")" > "$temp_allowed" + # key1 オプションなしで試す(ssh-keygen -Y sign は allowed_keys 形式のファイルを期待するが、key1 オプションがあると読み込めない場合がある) + cat "$temp_pubkey" > "$temp_allowed" # メッセージに署名(Agent経由) if ssh-keygen -Y sign -f "$temp_allowed" -n "nbase2" < "$temp_message" > "$temp_sig" 2>/dev/null; then + if [ "$check_mode" = "true" ]; then + info "Signature obtained from: SSH Agent" + fi # 署名を抜き出してハッシュし 256bit 鍵に cat "$temp_sig" | base64 -d 2>/dev/null | sha256sum | head -c 64 return 0 + else + if [ "$check_mode" = "true" ]; then + warn "Failed to sign with SSH Agent" + fi + fi + else + if [ "$check_mode" = "true" ]; then + warn "Failed to get Ed25519 key from SSH Agent" fi fi @@ -350,28 +395,37 @@ derive_key() { if [ -f "$key_file" ]; then # 公開鍵を抽出 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" - - # 秘密鍵ファイルを使って署名 + # 秘密鍵ファイルを使って署名(-f で秘密鍵ファイルを直接指定) if ssh-keygen -Y sign -f "$key_file" -n "nbase2" < "$temp_message" > "$temp_sig" 2>/dev/null; then + if [ "$check_mode" = "true" ]; then + info "Signature obtained from: id_ed25519" + fi # 署名を抜き出してハッシュし 256bit 鍵に cat "$temp_sig" | base64 -d 2>/dev/null | sha256sum | head -c 64 return 0 + else + if [ "$check_mode" = "true" ]; then + warn "Failed to sign with $key_file" + fi + fi + else + if [ "$check_mode" = "true" ]; then + warn "Failed to extract public key from $key_file" fi fi - fi - - # 3. ホスト SSH: NB_SIGN_VIA_SSH / NB_SSH_PORT(未設定時 nodoka@host.docker.internal:60516)で ~/.ssh/id_ed25519 に署名してもらう - if ssh -o BatchMode=yes -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new -p "${NB_SSH_PORT:-60516}" "${NB_SIGN_VIA_SSH:-nodoka@host.docker.internal}" 'echo -n "nbase2-secret-key-seed-v1" | ssh-keygen -Y sign -f ~/.ssh/id_ed25519 -n "nbase2"' > "$temp_sig" 2>/dev/null; then - _key=$(cat "$temp_sig" | base64 -d 2>/dev/null | sha256sum | head -c 64) - if [[ "${_key:-}" =~ ^[0-9a-f]{64}$ ]]; then - echo -n "$_key" - return 0 + else + if [ "$check_mode" = "true" ]; then + warn "Private key file not found: $key_file" fi fi - # 4. どれも失敗した場合、エラー(BWS は check_ssh_agent で処理される) - error "Could not derive key from SSH Agent, private key file, or host. Ensure SSH Agent has Ed25519, or set NB_KEY_FILE. Host: NB_SIGN_VIA_SSH/NB_SSH_PORT (default nodoka@host.docker.internal:60516)." + # 3. どれも失敗した場合、エラー(BWS は check_ssh_agent で処理される) + if [ "$check_mode" = "true" ]; then + warn "Could not derive key from SSH Agent or private key file. Ensure SSH Agent has Ed25519, or set NB_KEY_FILE." + return 1 + else + error "Could not derive key from SSH Agent or private key file. Ensure SSH Agent has Ed25519, or set NB_KEY_FILE." + fi } encrypt_file() { @@ -382,9 +436,9 @@ encrypt_file() { error "Input file not found: $input" fi - # 秘密鍵ファイルまたは NB_SIGN_VIA_SSH がある場合は check_ssh_agent をスキップ + # 秘密鍵ファイルがある場合は check_ssh_agent をスキップ local key_file="${NB_KEY_FILE:-${HOME}/.ssh/id_ed25519}" - if [ ! -f "$key_file" ] && [ -z "${NB_SIGN_VIA_SSH:-}" ]; then + if [ ! -f "$key_file" ]; then check_ssh_agent fi @@ -437,9 +491,9 @@ decrypt_file() { error "Ed25519 key not found in SSH Agent after BWS setup" fi else - # 秘密鍵ファイルまたは NB_SIGN_VIA_SSH がある場合は check_ssh_agent をスキップ + # 秘密鍵ファイルがある場合は check_ssh_agent をスキップ local key_file="${NB_KEY_FILE:-${HOME}/.ssh/id_ed25519}" - if [ ! -f "$key_file" ] && [ -z "${NB_SIGN_VIA_SSH:-}" ]; then + if [ ! -f "$key_file" ]; then check_ssh_agent fi fi @@ -464,9 +518,9 @@ decrypt_file() { encrypt_text() { local input_text="$1" - # 秘密鍵ファイルまたは NB_SIGN_VIA_SSH がある場合は check_ssh_agent をスキップ + # 秘密鍵ファイルがある場合は check_ssh_agent をスキップ local key_file="${NB_KEY_FILE:-${HOME}/.ssh/id_ed25519}" - if [ ! -f "$key_file" ] && [ -z "${NB_SIGN_VIA_SSH:-}" ]; then + if [ ! -f "$key_file" ]; then check_ssh_agent fi @@ -493,9 +547,9 @@ encrypt_text() { decrypt_text() { local input_text="$1" - # 秘密鍵ファイルまたは NB_SIGN_VIA_SSH がある場合は check_ssh_agent をスキップ + # 秘密鍵ファイルがある場合は check_ssh_agent をスキップ local key_file="${NB_KEY_FILE:-${HOME}/.ssh/id_ed25519}" - if [ ! -f "$key_file" ] && [ -z "${NB_SIGN_VIA_SSH:-}" ]; then + if [ ! -f "$key_file" ]; then check_ssh_agent fi @@ -583,8 +637,37 @@ main() { decrypt_file "$force_mode" "$input" "$output" ;; check) - check_ssh_agent - echo "✅ All checks passed" + info "Testing signature derivation..." + if derive_key --check >/dev/null; then + echo "✅ Signature derivation successful" + else + warn "All signature methods failed" + info "Checking BWS availability..." + + # bws コマンドが利用可能か + if command -v bws >/dev/null 2>&1; then + info "bws command is available" + else + if check_install_bws; then + info "bws can be installed (run 'nbcrypt install-bws')" + else + warn "bws installation is not possible" + fi + fi + + # BWS_ACCESS_TOKEN の取得を試みる + local bws_token + if bws_token=$(get_bws_token 2>/dev/null); then + info "BWS_ACCESS_TOKEN is available" + if command -v bws >/dev/null 2>&1; then + info "BWS setup is available. Run 'nbcrypt keychain' to set up SSH Agent." + else + info "BWS_ACCESS_TOKEN is available but bws command is not installed." + fi + else + warn "BWS_ACCESS_TOKEN is not available (checked: nbconf, environment variable)" + fi + fi ;; keychain) local keep_mode=false diff --git a/nbmain.sh.enc b/nbmain.sh.enc index 8441bb7..2a74878 100644 Binary files a/nbmain.sh.enc and b/nbmain.sh.enc differ