【问题标题】:RSA java signature verification failedRSA java签名验证失败
【发布时间】:2023-03-06 11:06:01
【问题描述】:

这可能与以下内容重复: Java Signature.verify results in SignatureException: Signature encoding error Caused by IOException: Sequence tag error ,但答案没有回答我的问题。

有这个代码:

String RSA_CIPHER_ALGORITHM = "RSA/ECB/PKCS1Padding";
String RSA_KEY_FACTORY_ALGORITHM = "RSA";
String RSA_SIGNATURE_ALGORITHM = "SHA512withRSA";

KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_FACTORY_ALGORITHM);
RSAPublicKey key = (RSAPublicKey)keyFactory.generatePublic(pubKeySpec);

Signature signature = Signature.getInstance(RSA_SIGNATURE_ALGORITHM);
signature.initVerify(key);
signature.update(data);

有这个错误:

java.security.SignatureException: Signature encoding error
at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:204)
at java.security.Signature$Delegate.engineVerify(Signature.java:1219)
at java.security.Signature.verify(Signature.java:652)

...

Caused by: java.io.IOException: Sequence tag error
at sun.security.util.DerInputStream.getSequence(DerInputStream.java:297)
at sun.security.rsa.RSASignature.decodeSignature(RSASignature.java:229)
at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:195)
... 45 common frames omitted

【问题讨论】:

    标签: java rsa digital-signature


    【解决方案1】:

    当您的签名确实包含 PKCS#1 compatible padding(第 4 步和第 5 步),但它不包含所用哈希方法的 DER 编码标识符时,通常会发生这种情况。此编码标识符以一个代表 ASN.1 SEQUENCE 的 DER 标签开头(第 1 步和第 2 步)。

    您可以使用原始 RSA 密码查看编码:

    // setup
    Signature sigAlg = Signature.getInstance("SHA512withRSA");
    sigAlg.initSign(keyPair.getPrivate());
    byte[] signature = sigAlg.sign();
    
    // check padding manually
    Cipher rsaRaw = Cipher.getInstance("RSA/ECB/NoPadding");
    // encrypt or decrypt is actually the same operation for raw RSA
    rsaRaw.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
    byte[] paddedSig = rsaRaw.doFinal(signature);
    // using Bouncy Castle's hex encoder, you can use any encoder
    System.out.println(Hex.toHexString(paddedSig));
    

    然后您实际上可以看到序列字节(值30,在一大堆FF 字节(填充)和一个值00 的单个字节之后。如果它当然是一个有效的签名:

    0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003051300d060960864801650304020305000440cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e
    

    您可能只会得到代表哈希值的 64 个字节。

    【讨论】:

    • 我可以对传入的签名做些什么来使其正常工作?
    • 踢给你签名的人,让他使用有效且正确的签名格式。或者,如果他们坚持向您发送不正确的值:使用 "RSA/ECB/NoPadding" 并自己提取哈希值。然后与计算的哈希值进行比较。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-22
    • 1970-01-01
    • 1970-01-01
    • 2016-12-27
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多