如何使用openssl生成ES256算法的JWT?现有生成命令输出无效令牌求解决
OpenSSL生成ES256签名JWT的问题排查与正确方案
现有命令的问题
- 待签名的JWT头和负载串本身非法:你提供的头base64url解码后不是合法JSON,负载部分也存在截断、JSON语法错误的问题,哪怕签名逻辑正确,生成的令牌本身也不符合JWT规范。
- ECDSA签名格式不匹配:这是最核心的问题。OpenSSL默认输出的ES256签名是ASN.1 DER编码格式,而JWT规范要求的ES256签名是32字节r值+32字节s值直接拼接的原始二进制格式,二者结构完全不同,所以生成的签名无法通过校验。
- 未校验密钥格式:需要确认你的
AuthKey_Q8KL9.pem是secp256r1(即prime256v1,ES256算法对应的标准椭圆曲线)格式的私钥,如果是其他曲线的密钥,签名也会无效。
正确的生成命令
首先预处理合法的JWT头和负载:
# 生成符合ES256规范的JWT头的base64url编码 header=$(echo -n '{"alg":"ES256","typ":"JWT"}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=') # 替换为你自己的业务负载,生成payload的base64url编码 payload=$(echo -n '{"iss":"6de76-6a61-47e3-e053-5b8c7c11a4d1","aud":"appstoreconnect-v1","iat":1630997711,"exp":1630999511}' | openssl base64 -e -A | tr '+/' '-_' | tr -d '=') # 拼接待签名的内容 signing_input="${header}.${payload}"
执行签名,额外做DER格式到r+s原始格式的转换:
signature=$(echo -n "${signing_input}" | openssl dgst -sha256 -binary -sign AuthKey_Q8KL9.pem \ | openssl asn1parse -inform DER | grep -A2 'INTEGER' | awk '{print $4}' | xxd -r -p | head -c 64 \ | openssl base64 -e -A | tr '+/' '-_' | tr -d '=')
最终拼接得到完整JWT:
jwt_token="${signing_input}.${signature}" echo ${jwt_token}
可选的签名校验步骤
如果需要本地验证生成的签名是否正确,可以先从私钥导出公钥:
openssl ec -in AuthKey_Q8KL9.pem -pubout -out pubkey.pem
再执行验证:
echo -n "${signing_input}" | openssl dgst -sha256 -verify pubkey.pem -signature <(echo "${signature}" | tr '_-' '/+' | base64 -d)
验证通过会输出Verified OK。
内容的提问来源于stack exchange,提问作者Krishna Chaitanya Chalavadi
相关产品推荐
相关产品推荐

