Java SHA256withRSA和SHA256然后RSA之间的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33305800/
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
Difference between SHA256withRSA and SHA256 then RSA
提问by Greenhand
What is the difference between compute a signature with the following two methods?
使用以下两种方法计算签名有什么区别?
- Compute a signature with
Signature.getInstance("SHA256withRSA")
- Compute SHA256 with
MessageDigest.getInstance("SHA-256")
and compute the digest withSignature.getInstance("RSA");
to get the signature?
- 计算签名
Signature.getInstance("SHA256withRSA")
- 计算 SHA256
MessageDigest.getInstance("SHA-256")
并计算摘要Signature.getInstance("RSA");
以获得签名?
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
方法一: 61427B2A2CF1902A4B15F80156AEB09D8096BA1271F89F1919C78B18D0BABA08AA043A0037934B5AE3FC0EB7702898AC5AE96517AFD93433DF540353BCCE72A470CFA4B765D5835E7EA77743F3C4A0ABB11414B0141EF7ECCD2D5285A69728D0D0709C2537D6A772418A928B0E168F81C99B538FD25BDA7496AE8E185AC46F39
method 2: BA9039B75CA8A40DC9A7AED51E174E2B3365B2D6A1CF94DF70A00D898074A51FDD9973672DDE95CBAC39EBE4F3BA529C538ED0FF9F0A3F9A8CE203F1DFFA907DC508643906AA86DA54DFF8A90B00F5F116D13A53731384C1C5C9C4E75A3E41DAF88F74D2F1BCCF818764A4AB144A081B641C1C488AC8B194EB14BC9D1928E4EA
方法二: BA9039B75CA8A40DC9A7AED51E174E2B3365B2D6A1CF94DF70A00D898074A51FDD9973672DDE95CBAC39EBE4F3BA529C538ED0FF9F0A3F9A8CE203F1DFFA907DC508643906AA86DA54DFF8A90B00F5F116D13A53731384C1C5C9C4E75A3E41DAF88F74D2F1BCCF818764A4AB144A081B641C1C488AC8B194EB14BC9D1928E4EA
Update 1:
更新 1:
According to mkl's answer, I modify my code but still cannot get it right. Do I still miss something?
根据 mkl 的回答,我修改了我的代码,但仍然无法正确处理。我还想念什么吗?
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
方法一:
675D868546777C5A9B5E74988E0CD41A46A929C1D0890B32B1FBE34F12D68F1FDB56E623294DB903F6AC60A2ADA61976B27C66056A16F5790A78168803AD2C685F9B4CF983C939305A9819CBA9D95441CD7214D40D06A98B4DDF9692A7D300DD51E808A6722A0D7C288DBD476DF4DEEBB3DAF41CFC0978F24424960F86F0284E
method 2:
BA9039B75CA8A40DC9A7AED51E174E2B3365B2D6A1CF94DF70A00D898074A51FDD9973672DDE95CBAC39EBE4F3BA529C538ED0FF9F0A3F9A8CE203F1DFFA907DC508643906AA86DA54DFF8A90B00F5F116D13A53731384C1C5C9C4E75A3E41DAF88F74D2F1BCCF818764A4AB144A081B641C1C488AC8B194EB14BC9D1928E4EA
方法二:
BA9039B75CA8A40DC9A7AED51E174E2B3365B2D6A1CF94DF70A00D898074A51FDD9973672DDE95CBAC39EBE4F3BA529C538ED0FF9F0A3F9A8CE203F1DFFA907DC508643906AA86DA54DFF8A90B00F5F116D13A53731384C1C5C9C4E75A3E41DAF88F74D2F1BCCF818764A4AB144A081B641C1C488AC8B194EB14BC9D1928E4EA
采纳答案by mkl
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"
.
首先,您必须DigestInfo
在使用签名之前将哈希值封装在一个结构中"NONEwithRSA"
。
RFC 3447 Section 9.2helps 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. Unfortunately, though, it did not yet work for him. Thus,
为了回应上面的部分,OP 用更新的代码更新了他的问题。然而不幸的是,这对他来说还没有奏效。因此,
The OP's code
OP的代码
I executed the OP's code (SignInSteps.java). As he didn't provide the private key, I used a test key of my own (demo-rsa2048.p12). The result:
我执行了 OP 的代码(SignInSteps.java)。由于他没有提供私钥,我使用了自己的测试密钥(demo-rsa2048.p12)。结果:
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 update 66。BouncyCastle 是 bcprov-jdk15on-153.jar。
Thus I updated Java, still no difference.
因此我更新了Java,仍然没有区别。
Then I updated BouncyCastle to 1.53. And indeed, suddenly the results differed:
然后我将 BouncyCastle 更新到 1.53。事实上,结果突然不同了:
GreenhandOriginal:
1B9557B6A076226FA4C26A9370A0E9E91B627F14204D427B03294EC4BFC346FDEEFB3A483B1E5A0593F26E9DE87F9202E1064F4D75B24B8FA355B23A560AF263361BB94B2339C3A01952C447CAC862AA9DCAB64B09ABAA0AD50232CDB299D1E4B5F7138F448A87ED32BFF4B5B66F35FFA08F13FD98DFCEC7114710282E463245311DA7A56CBEA958D88137A8B507D8601464535978EFE36EE37EF721260DB7112484F244409F0BD64C823ACFB13D06ABA84A9A0C5AB207E19231D6A71CC80F07FDA2A9654F0F609C2C3396D6DFFBBB10EF4C3D4B5ADFC72EACC044E81F252B699F095CFEF8630B284B1F6BD7201367BD5FDF2BB4C20BD07B9CC20B214D86C729
4B9ECA6DD47C1B230D972E7DA026165F1CE743EC96825E4C13DFE2C6437FE673A13CA622047EE7D2F7C5280198D81550A1CBD17F8E8A3C4C2D53A746FA6464AA5194FC2782527B014F017008D89BB2C80B7FA367C74FE01369986B56BCE7DC573A11ED884511F0CB12160CA5E42D488451AA8961BF5A9F71E6A5E89F19BC8EFAC26DDE989A0369667EE74372F6E558887FE2561EA926B441AB8F0FD3DEDD608A671011313372084B059CAD7E4807AC852C0873C57F216349422771C089678BAC3021D054C4427EADE70219E251617B83E68640DD7D03C3F99E47F79EB71C124F59EDEA724496A4552F2E9E1F90DDE550745E85483D823F146982C6D2008FE9AA
GreenhandUpdated:
method 1: 6BAAAC1060B6D0D56AD7D45A1BEECE82391088FF47A8D8179EFBBEB0925C4AC6C9DFC56F672E99F4A6E3C106A866B70513C25AE11B267286C584A136FBC20C4D1E7B10697352DF020BA5D67029A6EF890B2674F02C496CB1F1EBB0D4DBB580EB045DBB0FA0D7D73B418FF63F345658C6C73DA742FE260C9639C94967A928F74F61DACA03310B9986C32D83CAB8C7FC13E80612CCFC0B7E3E35BEA04EAEBDAA55FB8837B4661DC71499B4A0B1D36E1D23D9927CDB55C237D5AB2E5C088F29C6FAFAD9FE64DD4851CEC113560864E9923D485D0C6E092C8EBE82D29C312E5835B38EE9BD6B8B4BCC753EF4EE4D0977B2E781B391839E3EC31C36E5B1AA0CE90227
method 2: 4B9ECA6DD47C1B230D972E7DA026165F1CE743EC96825E4C13DFE2C6437FE673A13CA622047EE7D2F7C5280198D81550A1CBD17F8E8A3C4C2D53A746FA6464AA5194FC2782527B014F017008D89BB2C80B7FA367C74FE01369986B56BCE7DC573A11ED884511F0CB12160CA5E42D488451AA8961BF5A9F71E6A5E89F19BC8EFAC26DDE989A0369667EE74372F6E558887FE2561EA926B441AB8F0FD3DEDD608A671011313372084B059CAD7E4807AC852C0873C57F216349422771C089678BAC3021D054C4427EADE70219E251617B83E68640DD7D03C3F99E47F79EB71C124F59EDEA724496A4552F2E9E1F90DDE550745E85483D823F146982C6D2008FE9AA
Interestingly only the value for method 1 in the updated code differs. Thus, I looked at the intermediary objects in that case
有趣的是,只有更新代码中方法 1 的值不同。因此,我查看了这种情况下的中间对象
[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! And the encoding in 1.52 (and below) is the one expected by the RFC 3447 Section 9.2.
因此,BouncyCastle 1.53 以不同的方式对 DigestInfo 对象进行编码!1.52(及以下)中的编码是RFC 3447 Section 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. This suggests changing the line
所以在 1.53 中,算法参数完全丢失了。这表明改变线路
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; 博士
Don't use null
as the SHA-256 parameters when instantiating the AlgorithmIdentifier
, use DERNull.INSTANCE
instead.
null
实例化 时不要用作 SHA-256 参数AlgorithmIdentifier
,DERNull.INSTANCE
而是使用。
How did I...
我怎么...
In a comment the OP indicated that he'd like to know more about
在评论中,OP 表示他想了解更多关于
- how do you inspect the intermediate object of BouncyCastle and
- how do you produce the ASN.1 dumps.
- 你如何检查 BouncyCastle 的中间对象和
- 你如何产生 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 Gutmannwhich has become the kernel of many command line and GUI tools for creating and displaying ASN.1 dumps. I currently happen to use GUIdumpASN-ng.
Peter Gutmann有一个著名的实用程序,称为dumpasn1,它已成为许多用于创建和显示 ASN.1 转储的命令行和 GUI 工具的内核。我目前碰巧使用GUIdumpASN-ng。
In the case at hand I saved the contents of the byte[] encodedDigestInfo
to a file (which can be done using e.g. Files.write
) and opened these files in GUIdumpASN-ng.
在手头的情况下,我将 的内容保存byte[] encodedDigestInfo
到一个文件(可以使用 eg 完成Files.write
)并在 GUIdumpASN-ng 中打开这些文件。
回答by Luciano Sousa
******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);
}
}