简体   繁体   English

SHA256withRSA和SHA256然后RSA之间的区别

[英]Difference between SHA256withRSA and SHA256 then RSA

What is the difference between compute a signature with the following two methods? 使用以下两种方法计算签名有什么区别?

  1. Compute a signature with Signature.getInstance("SHA256withRSA") 使用Signature.getInstance("SHA256withRSA")计算签名
  2. Compute SHA256 with MessageDigest.getInstance("SHA-256") and compute the digest with Signature.getInstance("RSA"); 使用MessageDigest.getInstance("SHA-256")计算SHA256,并使用Signature.getInstance("RSA");计算摘要Signature.getInstance("RSA"); to get the signature? 得到签名?

If they are different, is there a way to modify the method 2 so that both methods give the same output? 如果它们不同,是否有办法修改方法2,使两种方法都输出相同?

I tried the following code: 我尝试了以下代码:

package mysha.mysha;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.Security;
import java.security.Signature;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class MySHA256 {

    public static void main(String[] args) throws Exception {
        //compute SHA256 first
        Security.addProvider(new BouncyCastleProvider());
        String s = "1234";
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
        messageDigest.update(s.getBytes());
        byte[] outputDigest = messageDigest.digest();       
        //sign SHA256 with RSA
        PrivateKey privateKey = Share.loadPk8("D:/key.pk8");
        Signature rsaSignature = Signature.getInstance("RSA");
        rsaSignature.initSign(privateKey);
        rsaSignature.update(outputDigest);
        byte[] signed = rsaSignature.sign();
        System.out.println(bytesToHex(signed));


        //compute SHA256withRSA as a single step
        Signature rsaSha256Signature = Signature.getInstance("SHA256withRSA");
        rsaSha256Signature.initSign(privateKey);
        rsaSha256Signature.update(s.getBytes());
        byte[] signed2 = rsaSha256Signature.sign();
        System.out.println(bytesToHex(signed2));
    }

    public static String bytesToHex(byte[] bytes) {
        final char[] hexArray = "0123456789ABCDEF".toCharArray();
        char[] hexChars = new char[bytes.length * 2];
        for ( int j = 0; j < bytes.length; j++ ) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }

}

Nevertheless, the outputs are not the same. 但是,输出并不相同。

The following is the sample output with my test key: 以下是带有测试键的示例输出:

method 1: 61427B2A2CF1902A4B15F80156AEB09D8096BA1271F89F1919C78B18D0BABA08AA043A0037934B5AE3FC0EB7702898AC5AE96517AFD93433DF540353BCCE72A470CFA4B765D5835E7EA77743F3C4A0ABB11414B0141EF7ECCD2D5285A69728D0D0709C2537D6A772418A928B0E168F81C99B538FD25BDA7496AE8E185AC46F39 方法1: 61427B2A2CF1902A4B15F80156AEB09D8096BA1271F89F1919C78B18D0BABA08AA043A0037934B5AE3FC0EB7702898AC5AE96517AFD93433DF540353BCCE72A470CFA4B765D5835E7EA77743F3C4A0ABB11414B0141EF7ECCD2D5285A69728D0D0709C2537D6A772418A928B0E168F81C99B538FD25BDA7496AE8E185AC46F39

method 2: BA9039B75CA8A40DC9A7AED51E174E2B3365B2D6A1CF94DF70A00D898074A51FDD9973672DDE95CBAC39EBE4F3BA529C538ED0FF9F0A3F9A8CE203F1DFFA907DC508643906AA86DA54DFF8A90B00F5F116D13A53731384C1C5C9C4E75A3E41DAF88F74D2F1BCCF818764A4AB144A081B641C1C488AC8B194EB14BC9D1928E4EA 方法2: BA9039B75CA8A40DC9A7AED51E174E2B3365B2D6A1CF94DF70A00D898074A51FDD9973672DDE95CBAC39EBE4F3BA529C538ED0FF9F0A3F9A8CE203F1DFFA907DC508643906AA86DA54DFF8A90B00F5F116D13A53731384C1C5C9C4E75A3E41DAF88F74D2F1BCCF818764A4AB144A081B641C1C488AC8B194EB14BC9D1928E4EA

