SHA1 和 RSA 与 java.security.Signature 对比 MessageDigest 和 Ciph

Using SHA1 and RSA with java.security.Signature vs. MessageDigest and Cipher(SHA1 和 RSA 与 java.security.Signature 对比 MessageDigest 和 Cipher)
本文介绍了SHA1 和 RSA 与 java.security.Signature 对比 MessageDigest 和 Cipher的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我试图了解 Java java.security.Signature 类的作用.如果我计算一个 SHA1 消息摘要,然后使用 RSA 加密该摘要,我会得到与要求 Signature 类签署相同内容不同的结果:

I'm trying to understand what the Java java.security.Signature class does. If I compute an SHA1 message digest, and then encrypt that digest using RSA, I get a different result to asking the Signature class to sign the same thing:

// Generate new key
KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
String plaintext = "This is the message being signed";

// Compute signature
Signature instance = Signature.getInstance("SHA1withRSA");
instance.initSign(privateKey);
instance.update((plaintext).getBytes());
byte[] signature = instance.sign();

// Compute digest
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
byte[] digest = sha1.digest((plaintext).getBytes());

// Encrypt digest
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] cipherText = cipher.doFinal(digest);

// Display results
System.out.println("Input data: " + plaintext);
System.out.println("Digest: " + bytes2String(digest));
System.out.println("Cipher text: " + bytes2String(cipherText));
System.out.println("Signature: " + bytes2String(signature));

结果(例如):

输入数据:这是正在签名的消息
摘要:62b0a9ef15461c82766fb5bdaae9edbe4ac2e067
密文:057dc0d2f7f54acc95d3cf5cba9f944619394711003bdd12...
签名:7177c74bbbb871cc0af92e30d2808ebae146f25d3fd8ba1622...

Input data: This is the message being signed
Digest: 62b0a9ef15461c82766fb5bdaae9edbe4ac2e067
Cipher text: 057dc0d2f7f54acc95d3cf5cba9f944619394711003bdd12...
Signature: 7177c74bbbb871cc0af92e30d2808ebae146f25d3fd8ba1622...

我一定对 Signature 正在做的事情有一个根本性的误解 - 我已经对其进行了跟踪,它似乎正在对 MessageDigest 对象调用更新,其中如我所料,算法设置为 SHA1,然后获取摘要,然后进行加密.是什么导致结果不同?

I must have a fundamental misunderstanding of what Signature is doing - I've traced through it, and it appears to be calling update on a MessageDigest object, with the algorithm set to SHA1 as I would expect, then getting the digest, then doing the encryption. What's making the results differ?

Leonidas 让我检查签名方案是否应该按照我的想法去做.RFC 中定义了两种类型的签名:

Leonidas made me check whether the signature scheme is supposed to do what I think it does. There are two types of signature defined in the RFC:

  • RSSA-PKCS1-v1_5
  • RSSA-PSS

第一个 (PKCS1) 是我在上面描述.它使用哈希函数创建摘要,然后使用私钥对结果进行加密.

The first of these (PKCS1) is the one I describe above. It uses a hash function to create a digest, and then encrypts the result with a private key.

第二种算法使用随机盐值,并且更安全但不确定.如果重复使用相同的密钥,上面代码产生的签名不会改变,所以我认为它不可能是PSS.

The second algorithm uses a random salt value, and is more secure but non-deterministic. The signature produced from the code above does not change if the same key is used repeatedly, so I don't think it can be PSS.

这是我使用的 bytes2string 方法:

Here's the bytes2string method I was using:

private static String bytes2String(byte[] bytes) {
    StringBuilder string = new StringBuilder();
    for (byte b : bytes) {
        String hexString = Integer.toHexString(0x00FF & b);
        string.append(hexString.length() == 1 ? "0" + hexString : hexString);
    }
    return string.toString();
}

推荐答案

好的,我已经弄清楚发生了什么.Leonidas 是对的,它不仅仅是被加密的哈希(在 Cipher 类方法的情况下),它是与摘要连接的哈希算法的 ID:

OK, I've worked out what's going on. Leonidas is right, it's not just the hash that gets encrypted (in the case of the Cipher class method), it's the ID of the hash algorithm concatenated with the digest:

  DigestInfo ::= SEQUENCE {
      digestAlgorithm AlgorithmIdentifier,
      digest OCTET STRING
  }

这就是 Cipher 和 Signature 的加密方式不同的原因.

Which is why the encryption by the Cipher and Signature are different.

这篇关于SHA1 和 RSA 与 java.security.Signature 对比 MessageDigest 和 Cipher的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Reliable implementation of PBKDF2-HMAC-SHA256 for JAVA(PBKDF2-HMAC-SHA256 for JAVA 的可靠实现)
Correct way to sign and verify signature using bouncycastle(使用 bouncycastle 签名和验证签名的正确方法)
Creating RSA Public Key From String(从字符串创建 RSA 公钥)
Why java.security.NoSuchProviderException No such provider: BC?(为什么 java.security.NoSuchProviderException 没有这样的提供者:BC?)
Generating X509 Certificate using Bouncy Castle Java(使用 Bouncy Castle Java 生成 X509 证书)
How can I get a PublicKey object from EC public key bytes?(如何从 EC 公钥字节中获取 PublicKey 对象?)