当前位置:  开发笔记 > 编程语言 > 正文

将SHA1和RSA与java.security.Signature与MessageDigest和Cipher一起使用

如何解决《将SHA1和RSA与java.security.Signature与MessageDigest和Cipher一起使用》经验,为你挑选了2个好方法。

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

// 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 ...

我必须对Signature正在做的事情有一个基本的误解- 我已经跟踪了它,它似乎是在MessageDigest对象上调用update ,算法设置为SHA1,正如我所期望的那样,然后获取摘要,然后执行加密.是什么让结果有所不同?

编辑:

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

RSASSA-PKCS1-v1_5中

RSASSA-PSS

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

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

编辑:

这是bytes2string我使用的方法:

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

Mike Houston.. 52

好的,我已经知道发生了什么.我当时很蠢.Leonidas是对的,它不仅仅是加密的哈希,它是与摘要连接的哈希算法的ID:

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

这就是他们与众不同的原因.



1> Mike Houston..:

好的,我已经知道发生了什么.我当时很蠢.Leonidas是对的,它不仅仅是加密的哈希,它是与摘要连接的哈希算法的ID:

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

这就是他们与众不同的原因.


好的,迈克.你如何让他们产生相同的结果?
正是我需要的!非常感谢!+20分给你

2> Romulo Perei..:

要产生相同的结果:

MessageDigest sha1 = MessageDigest.getInstance("SHA1", BOUNCY_CASTLE_PROVIDER);
byte[] digest = sha1.digest(content);
DERObjectIdentifier sha1oid_ = new DERObjectIdentifier("1.3.14.3.2.26");

AlgorithmIdentifier sha1aid_ = new AlgorithmIdentifier(sha1oid_, null);
DigestInfo di = new DigestInfo(sha1aid_, digest);

byte[] plainSig = di.getDEREncoded();
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", BOUNCY_CASTLE_PROVIDER);
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] signature = cipher.doFinal(plainSig);


你怎么找到SHA1的魔术代码"1.3.14.3.2.26"?
推荐阅读
放ch养奶牛
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有