Update 1: 更新1:

According to mkl's answer, I modify my code but still cannot get it right. 根据mkl的回答,我修改了代码,但仍然无法正确执行。 Do I still miss something? 我还想念什么吗?

package mysha.mysha;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.Security;
import java.security.Signature;

import org.bouncycastle.asn1.DEROutputStream;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DigestInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class MySHA256 { 
    public static void main(String[] args) throws Exception {
        //compute SHA256 first
        Security.addProvider(new BouncyCastleProvider());
        String s = "1234";
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
        messageDigest.update(s.getBytes());
        byte[] outputDigest = messageDigest.digest();

        AlgorithmIdentifier sha256Aid = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256, null);
        DigestInfo di = new DigestInfo(sha256Aid, outputDigest);
        //sign SHA256 with RSA
        PrivateKey privateKey = Share.loadPk8("D:/key.pk8");
        Signature rsaSignature = Signature.getInstance("RSA");
        rsaSignature.initSign(privateKey);
        rsaSignature.update(di.toASN1Primitive().getEncoded());
        byte[] signed = rsaSignature.sign();
        System.out.println("method 1: "+bytesToHex(signed));


        //compute SHA256withRSA as a single step
        Signature rsaSha256Signature = Signature.getInstance("SHA256withRSA");
        rsaSha256Signature.initSign(privateKey);
        rsaSha256Signature.update(s.getBytes());
        byte[] signed2 = rsaSha256Signature.sign();
        System.out.println("method 2: "+bytesToHex(signed2));
    }
    public static String bytesToHex(byte[] bytes) {
        final char[] hexArray = "0123456789ABCDEF".toCharArray();
        char[] hexChars = new char[bytes.length * 2];
        for ( int j = 0; j < bytes.length; j++ ) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }
}

method 1: 675D868546777C5A9B5E74988E0CD41A46A929C1D0890B32B1FBE34F12D68F1FDB56E623294DB903F6AC60A2ADA61976B27C66056A16F5790A78168803AD2C685F9B4CF983C939305A9819CBA9D95441CD7214D40D06A98B4DDF9692A7D300DD51E808A6722A0D7C288DBD476DF4DEEBB3DAF41CFC0978F24424960F86F0284E 方法1: 675D868546777C5A9B5E74988E0CD41A46A929C1D0890B32B1FBE34F12D68F1FDB56E623294DB903F6AC60A2ADA61976B27C66056A16F5790A78168803AD2C685F9B4CF983C939305A9819CBA9D95441CD7214D40D06A98B4DDF9692A7D300DD51E808A6722A0D7C288DBD476DF4DEEBB3DAF41CFC0978F24424960F86F0284E

method 2: BA9039B75CA8A40DC9A7AED51E174E2B3365B2D6A1CF94DF70A00D898074A51FDD9973672DDE95CBAC39EBE4F3BA529C538ED0FF9F0A3F9A8CE203F1DFFA907DC508643906AA86DA54DFF8A90B00F5F116D13A53731384C1C5C9C4E75A3E41DAF88F74D2F1BCCF818764A4AB144A081B641C1C488AC8B194EB14BC9D1928E4EA 方法2: BA9039B75CA8A40DC9A7AED51E174E2B3365B2D6A1CF94DF70A00D898074A51FDD9973672DDE95CBAC39EBE4F3BA529C538ED0FF9F0A3F9A8CE203F1DFFA907DC508643906AA86DA54DFF8A90B00F5F116D13A53731384C1C5C9C4E75A3E41DAF88F74D2F1BCCF818764A4AB144A081B641C1C488AC8B194EB14BC9D1928E4EA

The difference 区别

The difference between signing with "SHA256withRSA" and computing the SHA256 hash and signing it with "RSA" (= "NONEwithRSA" ) is foremost that in the former case the calculated SHA-256 hash value is first encapsulated in a DigestInfo structure "SHA256withRSA"签名和计算SHA256哈希值再用"RSA" (= "NONEwithRSA" )签名之间的区别是,在前一种情况下,首先将计算出的SHA-256哈希值封装在DigestInfo结构中

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

