使用ECCP256签名的JWT无法在jwt.io验证的问题排查
问题根源与解决方案
你遇到的核心问题是EC签名格式不匹配:JWT的ES256算法要求签名采用原始(raw)格式(将签名的r和s分量各以32字节大端格式拼接,总长度64字节),但YubiKey和OpenSSL默认生成的是ASN.1/DER编码格式的签名,这种格式包含额外的标识符和长度字段,导致jwt.io无法识别验证。
验证问题点
你可以用以下命令查看签名的格式差异:
# 查看YubiKey生成的ASN.1签名结构 openssl asn1parse -inform DER -in data.sig
输出会显示ASN.1的嵌套结构,而非直接的r+s字节拼接内容。
修复步骤
需要把ASN.1编码的签名转换为JWT要求的原始格式,再进行base64url编码。
1. 修改YubiKey签名后的处理脚本
替换原脚本中签名拼接的部分:
# 将YubiKey生成的ASN.1签名转成raw格式 openssl asn1parse -inform DER -in data.sig -out raw_sig.tmp -noout # 提取r和s分量(跳过ASN.1头部,取第4字节开始的64字节) dd if=raw_sig.tmp of=raw_sig.bin bs=1 skip=4 count=64 2>/dev/null # 对raw签名进行base64url编码并拼接到JWT printf "." >> token.jwt cat raw_sig.bin | base64 | tr -d '\n=' | tr '+/' '-_' >> token.jwt # 清理临时文件 rm raw_sig.tmp raw_sig.bin
2. 修改OpenSSL签名的处理脚本
生成签名后同样需要转成raw格式:
# 生成ASN.1签名后,转成raw格式 openssl dgst -sha256 -sign private.pem token.jwt > signature.asn1 openssl asn1parse -inform DER -in signature.asn1 -out raw_sig.tmp -noout dd if=raw_sig.tmp of=raw_sig.bin bs=1 skip=4 count=64 2>/dev/null # 拼接JWT printf "." >> token.jwt cat raw_sig.bin | base64 | tr -d '\n=' | tr '+/' '-_' >> token.jwt rm signature.asn1 raw_sig.tmp raw_sig.bin
为什么RSA没有问题?
RS256算法的签名格式本身就是PKCS#1 v1.5编码,JWT标准直接支持这种格式,因此不需要额外转换。
内容的提问来源于stack exchange,提问作者Luhko
相关产品推荐
相关产品推荐

