Java – the difference between sha256 and RSA and sha256, and then RSA
What is the difference between using the following two methods to calculate a signature?
>Use signature GetInstance calculates the signature ("sha256withrsa") > using messagedigest GetInstance ("SHA-256") calculates sha256 and uses signature GetInstance ("RSA") calculation summary; Get a signature?
If they are different, is there a way to modify method 2 so that both methods give the same output?
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); } }
However, the output is different
The following is an example output of my test key:
Method 1: 61427b2a2cf1902a4b15f80156aeb09d8096ba1271f89f1919c78b18d0baba08aa0037934b5ae3fc0eb7702898ac5ae96517afd93433df54035bcce72a470cfa4b765d5835e7ea77743f3c4a0abb1414b0141ef7eccd2d5285a69728d0d0d00709c2537d6a77218a928b0e168f81c99b538fd25bda7496ae8e185ac46f39
Method 2: ba9039b75ca8a40dc9a7aed51e174e2b3365b2d6a1cf94df70a00d898074a51fddd9973672dde95cbac39ebe4f3ba529c538ed0ff9f0a3f9a8ce203f1dffa907dc50863906aa86da54dff8a90b00f5f116d13a5373184c1c5c9c4e75a3e41daf88f74d2f1bccf818764a4ab144a081b641c488ac8b194eb14bc9d1928e4e a
Update 1:
According to MKL's answer, I modified my code, but I still can't correct it What else do I miss?
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: 675d868546777c5a9b5e74988e0cd41a46a929c1d0890b32b1fbe34f12d68f1fdb56e623294db903f6ac60a2ada61976b27c66056a16f5790a78168803ad2c685f9b4cf983c939305a9819cba9d95441cd7214d40d06a98b4ddf9692a7d300dd51e808a6722a0d7c288dbd476df4deeb3daf41cfc0978f244960f86f86f0284 E
Method 2: ba9039b75ca8a40dc9a7aed51e174e2b3365b2d6a1cf94df70a00d898074a51fddd9973672dde95cbac39ebe4f3ba529c538ed0ff9f0a3f9a8ce203f1dffa907dc50863906aa86da54dff8a90b00f5f116d13a5373184c1c5c9c4e75a3e41daf88f74d2f1bccf818764a4ab144a081b641c488ac8b194eb14bc9d1928e4e a
Solution
difference
The difference from "sha256withrsa" signing and calculating sha256 hash and signing with "RSA" (= "nonewithrsa"). Firstly, in the former case, the calculated SHA-256 hash value is first encapsulated in the digestinfo structure
DigestInfo ::= SEQUENCE { digestAlgorithm DigestAlgorithm,digest OCTET STRING }
In the latter case, bare metal sha256 hash values are populated and encrypted
First, you must encapsulate the hash value in the digestinfo structure before using "none with RSA" signature
RFC 3447 Section 9.2 describes note 1 here
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.
Make it work
In response to the above section, Op updated his questions and updated code Unfortunately, it hasn't worked for him yet Thus,
Op code
I executed the op code (signinsteps. Java) Since he did not provide the private key, I used my own test key (demo-rsa2048. P12) result:
GreenhandOriginal: 1B9557B6A076226FA4C26A9370A0E9E91B627F14204D427B03294EC4BFC346FDEEFB3A483B1E5A0593F26E9DE87F9202E1064F4D75B24B8FA355B23A560AF263361BB94B2339C3A01952C447CAC862AA9DCAB64B09ABAA0AD50232CDB299D1E4B5F7138F448A87ED32BFF4B5B66F35FFA08F13FD98DFCEC7114710282E463245311DA7A56CBEA958D88137A8B507D8601464535978EFE36EE37EF721260DB7112484F244409F0BD64C823ACFB13D06ABA84A9A0C5AB207E19231D6A71CC80F07FDA2A9654F0F609C2C3396D6DFFBBB10EF4C3D4B5ADFC72EACC044E81F252B699F095CFEF8630B284B1F6BD7201367BD5FDF2BB4C20BD07B9CC20B214D86C729 4B9ECA6DD47C1B230D972E7DA026165F1CE743EC96825E4C13DFE2C6437FE673A13CA622047EE7D2F7C5280198D81550A1CBD17F8E8A3C4C2D53A746FA6464AA5194FC2782527B014F017008D89BB2C80B7FA367C74FE01369986B56BCE7DC573A11ED884511F0CB12160CA5E42D488451AA8961BF5A9F71E6A5E89F19BC8EFAC26DDE989A0369667EE74372F6E558887FE2561EA926B441AB8F0FD3DEDD608A671011313372084B059CAD7E4807AC852C0873C57F216349422771C089678BAC3021D054C4427EADE70219E251617B83E68640DD7D03C3F99E47F79EB71C124F59EDEA724496A4552F2E9E1F90DDE550745E85483D823F146982C6D2008FE9AA GreenhandUpdated: method 1: 4B9ECA6DD47C1B230D972E7DA026165F1CE743EC96825E4C13DFE2C6437FE673A13CA622047EE7D2F7C5280198D81550A1CBD17F8E8A3C4C2D53A746FA6464AA5194FC2782527B014F017008D89BB2C80B7FA367C74FE01369986B56BCE7DC573A11ED884511F0CB12160CA5E42D488451AA8961BF5A9F71E6A5E89F19BC8EFAC26DDE989A0369667EE74372F6E558887FE2561EA926B441AB8F0FD3DEDD608A671011313372084B059CAD7E4807AC852C0873C57F216349422771C089678BAC3021D054C4427EADE70219E251617B83E68640DD7D03C3F99E47F79EB71C124F59EDEA724496A4552F2E9E1F90DDE550745E85483D823F146982C6D2008FE9AA method 2: 4B9ECA6DD47C1B230D972E7DA026165F1CE743EC96825E4C13DFE2C6437FE673A13CA622047EE7D2F7C5280198D81550A1CBD17F8E8A3C4C2D53A746FA6464AA5194FC2782527B014F017008D89BB2C80B7FA367C74FE01369986B56BCE7DC573A11ED884511F0CB12160CA5E42D488451AA8961BF5A9F71E6A5E89F19BC8EFAC26DDE989A0369667EE74372F6E558887FE2561EA926B441AB8F0FD3DEDD608A671011313372084B059CAD7E4807AC852C0873C57F216349422771C089678BAC3021D054C4427EADE70219E251617B83E68640DD7D03C3F99E47F79EB71C124F59EDEA724496A4552F2E9E1F90DDE550745E85483D823F146982C6D2008FE9AA
Therefore, different from the observation of OP, the signatures are equal in the case of updated code
Do not assume copy and paste errors, there may still be other differences
environment
I used java 8 (1.8.0_20) for testing, which added unlimited jurisdiction files, bouncy castle 1.52, 1.49 and 1.46 (minor test code modifications due to BC API changes)
OP mentioned in comments:
So I updated Java, still no difference
Then I updated bouncy castle to 1.53 In fact, suddenly the results are different:
GreenhandOriginal: 1B9557B6A076226FA4C26A9370A0E9E91B627F14204D427B03294EC4BFC346FDEEFB3A483B1E5A0593F26E9DE87F9202E1064F4D75B24B8FA355B23A560AF263361BB94B2339C3A01952C447CAC862AA9DCAB64B09ABAA0AD50232CDB299D1E4B5F7138F448A87ED32BFF4B5B66F35FFA08F13FD98DFCEC7114710282E463245311DA7A56CBEA958D88137A8B507D8601464535978EFE36EE37EF721260DB7112484F244409F0BD64C823ACFB13D06ABA84A9A0C5AB207E19231D6A71CC80F07FDA2A9654F0F609C2C3396D6DFFBBB10EF4C3D4B5ADFC72EACC044E81F252B699F095CFEF8630B284B1F6BD7201367BD5FDF2BB4C20BD07B9CC20B214D86C729 4B9ECA6DD47C1B230D972E7DA026165F1CE743EC96825E4C13DFE2C6437FE673A13CA622047EE7D2F7C5280198D81550A1CBD17F8E8A3C4C2D53A746FA6464AA5194FC2782527B014F017008D89BB2C80B7FA367C74FE01369986B56BCE7DC573A11ED884511F0CB12160CA5E42D488451AA8961BF5A9F71E6A5E89F19BC8EFAC26DDE989A0369667EE74372F6E558887FE2561EA926B441AB8F0FD3DEDD608A671011313372084B059CAD7E4807AC852C0873C57F216349422771C089678BAC3021D054C4427EADE70219E251617B83E68640DD7D03C3F99E47F79EB71C124F59EDEA724496A4552F2E9E1F90DDE550745E85483D823F146982C6D2008FE9AA GreenhandUpdated: method 1: 6BAAAC1060B6D0D56AD7D45A1BEECE82391088FF47A8D8179EFBBEB0925C4AC6C9DFC56F672E99F4A6E3C106A866B70513C25AE11B267286C584A136FBC20C4D1E7B10697352DF020BA5D67029A6EF890B2674F02C496CB1F1EBB0D4DBB580EB045DBB0FA0D7D73B418FF63F345658C6C73DA742FE260C9639C94967A928F74F61DACA03310B9986C32D83CAB8C7FC13E80612CCFC0B7E3E35BEA04EAEBDAA55FB8837B4661DC71499B4A0B1D36E1D23D9927CDB55C237D5AB2E5C088F29C6FAFAD9FE64DD4851CEC113560864E9923D485D0C6E092C8EBE82D29C312E5835B38EE9BD6B8B4BCC753EF4EE4D0977B2E781B391839E3EC31C36E5B1AA0CE90227 method 2: 4B9ECA6DD47C1B230D972E7DA026165F1CE743EC96825E4C13DFE2C6437FE673A13CA622047EE7D2F7C5280198D81550A1CBD17F8E8A3C4C2D53A746FA6464AA5194FC2782527B014F017008D89BB2C80B7FA367C74FE01369986B56BCE7DC573A11ED884511F0CB12160CA5E42D488451AA8961BF5A9F71E6A5E89F19BC8EFAC26DDE989A0369667EE74372F6E558887FE2561EA926B441AB8F0FD3DEDD608A671011313372084B059CAD7E4807AC852C0873C57F216349422771C089678BAC3021D054C4427EADE70219E251617B83E68640DD7D03C3F99E47F79EB71C124F59EDEA724496A4552F2E9E1F90DDE550745E85483D823F146982C6D2008FE9AA
Interestingly, only the value of method 1 in the update code is different Therefore, I looked at the object of the mediation in this 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
Therefore, bouncycastle 1.53 encodes digestinfo objects differently! The code of 1.52 (and below) is the expected code of RFC 3447 Section 9.2
Look at ASN 1. It can be seen that BC 1.52 encodes algorithmidentifier as
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 : }
BC 1.53 creates
2 11: SEQUENCE { <06 09> 4 9: OBJECT IDENTIFIER sha-256 (2 16 840 1 101 3 4 2 1) : (NIST Algorithm) : }
Therefore, the algorithm parameters are completely missing in 1.53 This indicates a change in line
AlgorithmIdentifier sha256Aid = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256,null);
to
AlgorithmIdentifier sha256Aid = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256,DERNull.INSTANCE);
Suddenly, it works with bouncycastle 1.53, and the values of method 1 and method 2 are consistent!
The above is the difference between Java – sha256 and RSA and sha256 collected by programming home for you, and then the whole content of RSA. I hope this article can help you solve the difference between Java – sha256 and RSA and sha256, and then the program development problems encountered by RSA.
If you think the content of the programming home website is good, you are welcome to recommend the programming home website to programmers and friends.