before being padded and then encrypted while in the latter case the naked SHA256 hash value is padded and encrypted. 在填充之前先进行加密,然后再进行加密;在后一种情况下,将对裸露的SHA256哈希值进行填充和加密。

If they are different, is there a way to modify the method 2 so that both methods give the same output? 如果它们不同,是否有办法修改方法2,使两种方法都输出相同?

First and foremost you will have to encapsulate the hash value in a DigestInfo structure before signing using "NONEwithRSA" . 首先,在使用"NONEwithRSA"签名之前,您必须将哈希值封装在DigestInfo结构中。

RFC 3447 Section 9.2 helps here by stating in Note 1 that RFC 3447第9.2节通过在注释1中指出

1. For the six hash functions mentioned in Appendix B.1, the DER
   encoding T of the DigestInfo value is equal to the following:
   ...
   SHA-256: (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00
                04 20 || H.

Making it work 使它工作

In response to the section above the OP updated his question with the updated code. 针对以上部分,OP使用更新的代码更新了他的问题。 Unfortunately, though, it did not yet work for him. 但是,不幸的是,它对他还没有起作用。 Thus, 从而,

The OP's code OP的代码

I executed the OP's code ( SignInSteps.java ). 我执行了OP的代码( SignInSteps.java )。 As he didn't provide the private key, I used a test key of my own ( demo-rsa2048.p12 ). 由于他没有提供私钥,因此我使用了自己的测试密钥( demo-rsa2048.p12 )。 The result: 结果:

GreenhandOriginal:
1B9557B6A076226FA4C26A9370A0E9E91B627F14204D427B03294EC4BFC346FDEEFB3A483B1E5A0593F26E9DE87F9202E1064F4D75B24B8FA355B23A560AF263361BB94B2339C3A01952C447CAC862AA9DCAB64B09ABAA0AD50232CDB299D1E4B5F7138F448A87ED32BFF4B5B66F35FFA08F13FD98DFCEC7114710282E463245311DA7A56CBEA958D88137A8B507D8601464535978EFE36EE37EF721260DB7112484F244409F0BD64C823ACFB13D06ABA84A9A0C5AB207E19231D6A71CC80F07FDA2A9654F0F609C2C3396D6DFFBBB10EF4C3D4B5ADFC72EACC044E81F252B699F095CFEF8630B284B1F6BD7201367BD5FDF2BB4C20BD07B9CC20B214D86C729
4B9ECA6DD47C1B230D972E7DA026165F1CE743EC96825E4C13DFE2C6437FE673A13CA622047EE7D2F7C5280198D81550A1CBD17F8E8A3C4C2D53A746FA6464AA5194FC2782527B014F017008D89BB2C80B7FA367C74FE01369986B56BCE7DC573A11ED884511F0CB12160CA5E42D488451AA8961BF5A9F71E6A5E89F19BC8EFAC26DDE989A0369667EE74372F6E558887FE2561EA926B441AB8F0FD3DEDD608A671011313372084B059CAD7E4807AC852C0873C57F216349422771C089678BAC3021D054C4427EADE70219E251617B83E68640DD7D03C3F99E47F79EB71C124F59EDEA724496A4552F2E9E1F90DDE550745E85483D823F146982C6D2008FE9AA

GreenhandUpdated:
method 1: 4B9ECA6DD47C1B230D972E7DA026165F1CE743EC96825E4C13DFE2C6437FE673A13CA622047EE7D2F7C5280198D81550A1CBD17F8E8A3C4C2D53A746FA6464AA5194FC2782527B014F017008D89BB2C80B7FA367C74FE01369986B56BCE7DC573A11ED884511F0CB12160CA5E42D488451AA8961BF5A9F71E6A5E89F19BC8EFAC26DDE989A0369667EE74372F6E558887FE2561EA926B441AB8F0FD3DEDD608A671011313372084B059CAD7E4807AC852C0873C57F216349422771C089678BAC3021D054C4427EADE70219E251617B83E68640DD7D03C3F99E47F79EB71C124F59EDEA724496A4552F2E9E1F90DDE550745E85483D823F146982C6D2008FE9AA
method 2: 4B9ECA6DD47C1B230D972E7DA026165F1CE743EC96825E4C13DFE2C6437FE673A13CA622047EE7D2F7C5280198D81550A1CBD17F8E8A3C4C2D53A746FA6464AA5194FC2782527B014F017008D89BB2C80B7FA367C74FE01369986B56BCE7DC573A11ED884511F0CB12160CA5E42D488451AA8961BF5A9F71E6A5E89F19BC8EFAC26DDE989A0369667EE74372F6E558887FE2561EA926B441AB8F0FD3DEDD608A671011313372084B059CAD7E4807AC852C0873C57F216349422771C089678BAC3021D054C4427EADE70219E251617B83E68640DD7D03C3F99E47F79EB71C124F59EDEA724496A4552F2E9E1F90DDE550745E85483D823F146982C6D2008FE9AA

Thus, in contrast to the OP's observations, signatures equal in case of the updated code. 因此,与OP的观察相反,在更新代码的情况下,签名相等。

Not assuming copy&paste errors, there still might be other differences involved. 不承担复制和粘贴错误,可能还会涉及其他差异。

The environment 环境

I tested using Java 8 (1.8.0_20) with unlimited jurisdiction files added and BouncyCastle 1.52, 1.49, and 1.46 (with a small test code modification due to the BC API changes). 我使用Java 8(1.8.0_20)添加了无限制的权限文件并添加了BouncyCastle 1.52、1.49和1.46(由于BC API更改而对测试代码进行了少量修改)进行了测试。

The OP mentioned in a comment: OP在评论中提到:

The Java is JRE 8 update 66. The BouncyCastle is bcprov-jdk15on-153.jar. Java是JRE 8更新66。BouncyCastle是bcprov-jdk15on-153.jar。

Thus I updated Java, still no difference. 因此,我更新了Java,仍然没有区别。

Then I updated BouncyCastle to 1.53. 然后,我将BouncyCastle更新为1.53。 And indeed, suddenly the results differed: 实际上,突然之间结果有所不同:

GreenhandOriginal:
1B9557B6A076226FA4C26A9370A0E9E91B627F14204D427B03294EC4BFC346FDEEFB3A483B1E5A0593F26E9DE87F9202E1064F4D75B24B8FA355B23A560AF263361BB94B2339C3A01952C447CAC862AA9DCAB64B09ABAA0AD50232CDB299D1E4B5F7138F448A87ED32BFF4B5B66F35FFA08F13FD98DFCEC7114710282E463245311DA7A56CBEA958D88137A8B507D8601464535978EFE36EE37EF721260DB7112484F244409F0BD64C823ACFB13D06ABA84A9A0C5AB207E19231D6A71CC80F07FDA2A9654F0F609C2C3396D6DFFBBB10EF4C3D4B5ADFC72EACC044E81F252B699F095CFEF8630B284B1F6BD7201367BD5FDF2BB4C20BD07B9CC20B214D86C729
4B9ECA6DD47C1B230D972E7DA026165F1CE743EC96825E4C13DFE2C6437FE673A13CA622047EE7D2F7C5280198D81550A1CBD17F8E8A3C4C2D53A746FA6464AA5194FC2782527B014F017008D89BB2C80B7FA367C74FE01369986B56BCE7DC573A11ED884511F0CB12160CA5E42D488451AA8961BF5A9F71E6A5E89F19BC8EFAC26DDE989A0369667EE74372F6E558887FE2561EA926B441AB8F0FD3DEDD608A671011313372084B059CAD7E4807AC852C0873C57F216349422771C089678BAC3021D054C4427EADE70219E251617B83E68640DD7D03C3F99E47F79EB71C124F59EDEA724496A4552F2E9E1F90DDE550745E85483D823F146982C6D2008FE9AA

GreenhandUpdated:
method 1: 6BAAAC1060B6D0D56AD7D45A1BEECE82391088FF47A8D8179EFBBEB0925C4AC6C9DFC56F672E99F4A6E3C106A866B70513C25AE11B267286C584A136FBC20C4D1E7B10697352DF020BA5D67029A6EF890B2674F02C496CB1F1EBB0D4DBB580EB045DBB0FA0D7D73B418FF63F345658C6C73DA742FE260C9639C94967A928F74F61DACA03310B9986C32D83CAB8C7FC13E80612CCFC0B7E3E35BEA04EAEBDAA55FB8837B4661DC71499B4A0B1D36E1D23D9927CDB55C237D5AB2E5C088F29C6FAFAD9FE64DD4851CEC113560864E9923D485D0C6E092C8EBE82D29C312E5835B38EE9BD6B8B4BCC753EF4EE4D0977B2E781B391839E3EC31C36E5B1AA0CE90227
method 2: 4B9ECA6DD47C1B230D972E7DA026165F1CE743EC96825E4C13DFE2C6437FE673A13CA622047EE7D2F7C5280198D81550A1CBD17F8E8A3C4C2D53A746FA6464AA5194FC2782527B014F017008D89BB2C80B7FA367C74FE01369986B56BCE7DC573A11ED884511F0CB12160CA5E42D488451AA8961BF5A9F71E6A5E89F19BC8EFAC26DDE989A0369667EE74372F6E558887FE2561EA926B441AB8F0FD3DEDD608A671011313372084B059CAD7E4807AC852C0873C57F216349422771C089678BAC3021D054C4427EADE70219E251617B83E68640DD7D03C3F99E47F79EB71C124F59EDEA724496A4552F2E9E1F90DDE550745E85483D823F146982C6D2008FE9AA

Interestingly only the value for method 1 in the updated code differs. 有趣的是,仅更新代码中方法1的值有所不同。 Thus, I looked at the intermediary objects in that case 因此,在这种情况下,我研究了中介对象

[BC 1.52]
hash: 03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4
algo: 2.16.840.1.101.3.4.2.1
info: 3031300D06096086480165030402010500042003AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4

[BC 1.53]
hash: 03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4
algo: 2.16.840.1.101.3.4.2.1
info: 302F300B0609608648016503040201042003AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4

Thus, BouncyCastle 1.53 encodes the DigestInfo object differently! 因此,BouncyCastle 1.53对DigestInfo对象的编码方式有所不同! And the encoding in 1.52 (and below) is the one expected by the RFC 3447 Section 9.2 . 1.52(及以下)中的编码是RFC 3447第9.2节所期望的编码。

Looking at the ASN.1 dumps one sees that BC 1.52 encodes the AlgorithmIdentifier as 查看ASN.1转储,您会发现BC 1.52将AlgorithmIdentifier编码为

 2  13:   SEQUENCE {
   <06 09>
 4   9:     OBJECT IDENTIFIER sha-256 (2 16 840 1 101 3 4 2 1)
      :       (NIST Algorithm)
   <05 00>
15   0:     NULL
      :     }

while BC 1.53 creates 而BC 1.53创造了

 2  11:   SEQUENCE {
   <06 09>
 4   9:     OBJECT IDENTIFIER sha-256 (2 16 840 1 101 3 4 2 1)
      :       (NIST Algorithm)
      :     }

So in 1.53 the algorithm parameters are missing altogether. 因此在1.53中,算法参数完全缺失。 This suggests changing the line 这建议改变线

AlgorithmIdentifier sha256Aid = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256, null);

