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
??磈ava.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();
添加回答
舉報