3 回答
TA贡献2003条经验 获得超2个赞
Azure 的 JWS只是连接固定大小的 r 和 s 的 I2OSP,但 Java JCE 与大多数但不是所有标准一样,使用 ASN.1 DER 编码,例如 rfc3279(注意:现在有用于 ECDSA 的 OID 和其他哈希值)。
要将 JWS/plain 转换为 DER,请参阅我的(交叉)https://security.stackexchange.com/questions/174095/convert-ecdsa-signature-from-plain-to-der-format以获得 C 方法,但 Java 使它更容易,因为BigInteger
为你做了一半的工作:
// byte[64] plain contains the JWS-style r,s (de-base64-ed if necessary)
byte[] r = new BigInteger(1,Arrays.copyOfRange(plain,0,32)).toByteArray();
byte[] s = new BigInteger(1,Arrays.copyOfRange(plain,32,64)).toByteArray();
byte[] der = new byte[6+r.length+s.length]; der[0] = 0x30; der[1] = der.length-2; int o = 2;
der[o++] = 2; der[o++] = (byte)r.length; System.arraycopy (r,0, der,o, r.length); o+=r.length;
der[o++] = 2; der[o++] = (byte)s.length; System.arraycopy (s,0, der,o, s.length); //o+=s.length;
更正并添加: Java 9 向上也使用诸如 之类的算法名称直接处理此问题SHA256withECDSAinP1363format
,并且在所有版本的 Java 上,如果您添加 BouncyCastle,它会使用诸如SHA256withPLAIN-ECDSA
或 之类的名称来处理此问题SHA256withCVC-ECDSA
。看java.security.Signature签名方法和Java ECDSAwithSHA256签名长度不一致如何指定签名长度。
TA贡献1784条经验 获得超9个赞
dave_thompson_085 - 谢谢!你附上的代码有一些错误,签名部分的标签应该是0x02,而不是0x30,而且你复制第一部分后没有增加o。这是更改后的代码:
byte[] r = new BigInteger(1,Arrays.copyOfRange(signature,0,32)).toByteArray();
byte[] s = new BigInteger(1,Arrays.copyOfRange(signature,32,64)).toByteArray();
byte[] der = new byte[6+r.length+s.length];
der[0] = 0x30; // Tag of signature object
der[1] = (byte)(der.length-2); // Length of signature object
int o = 2;
der[o++] = 0x02; // Tag of ASN1 Integer
der[o++] = (byte)r.length; // Length of first signature part
System.arraycopy (r,0, der,o, r.length);
o += r.length;
der[o++] = 0x02; // Tag of ASN1 Integer
der[o++] = (byte)s.length; // Length of second signature part
System.arraycopy (s,0, der,o, s.length);
格式更改后,我没有得到“序列标记错误”异常。但是验证还是失败了。
TA贡献1845条经验 获得超8个赞
在我的例子中,我只需要先将签名的原始字节解码为 Base64。
byte[] signatureBytes = Base64.getDecoder().decode(signature.getBytes());
byte[] r = new BigInteger(1,Arrays.copyOfRange(signatureBytes,0,32)).toByteArray();
byte[] s = new BigInteger(1,Arrays.copyOfRange(signatureBytes,32,64)).toByteArray();
添加回答
举报