to

AlgorithmIdentifier sha256Aid = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256, DERNull.INSTANCE);

and suddenly it works with BouncyCastle 1.53, too, the values for method 1 and method 2 coincide! 突然之间,它也可以与BouncyCastle 1.53一起使用,方法1和方法2的值一致! ;) ;)

TL;DR TL; DR

Don't use null as the SHA-256 parameters when instantiating the AlgorithmIdentifier , use DERNull.INSTANCE instead. 实例化AlgorithmIdentifier ,请勿将null用作SHA-256参数,而应使用DERNull.INSTANCE

How did I... 我怎么

In a comment the OP indicated that he'd like to know more about OP在评论中表示他想进一步了解

  1. how do you inspect the intermediate object of BouncyCastle and 您如何检查BouncyCastle的中间对象和
  2. how do you produce the ASN.1 dumps. 您如何产生ASN.1转储。

So... 所以...

... inspect the intermediate object ...检查中间物体

Quite simple. 非常简单。 First I split up the line 首先我把线分开

rsaSignature.update(di.toASN1Primitive().getEncoded());

in the updated code as 在更新的代码中

byte[] encodedDigestInfo = di.toASN1Primitive().getEncoded();
rsaSignature.update(encodedDigestInfo);

and then added console outputs 然后添加控制台输出

