java RSA SignatureException:签名长度不正确

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46225417/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 09:07:18  来源:igfitidea点击:

RSA SignatureException: Signature length not correct

javasecurityencryptionrsadigital-signature

提问by VMA92

I am having issues signing an rsa signature. I have a signature that has been encrypted with a private key. I have an issue when trying to validate it with the public key however. I get the following exception:

我在签署 rsa 签名时遇到问题。我有一个用私钥加密的签名。但是,我在尝试使用公钥对其进行验证时遇到问题。我收到以下异常:

java.security.SignatureException: Signature length not correct: got 336 but was expecting 128
    at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:189)
    at java.security.Signature$Delegate.engineVerify(Signature.java:1219)
    at java.security.Signature.verify(Signature.java:652)
    at XmlReader.main(XmlReader.java:65)

I have retrieved my signature and public key the following way:

我已通过以下方式检索了我的签名和公钥:

    BigInteger modulus = new BigInteger(Base64.getDecoder().decode(publicKeyString));
    BigInteger exponent = new BigInteger(Base64.getDecoder().decode("AQAB"));

    RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, exponent);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PublicKey pubKey = keyFactory.generatePublic(keySpec);

    byte[] sigToVerify = Base64.getDecoder().decode(signatureString);
    Signature sig = Signature.getInstance("MD5WithRSA");
    sig.initVerify(pubKey);
    boolean verifies = sig.verify(sigToVerify);

The application fails at the last line. Any thoughts as to where this exception is caused?

应用程序在最后一行失败。关于导致此异常的任何想法?

UPDATE:

更新:

Added data for signature to be verified:

添加待验证签名的数据:

        String data = "...." //hidden since sensitive data
        byte[] dataBytes = Base64.getEncoder().encode(data.getBytes());
        dataBytes = Base64.getDecoder().decode(dataBytes);

回答by algrid

Before calling sig.verify(sigToVerify)you should call

在打电话之前sig.verify(sigToVerify)你应该打电话

sig.update(data);

passing the data you're verifying signature for.

传递您正在验证签名的数据。

And make sure that calling verifyin your argument you have signature bytes only.

并确保verify在您的参数中调用您只有签名字节。

回答by Maarten Bodewes

Well, the signature size is obviously not correct. This means that at least the signature is not formatted correctly; an RSA signature by itself is always the size of the modulus in bytes (identical to the key size, in your case a short 1024 bit key).

好吧,签名大小显然不正确。这意味着至少签名格式不正确;RSA 签名本身总是以字节为单位的模数大小(与密钥大小相同,在您的情况下为 1024 位短密钥)。

algrid is rightthat usually you'd have to update the signature first. So it would be logical that the input of the signature is prefixed with the data that was signed. In that case the last 128 bytes are probably the signature, and the bytes before that are the data.

algrid 是对的,通常你必须先更新签名。因此,签名的输入以已签名的数据为前缀是合乎逻辑的。在这种情况下,最后 128 个字节可能是签名,而之前的字节是数据。

It is also possible that the signature is not a "raw" signature but a formatted signature, e.g. using the PKCS#7 / CMS syntax or PGP syntax. In that case you would need an library to decode it.

签名也可能不是“原始”签名而是格式化签名,例如使用 PKCS#7 / CMS 语法或 PGP 语法。在这种情况下,您需要一个库来解码它。

Note that you cannot verify a signature without the data that was signed, or at least the hash over the data. You can only check the correctness of the signature in that case (by validating the padding performed before modular exponentiation for RSA, in case we need to go into details).

请注意,如果没有签名的数据,或者至少是数据上的散列,则无法验证签名。在这种情况下,您只能检查签名的正确性(通过验证在 RSA 的模幂运算之前执行的填充,以防我们需要详细了解)。