亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

java.security.SignatureException:簽名編碼無效。

java.security.SignatureException:簽名編碼無效。

千巷貓影 2023-02-23 18:21:17
使用 Signature.verify 驗證簽名時,我收到“簽名的無效編碼”異常。使用 Azure 服務驗證相同簽名時,將驗證簽名。我有一個散列數據 (SHA-256)、一個公鑰和一個我要驗證的簽名。使用 com.microsoft.azure.keyvault.KeyVaultClient.sign 方法接收簽名,簽名算法為“ES256”。這有效(使用 ES256 算法):    com.microsoft.azure.keyvault.KeyVaultClient keyVaultClient;    String keyPairIdentifier;    boolean verify(byte[] hashData, byte[] signature, JsonWebKeySignatureAlgorithm signingAlgorithm) {        com.microsoft.azure.keyvault.models.KeyVerifyResult result = keyVaultClient.verify(keyPairIdentifier, signingAlgorithm, hashData, signature);        return result.value().booleanValue();    }這失敗了(證書持有存儲在 Azure keyvault 中的相同公鑰):    Signature ecdsaSign = Signature.getInstance("SHA256withECDSA");    ecdsaSign.initVerify(certificate.getPublicKey());    ecdsaSign.update(hashData);    ecdsaSign.verify(signature)預期結果 - true(簽名已驗證)實際結果:java.security.SignatureException: Could not verify signature    at sun.security.ec.ECDSASignature.engineVerify(ECDSASignature.java:325)    at java.security.Signature$Delegate.engineVerify(Signature.java:1222)    at java.security.Signature.verify(Signature.java:655)    at TestKV.KeyVault.VerifyDPSignature.verifySignatureUsingCertificate(VerifyDPSignature.java:143)    at TestKV.KeyVault.VerifyDPSignature.main(VerifyDPSignature.java:104)Caused by: java.security.SignatureException: Invalid encoding for signature    at sun.security.ec.ECDSASignature.decodeSignature(ECDSASignature.java:400)    at sun.security.ec.ECDSASignature.engineVerify(ECDSASignature.java:322)    ... 4 more Caused by: java.io.IOException: Sequence tag error    at sun.security.util.DerInputStream.getSequence(DerInputStream.java:330)    at sun.security.ec.ECDSASignature.decodeSignature (ECDSASignature.java:376)
查看完整描述

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簽名長度不一致如何指定簽名長度。

查看完整回答
反對 回復 2023-02-23
?
千萬里不及你

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);

格式更改后,我沒有得到“序列標記錯誤”異常。但是驗證還是失敗了。


查看完整回答
反對 回復 2023-02-23
?
精慕HU

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();



查看完整回答
反對 回復 2023-02-23
  • 3 回答
  • 0 關注
  • 1181 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號