System.out.println("    hash: " + bytesToHex(outputDigest));
System.out.println("    algo: " + sha256Aid.getAlgorithm());
System.out.println("    info: " + bytesToHex(encodedDigestInfo));

Finally I executed the code with the different BouncyCastle versions. 最后,我使用不同的BouncyCastle版本执行了代码。

... produce the ASN.1 dumps ...产生ASN.1转储

There is a well-known utility called dumpasn1 by Peter Gutmann which has become the kernel of many command line and GUI tools for creating and displaying ASN.1 dumps. 彼得·古特曼(Peter Gutmann)有一个著名的实用程序dumpasn1,它已成为创建和显示ASN.1转储的许多命令行和GUI工具的内核。 I currently happen to use GUIdumpASN-ng . 我目前正巧使用GUIdumpASN-ng

In the case at hand I saved the contents of the byte[] encodedDigestInfo to a file (which can be done using eg Files.write ) and opened these files in GUIdumpASN-ng. 在目前的情况下,我将byte[] encodedDigestInfo的内容保存到文件中(可以使用例如Files.write完成),并在GUIdumpASN-ng中打开这些文件。

******Without BouncyCastle I adjusted your solution folowing the mkl's answer steps****** ******如果没有BouncyCastle,我会按照mkl的回答步骤调整您的解决方案******

