signature.verify() 总是返回 False

发布于 2024-09-07 20:48:23 字数 1976 浏览 1 评论 0原文

 public static void main(String[] args) {
    try{
        String mod = "q0AwozeUj0VVkoksDQSCTj3QEgODomq4sAr02xMyIrWldZrNHhWfZAIcWt2MuAY3X6S3ZVUfOFXOrVbltRrO3F9Z6R8/jJIMv7wjkeVBFC5gncwGR0C3aV9gmF6II19jTKfF1sxb26iMEMAlMEOSnAAceNaJH91zBoaW7ZIh+qk=";
        String exp = "AQAB";
        byte[] modulusBytes = Base64.decodeBase64(mod.getBytes("UTF-8"));
        byte[] exponentBytes = Base64.decodeBase64(exp.getBytes("UTF-8"));
        String signedMessage = "3753e672cfb21e3c182ef2df51f19edeffb63432ed338a47251326ccc14aa63883e910a140cf313754ebc6425aad434e309307cc882da6cd4a4f9f40bd14a9823aca145e5ffc97cd63dbb5925c049282416bdfd7d74ddeef7055065210a841793fe315dff5a44af19c1522daafdc2f7e61ce5a2b42ebf79dfb086e6d210168dd";
        BigInteger modulus = new BigInteger(1, modulusBytes );               
        BigInteger exponent = new BigInteger(1, exponentBytes);
        RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, exponent);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        PublicKey pubKey = fact.generatePublic(rsaPubKey);
        Signature signature = Signature.getInstance("SHA1withRSA");
        byte[] sigBytes = hexStringToByteArray(signedMessage);
        signature.initVerify(pubKey);
        System.out.println(signature.verify(sigBytes));
    }catch(Exception e){
        System.out.println("Error: " + e.toString());
    }
}
private static byte[] hexStringToByteArray(final String encoded) {
    if ((encoded.length() % 2) != 0)
        throw new IllegalArgumentException("Input string must contain an even number of characters");

    final byte result[] = new byte[encoded.length()/2];
    final char enc[] = encoded.toCharArray();
    for (int i = 0; i < enc.length; i += 2) {
        StringBuilder curr = new StringBuilder(2);
        curr.append(enc[i]).append(enc[i + 1]);
        result[i/2] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}

此代码始终返回 false。我不知道从这里该去哪里。

 public static void main(String[] args) {
    try{
        String mod = "q0AwozeUj0VVkoksDQSCTj3QEgODomq4sAr02xMyIrWldZrNHhWfZAIcWt2MuAY3X6S3ZVUfOFXOrVbltRrO3F9Z6R8/jJIMv7wjkeVBFC5gncwGR0C3aV9gmF6II19jTKfF1sxb26iMEMAlMEOSnAAceNaJH91zBoaW7ZIh+qk=";
        String exp = "AQAB";
        byte[] modulusBytes = Base64.decodeBase64(mod.getBytes("UTF-8"));
        byte[] exponentBytes = Base64.decodeBase64(exp.getBytes("UTF-8"));
        String signedMessage = "3753e672cfb21e3c182ef2df51f19edeffb63432ed338a47251326ccc14aa63883e910a140cf313754ebc6425aad434e309307cc882da6cd4a4f9f40bd14a9823aca145e5ffc97cd63dbb5925c049282416bdfd7d74ddeef7055065210a841793fe315dff5a44af19c1522daafdc2f7e61ce5a2b42ebf79dfb086e6d210168dd";
        BigInteger modulus = new BigInteger(1, modulusBytes );               
        BigInteger exponent = new BigInteger(1, exponentBytes);
        RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, exponent);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        PublicKey pubKey = fact.generatePublic(rsaPubKey);
        Signature signature = Signature.getInstance("SHA1withRSA");
        byte[] sigBytes = hexStringToByteArray(signedMessage);
        signature.initVerify(pubKey);
        System.out.println(signature.verify(sigBytes));
    }catch(Exception e){
        System.out.println("Error: " + e.toString());
    }
}
private static byte[] hexStringToByteArray(final String encoded) {
    if ((encoded.length() % 2) != 0)
        throw new IllegalArgumentException("Input string must contain an even number of characters");

    final byte result[] = new byte[encoded.length()/2];
    final char enc[] = encoded.toCharArray();
    for (int i = 0; i < enc.length; i += 2) {
        StringBuilder curr = new StringBuilder(2);
        curr.append(enc[i]).append(enc[i + 1]);
        result[i/2] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}

This code always returns false. I'm not sure where to go from here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

素罗衫 2024-09-14 20:48:23

在对消息进行签名的地方,您应该有一些如下所示的代码:

Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(privKey);
signature.update(message);
byte[] signatureValue = signature.sign();

注意名为 signatureValue 的字节数组。这是数据上的实际签名。这就是您应该提供给 verify() 方法的内容。已签名的消息应在对 update() 方法的调用中提供。 IE:

Signature signature = Signature.getInstance("SHA1withRSA");
signature.initVerify(pubKey);
signature.update(message);
bool ok = signature.verify(signatureValue);

Where you sign the message you should have some code like this:

Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(privKey);
signature.update(message);
byte[] signatureValue = signature.sign();

Note the byte-array named signatureValue. That is the actual signature on the data. That is what you should provide to the verify()-method. The message that is signed should be provided in a call to the update()-method. I.e.:

Signature signature = Signature.getInstance("SHA1withRSA");
signature.initVerify(pubKey);
signature.update(message);
bool ok = signature.verify(signatureValue);
七禾 2024-09-14 20:48:23

我认为问题在于你实际上并没有给它一个消息来验证。

RSA 签名的工作原理是首先对消息进行哈希处理(即“SHA1withRSA”中的“SHA1”),然后执行 活板门操作。这是一种在一个方向上很容易执行而在另一个方向上很难执行的操作,除非您知道一些秘密信息(RSA 私钥)。

为了进行验证,您首先要反转数学变换(因为它在一个方向上很容易),然后将签名中嵌入的哈希值与您刚刚计算的消息的哈希值进行比较。签名本身并不包含消息;要验证签名,您需要签名和已签名的消息。

API 级别,它看起来像Signature 类期望您使用此签名所针对的消息内容调用 update。如果没有这个,它可能会将哈希值与空字符串的哈希值进行比较,因此除非您最初签名的消息也是空字符串,否则签名实际上无效。

I think the problem is that you are not actually giving it a message to verify.

An RSA signature works by first hashing the message (that's the "SHA1" in "SHA1withRSA"), and then performing an trapdoor operation to it. This is an operation which is easy to do in one direction and hard in the other direction, unless you know some secret information (the RSA private key).

To verify, you first invert the mathematical transformation (because it's easy in one direction), and then compare the hash that is embedded in the signature with the hash of the message you just computed. The signature does not in itself contain the message; to verify a signature you need both the signature and the message that was signed.

At an API level, it looks like the Signature class is expecting you to call update with the contents of the message that this signature was for. Without this, it probably is comparing the hash with the hash of an empty string, so unless your originally signed message was also an empty string, the signature is in fact not valid.

洋洋洒洒 2024-09-14 20:48:23

你是对的,谢谢杰克。下面的方法完美地工作(即使使用在 .NET 中创建的密钥)!我希望这对其他人有帮助。

public static void main(String[] args) {
    try{
        String userID = "189711";
        String companyCode = "ILIKEPIZZA";
        String combine = userID + "." + companyCode;
        String mod = "q0AwozeUj0VVkoksDQSCTj3QEgODomq4sAr02xMyIrWldZrNHhWfZAIcWt2MuAY3X6S3ZVUfOFXOrVbltRrO3F9Z6R8/jJIMv7wjkeVBFC5gncwGR0C3aV9gmF6II19jTKfF1sxb26iMEMAlMEOSnAAceNaJH91zBoaW7ZIh+qk=";
        String exp = "AQAB";
        byte[] modulusBytes = Base64.decodeBase64(mod.getBytes("UTF-8"));
        byte[] exponentBytes = Base64.decodeBase64(exp.getBytes("UTF-8"));
        String sign = "3753e672cfb21e3c182ef2df51f19edeffb63432ed338a47251326ccc14aa63883e910a140cf313754ebc6425aad434e309307cc882da6cd4a4f9f40bd14a9823aca145e5ffc97cd63dbb5925c049282416bdfd7d74ddeef7055065210a841793fe315dff5a44af19c1522daafdc2f7e61ce5a2b42ebf79dfb086e6d210168dd";
        BigInteger modulus = new BigInteger(1, modulusBytes );               
        BigInteger exponent = new BigInteger(1, exponentBytes);
        RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, exponent);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        PublicKey pubKey = fact.generatePublic(rsaPubKey);
        Signature signature = Signature.getInstance("SHA1withRSA");
        byte[] sigBytes = hexStringToByteArray(sign);
        signature.initVerify(pubKey);
        signature.update(combine.getBytes("UTF-8"));
        System.out.println(signature.verify(sigBytes));
    }catch(Exception e){
        System.out.println("Error: " + e.toString());
    }
}

You were right, thanks Jack. The below method works perfectly (even with a key created in .NET)! I hope this helps others.

public static void main(String[] args) {
    try{
        String userID = "189711";
        String companyCode = "ILIKEPIZZA";
        String combine = userID + "." + companyCode;
        String mod = "q0AwozeUj0VVkoksDQSCTj3QEgODomq4sAr02xMyIrWldZrNHhWfZAIcWt2MuAY3X6S3ZVUfOFXOrVbltRrO3F9Z6R8/jJIMv7wjkeVBFC5gncwGR0C3aV9gmF6II19jTKfF1sxb26iMEMAlMEOSnAAceNaJH91zBoaW7ZIh+qk=";
        String exp = "AQAB";
        byte[] modulusBytes = Base64.decodeBase64(mod.getBytes("UTF-8"));
        byte[] exponentBytes = Base64.decodeBase64(exp.getBytes("UTF-8"));
        String sign = "3753e672cfb21e3c182ef2df51f19edeffb63432ed338a47251326ccc14aa63883e910a140cf313754ebc6425aad434e309307cc882da6cd4a4f9f40bd14a9823aca145e5ffc97cd63dbb5925c049282416bdfd7d74ddeef7055065210a841793fe315dff5a44af19c1522daafdc2f7e61ce5a2b42ebf79dfb086e6d210168dd";
        BigInteger modulus = new BigInteger(1, modulusBytes );               
        BigInteger exponent = new BigInteger(1, exponentBytes);
        RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, exponent);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        PublicKey pubKey = fact.generatePublic(rsaPubKey);
        Signature signature = Signature.getInstance("SHA1withRSA");
        byte[] sigBytes = hexStringToByteArray(sign);
        signature.initVerify(pubKey);
        signature.update(combine.getBytes("UTF-8"));
        System.out.println(signature.verify(sigBytes));
    }catch(Exception e){
        System.out.println("Error: " + e.toString());
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文