BASH脚本生成ES256 JWT无效,Ruby脚本正常,求修复签名问题
修复Bash脚本生成App Store Connect API的ES256 JWT令牌
问题根源
你的Bash脚本中,OpenSSL默认生成的ECDSA签名是ASN.1/DER编码格式,但JWT规范要求ES256签名必须是原始的r和s值拼接的二进制格式(每个值32字节,共64字节)。Ruby的jwt库自动处理了这个格式转换,而Bash脚本直接使用OpenSSL的签名输出,导致格式不匹配,令牌无效。
修复后的Bash脚本
#!/bin/bash # Check if required tools are installed if ! command -v openssl > /dev/null; then echo "Error: openssl not found. Please install openssl." exit 1 fi # Replace with your actual values key_id="MCHQZ23JLZ" p8_file="AuthKey_${key_id}.p8" issuer_id="69a6de92-655f-47e3-e053-5b8c7c11a4d1" expiration_time=$(( $(date '+%s') + 1200 )) # Token expires in 20 mins # Create the header and payload header='{"kid":"'$key_id'","typ":"JWT","alg":"ES256"}' payload='{"iss":"'$issuer_id'","exp":'$expiration_time',"aud":"appstoreconnect-v1"}' # Encode the header and payload to base64url encoded_header=$(echo -n "$header" | base64 | tr -d '\n=' | tr '/+' '_-') encoded_payload=$(echo -n "$payload" | base64 | tr -d '\n=' | tr '/+' '_-') # Generate ASN.1/DER signature der_signature=$(echo -n "$encoded_header.$encoded_payload" | openssl dgst -binary -sha256 -sign "$p8_file") # Convert DER signature to raw r + s format (64 bytes total) # 1. Parse DER to extract r and s values r_hex=$(echo "$der_signature" | openssl asn1parse -inform der -i | grep -A 1 "INTEGER :" | tail -1 | awk '{print $4}') s_hex=$(echo "$der_signature" | openssl asn1parse -inform der -i | grep -A 3 "INTEGER :" | tail -1 | awk '{print $4}') # 2. Pad r and s to 32 bytes (64 hex chars) r_padded=$(printf "%064s" "$r_hex" | tr ' ' '0') s_padded=$(printf "%064s" "$s_hex" | tr ' ' '0') # 3. Convert padded hex to binary, then base64url encode raw_signature=$(echo -n "$r_padded$s_padded" | xxd -r -p) signature=$(echo -n "$raw_signature" | base64 | tr -d '\n=' | tr '/+' '_-') # Combine into JWT token jwt_token="$encoded_header.$encoded_payload.$signature" echo "JWT Token: $jwt_token"
关键修复点说明
- 解析DER签名:通过
openssl asn1parse提取DER格式中r和s两个整数的十六进制值 - 补全长度:ECDSA的r和s必须是32字节(64位十六进制),原始值长度不足时在前面补0
- 转换为原始格式:将补全后的r和s十六进制拼接,转成二进制后再做base64url编码,得到符合JWT要求的签名
验证方法
可以用JWT解码工具(如jwt命令行工具)对比Ruby和修复后Bash脚本生成的令牌:
- 确认header和payload完全一致
- 检查签名部分的格式是否符合ES256的r+s拼接要求
内容的提问来源于stack exchange,提问作者esbenr
相关产品推荐
相关产品推荐

