From 93c658d9145f15cff7059dba6ef4080a2d46a657 Mon Sep 17 00:00:00 2001 From: hailin Date: Mon, 15 Dec 2025 08:52:40 -0800 Subject: [PATCH] =?UTF-8?q?fix(scripts):=20=E6=B7=BB=E5=8A=A0=20JWT=20?= =?UTF-8?q?=E8=AE=A4=E8=AF=81=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mpc-system account-service 需要 JWT 认证,脚本需要: - 添加 --jwt-secret 参数或从 MPC_JWT_SECRET 环境变量读取 - 使用 openssl 生成 HS256 JWT token - 所有 API 请求添加 Authorization: Bearer header 用法: export MPC_JWT_SECRET='your_secret' ./init-hot-wallet.sh --username rwadurian-system-hot-wallet-01 --threshold-n 3 --threshold-t 2 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- backend/scripts/init-hot-wallet.sh | 63 +++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/backend/scripts/init-hot-wallet.sh b/backend/scripts/init-hot-wallet.sh index 50cd09ed..7021fec4 100644 --- a/backend/scripts/init-hot-wallet.sh +++ b/backend/scripts/init-hot-wallet.sh @@ -10,11 +10,13 @@ # 2. mpc-system session-coordinator 和 server-party 已启动 # 3. jq 已安装 (用于解析 JSON) # 4. curl 已安装 +# 5. 环境变量 MPC_JWT_SECRET 已设置(或通过 --jwt-secret 参数传入) # # 使用方法: -# ./init-hot-wallet.sh --username --threshold-n --threshold-t +# ./init-hot-wallet.sh --username --threshold-n --threshold-t [--jwt-secret ] # # 示例: +# export MPC_JWT_SECRET="your_jwt_secret_key" # ./init-hot-wallet.sh --username rwadurian-system-hot-wallet-01 --threshold-n 3 --threshold-t 2 # # ============================================================================= @@ -34,6 +36,7 @@ USERNAME="" THRESHOLD_N=3 THRESHOLD_T=2 MPC_HOST="http://localhost:4000" +JWT_SECRET="${MPC_JWT_SECRET:-}" VERBOSE=true # 日志函数 @@ -59,6 +62,28 @@ log_debug() { fi } +# 生成 JWT Token (简化版,用于 MPC 系统认证) +# 使用 openssl + base64 生成 HS256 JWT +generate_jwt_token() { + local secret="$1" + local now=$(date +%s) + local exp=$((now + 86400)) # 24小时后过期 + local jti=$(cat /proc/sys/kernel/random/uuid 2>/dev/null || uuidgen 2>/dev/null || echo "$(date +%s)-$$") + + # JWT Header + local header='{"alg":"HS256","typ":"JWT"}' + local header_b64=$(echo -n "$header" | base64 -w0 | tr '+/' '-_' | tr -d '=') + + # JWT Payload + local payload="{\"jti\":\"$jti\",\"iss\":\"init-script\",\"sub\":\"system\",\"party_id\":\"init-script\",\"token_type\":\"access\",\"iat\":$now,\"nbf\":$now,\"exp\":$exp}" + local payload_b64=$(echo -n "$payload" | base64 -w0 | tr '+/' '-_' | tr -d '=') + + # JWT Signature (HMAC-SHA256) + local signature=$(echo -n "${header_b64}.${payload_b64}" | openssl dgst -sha256 -hmac "$secret" -binary | base64 -w0 | tr '+/' '-_' | tr -d '=') + + echo "${header_b64}.${payload_b64}.${signature}" +} + # 检查依赖 check_dependencies() { log_info "检查依赖..." @@ -78,6 +103,12 @@ check_dependencies() { fi log_debug "✓ jq 已安装" + if ! command -v openssl &> /dev/null; then + log_error "openssl 未安装,请先安装 openssl" + exit 1 + fi + log_debug "✓ openssl 已安装" + log_success "依赖检查通过" } @@ -129,9 +160,13 @@ parse_args() { THRESHOLD_T="$2" shift 2 ;; + --jwt-secret) + JWT_SECRET="$2" + shift 2 + ;; *) log_error "未知参数: $1" - echo "用法: ./init-hot-wallet.sh --username --threshold-n --threshold-t " + echo "用法: ./init-hot-wallet.sh --username --threshold-n --threshold-t [--jwt-secret ]" exit 1 ;; esac @@ -143,11 +178,20 @@ validate_params() { if [ -z "$USERNAME" ]; then log_error "用户名不能为空" echo "" - echo "用法: ./init-hot-wallet.sh --username --threshold-n --threshold-t " + echo "用法: ./init-hot-wallet.sh --username --threshold-n --threshold-t [--jwt-secret ]" echo "示例: ./init-hot-wallet.sh --username rwadurian-system-hot-wallet-01 --threshold-n 3 --threshold-t 2" exit 1 fi + if [ -z "$JWT_SECRET" ]; then + log_error "JWT_SECRET 不能为空" + echo "" + echo "请通过以下方式之一提供 JWT_SECRET:" + echo " 1. 设置环境变量: export MPC_JWT_SECRET='your_secret'" + echo " 2. 命令行参数: --jwt-secret 'your_secret'" + exit 1 + fi + if [ "$THRESHOLD_N" -lt 2 ]; then log_error "总 party 数量 (threshold-n) 必须 >= 2" exit 1 @@ -164,6 +208,10 @@ validate_params() { create_keygen_session() { log_info "创建 Keygen 会话..." + # 生成 JWT Token + local jwt_token=$(generate_jwt_token "$JWT_SECRET") + log_debug "JWT Token: ${jwt_token:0:50}..." + local url="$MPC_HOST/api/v1/mpc/keygen" # mpc-system 使用 snake_case: threshold_n, threshold_t, require_delegate local payload="{ @@ -178,6 +226,7 @@ create_keygen_session() { KEYGEN_RESPONSE=$(curl -s -X POST "$url" \ -H "Content-Type: application/json" \ + -H "Authorization: Bearer $jwt_token" \ -d "$payload" \ --connect-timeout 30 \ --max-time 60) @@ -220,6 +269,9 @@ wait_for_keygen() { log_info "等待 Keygen 完成 (最多 6 分钟)..." echo "" + # 生成 JWT Token + local jwt_token=$(generate_jwt_token "$JWT_SECRET") + local max_attempts=180 # 6 分钟 (每 2 秒轮询一次) local attempt=0 local last_status="" @@ -229,7 +281,7 @@ wait_for_keygen() { while [ $attempt -lt $max_attempts ]; do # mpc-system 状态查询 API: /api/v1/mpc/sessions/{sessionId} local url="$MPC_HOST/api/v1/mpc/sessions/$SESSION_ID" - STATUS_RESPONSE=$(curl -s -X GET "$url" --connect-timeout 10) + STATUS_RESPONSE=$(curl -s -X GET "$url" -H "Authorization: Bearer $jwt_token" --connect-timeout 10) log_debug "轮询响应: $STATUS_RESPONSE" @@ -284,8 +336,9 @@ get_public_key() { if [ -z "$PUBLIC_KEY" ] || [ "$PUBLIC_KEY" == "null" ]; then # 再次获取状态以确保拿到公钥 + local jwt_token=$(generate_jwt_token "$JWT_SECRET") local url="$MPC_HOST/api/v1/mpc/sessions/$SESSION_ID" - STATUS_RESPONSE=$(curl -s -X GET "$url") + STATUS_RESPONSE=$(curl -s -X GET "$url" -H "Authorization: Bearer $jwt_token") PUBLIC_KEY=$(echo "$STATUS_RESPONSE" | jq -r '.public_key') fi