import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateCrtKey;

import sun.security.rsa.RSACore;
import sun.security.rsa.RSAPadding;
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
import sun.security.x509.AlgIdDSA;
import sun.security.x509.AlgorithmId;

public class MySHA256 {

    public static void main(String[] args) throws Exception {

        String s = "1234";
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
        messageDigest.update(s.getBytes());
        byte[] outputDigest = messageDigest.digest(); 
        //compute SHA256 first
        DerOutputStream out = new DerOutputStream();
        new AlgorithmId(AlgIdDSA.SHA256_oid).encode(out);
        out.putOctetString(outputDigest);
        DerValue result = new DerValue(DerValue.tag_Sequence, out.toByteArray());
        byte[] encoded = result.toByteArray();      
        //sign SHA256 with RSA
        PrivateKey privateKey = Share.loadPk8("D:/key.pk8");
        RSAPrivateCrtKey pkRSA = (RSAPrivateCrtKey)privateKey;
        int keySize = RSACore.getByteLength(pkRSA);
        RSAPadding padding = RSAPadding.getInstance(RSAPadding.PAD_BLOCKTYPE_1, keySize, null);
        byte[] padded = padding.pad(encoded);
        byte[] signed = RSACore.rsa(padded, pkRSA, true);
        System.out.println(bytesToHex(signed));


        //compute SHA256withRSA as a single step
        Signature rsaSha256Signature = Signature.getInstance("SHA256withRSA");
        rsaSha256Signature.initSign(privateKey);
        rsaSha256Signature.update(s.getBytes());
        byte[] signed2 = rsaSha256Signature.sign();
        System.out.println(bytesToHex(signed2));
    }

    public static String bytesToHex(byte[] bytes) {
        final char[] hexArray = "0123456789ABCDEF".toCharArray();
        char[] hexChars = new char[bytes.length * 2];
        for ( int j = 0; j < bytes.length; j++ ) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }



}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM