You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 20:01:05