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

JavaScript生成的ECDSA签名在Java端验证失败该如何解决?

ECDSA签名跨Web Crypto与Java端验证失败的核心原因及解决方法

核心问题

最常见的原因是两端采用的ECDSA签名编码格式不兼容:

  • Web Crypto API调用sign方法生成的P-256 ECDSA签名默认是IEEE P1363格式:即长度固定的r、s两个大整数直接拼接,P-256对应的签名长度固定为64字节,前32字节是r值,后32字节是s值。
  • Java的SHA256withECDSA算法、绝大多数在线ECDSA验证工具默认接受的是DER编码的ASN.1 Sequence格式:会把r和s封装成ASN.1的序列结构,长度不固定,通常在70~72字节左右,开头有固定的0x30序列标识tag。你遇到的Sequence tag error异常就是验证时解析DER头未读到预期的0x30标识导致的。

其他可能的兼容问题

  • 公钥格式不匹配:Web Crypto导出公钥如果用raw格式是未压缩的65字节公钥(开头0x04 + 32字节x坐标 + 32字节y坐标),Java端如果用X509EncodedKeySpec读取公钥,需要的是SPKI格式的公钥,直接传raw格式公钥会解析失败。
  • 哈希计算逻辑不一致:需确认两端的消息编码完全一致,比如字符串是否统一用UTF-8编码转字节,有没有额外新增换行、空格等隐形字符。

解决方案

方案1:前端将P1363格式签名转成DER格式再传输

转换逻辑可以直接在前端实现,核心步骤:

  1. 把64字节的签名拆分为r(前32字节)、s(后32字节)两个独立字节数组
  2. 分别给r、s补前导0如果其最高位为1(ASN.1整数规范要求最高位为1时补0标识数值为正)
  3. 按照DER规范封装为Sequence结构:0x30 <总长度> 0x02 <r的长度> <r字节> 0x02 <s的长度> <s字节>

方案2:Java端指定使用P1363格式解析签名

Java 15及以上版本可以直接使用SHA256withECDSAinP1363Format算法名初始化Signature对象,不需要修改前端签名逻辑:

Signature sig = Signature.getInstance("SHA256withECDSAinP1363Format");

低版本Java可以引入BouncyCastle加密库,调用对应P1363格式的签名实现即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 00:36:05