6

I have the following c# code to generate a digital signature from a private key:

 static string Sign(string text, string certificate) { X509Certificate2 cert = new X509Certificate2(certificate, "TestPassword", X509KeyStorageFlags.Exportable); RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PrivateKey; // Hash the data SHA1Managed sha1 = new SHA1Managed(); ASCIIEncoding encoding = new ASCIIEncoding(); byte[] data = encoding.GetBytes(text); byte[] hash = sha1.ComputeHash(data); // Sign the hash return System.Convert.ToBase64String(rsa.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"))); } 

I then created what I thought was the equivalent java code:

public static String signData(String dataToSign, String keyFile) { FileInputStream keyfis = null; try { keyfis = new FileInputStream(fileName); KeyStore store = KeyStore.getInstance("PKCS12"); store.load(keyfis, "TestPassword".toCharArray()); KeyStore.PrivateKeyEntry pvk = (KeyStore.PrivateKeyEntry)store. getEntry("testkey", new KeyStore.PasswordProtection("TestPassword".toCharArray())); PrivateKey privateKey = (PrivateKey)pvk.getPrivateKey(); byte[] data = dataToSign.getBytes("US-ASCII"); MessageDigest md = MessageDigest.getInstance("SHA1"); byte[] hashed = md.digest(data); Signature rsa = Signature.getInstance("SHA1withRSA"); rsa.initSign(privateKey); rsa.update(data); return Base64.encode(rsa.sign()); } catch (Exception ex) { Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex); } finally { if ( keyfis != null ) { try { keyfis.close() } catch (Exception ex) { keyfis = null; } } } return null; } 

Unfortunately the digital signatures do not match.

Any assistance will be greatly appreciated. Thanks in advance.

EDIT: If I remove the MessageDigest from the java code then the output is the same. Why? I thought hashing is needed.

Regards, Eugene

4
  • May be some encoding differences, if it is possible, I would compare bytes that will be signed before signing in java and c#. Commented Jun 27, 2013 at 8:27
  • Hi I did compare the bytes before signing and it was the same going into the sign/SignHash methods Commented Jun 27, 2013 at 8:29
  • Also, check this: stackoverflow.com/questions/1601560/… also, this one: codeproject.com/Articles/6623/… Commented Jun 27, 2013 at 9:10
  • You may provide samples to check. Commented Jun 27, 2013 at 9:46

2 Answers 2

4

The Java sign method does hashing and signing based on the algorithms provided in getInstance method of the Signature class, so basically you were hashing twice in Java.

Sign up to request clarification or add additional context in comments.

Comments

3

Ok so I have confirmed it. If I remove the MessageDigest/Hashing code from the java sample code then the two digital signatures are the same. Not sure why, but I'll try and find out. If anyone would like to educate me further feel free.

3 Comments

That makes sense. In c# you use method SignHash the name of which already tells that it expects a hash to create a signature with. In Java you retrieve an instance of something called SHA1withRSA, I.e. something that does hash and encrypt. Thus, your c# signer requires a pregenerated hash while your Java signer hashes itself.
Thanks mkl. I came across that exact explanation while researching. 500 points to you :)
Furthermore, the class RSACryptoServiceProvider your c# code uses also has a method SignData which works more like the methods in your Java code: It first hashes the data and thereafter applies RSA.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.