问题在于 JavaCard 和 BouncyCastle 使用不同格式的生成签名。例如,对于 Prime192v1 曲线,生成的 JavaCard 签名始终为 56 字节长,但 Bouncy Castle 签名有时更短,因为它省略了 EC 点坐标中的前导零。
JavaCard 签名(同样适用于 Prime192v1)的十六进制格式如下所示:
30 36 02 19 [25 bytes of the first coord] 02 19 [25 bytes of the second coord]
(它是 DER 编码结构:两个 INTEGER 的 SEQUENCE)
然而,BouncyCastle 预计 EC 坐标中不会出现这些零。所以你必须删除它们并修复 DER 结构,例如
30 36 02 19 **00 00** [the rest 23 bytes of the first coord] 02 19 **00** [24 bytes of the second coord]
Bouncy Castle 必须将 JavaCard 转换为:
30 **33** 02 **17** [23 bytes of the first coord] 02 **18** [24 bytes of the second coord]
有时您正确验证签名的原因很简单:有时 JavaCard 签名坐标中没有前导零。
编辑:受到 TajnosAgentos 观察的启发:
BouncyCastle 将坐标编码为有符号整数,JavaCard 始终将坐标编码为无符号整数。这就是为什么只要第一个字节的最高有效位为 1,BouncyCastle 就会添加一个特殊的前导零(尽管它会修剪其他前导零),因为坐标始终是正数。