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

Postman中ES512算法生成JWT验证不稳定问题排查

ES512 JWT签名验证不稳定问题排查与修复

问题根源

你遇到的验证成功率波动问题,核心原因是jsrsasign生成ES512签名时未严格遵循固定长度规范:

  • ES512基于secp521r1曲线,签名由两个521位整数r和s组成,每个整数必须用66字节的大端字节串表示(521位无法被8整除,需补位到66字节),因此完整签名长度固定为132字节。
  • jsrsasign的默认逻辑会自动省略r或s开头的空字节(当最高位为0时),导致签名长度偶尔变成130字节。而nimbus-jose-jwt库严格遵循规范,要求签名必须是132字节,这种短签名会直接验证失败。

是否错误使用jsrsasign?

不算完全错误,但该库的默认行为不符合部分严格实现的预期。ES512签名的编码规范要求必须保留补位的前导0,而jsrsasign省略了这部分,才导致兼容性问题。

修复方案:强制固定签名长度

修改你的signJwt函数,手动补全r和s的字节长度,确保签名始终为132字节:

function signJwt(payload, privateKey) {
  const alg = 'ES512';
  const header = {"alg": alg};
  const sHeader = JSON.stringify(header);
  const sPayload = JSON.stringify(payload);

  // 获取原始十六进制格式的签名(r+s拼接)
  const rawSignatureHex = KJUR.jws.JWS.sign(alg, sHeader, sPayload, privateKey, { format: 'raw' });

  // 拆分r和s,每个分量需占132个十六进制字符(对应66字节)
  let rHex = rawSignatureHex.slice(0, 132);
  let sHex = rawSignatureHex.slice(132);

  // 补前导0至132字符长度
  if (rHex.length < 132) {
    rHex = '0'.repeat(132 - rHex.length) + rHex;
  }
  if (sHex.length < 132) {
    sHex = '0'.repeat(132 - sHex.length) + sHex;
  }

  // 重新组合并转为Base64URL编码
  const fullSignatureHex = rHex + sHex;
  const signatureB64u = KJUR.util.b64utoutf8(KJUR.util.b64fromhex(fullSignatureHex));

  // 组装最终JWT
  const encodedHeader = KJUR.util.b64utoutf8(KJUR.util.b64fromstring(sHeader));
  const encodedPayload = KJUR.util.b64utoutf8(KJUR.util.b64fromstring(sPayload));
  
  return `${encodedHeader}.${encodedPayload}.${signatureB64u}`;
}

关于panva/jose库的问题

Postman预脚本环境不支持直接导入ES模块风格的库(panva/jose采用ES模块),若要使用需将其打包为UMD格式后,通过pm.globals.get导入执行,但步骤较繁琐。优先建议用上述方案修复jsrsasign的签名长度问题,成本更低。

内容的提问来源于stack exchange,提问作者user657009

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 04:02:02