I have some code in Java that successfully verifies and sign messages with SHA256withRSA. However when I try to verify the same data with my c# code, I get a different signature and verification of the signature fails. As the SHA values match, i figure it not related to codepage. I tried multiple ways to figure this one out, but is yet to fail, so any ideas is more than welcome.
import java.nio.file.Files; import java.nio.file.Paths; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.spec.X509EncodedKeySpec; import java.io.*; import java.util.*; import java.security.*; import java.util.Base64; import java.lang.*; import java.nio.charset.*; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMException; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; public class Main { public static void main(String[] args) throws Exception { String privatePem = "c:\\Lab\\Cert\\private.pem"; String publicPem = "C:\\Lab\\Cert\\public.pem"; String datafile = "C:\\Lab\\Cert\\data.txt"; byte[] buf = Files.readAllBytes(Paths.get(datafile)); String message = new String(buf, StandardCharsets.UTF_8); System.out.println("-----------------------------------------------------------------------------------------------------------------------------------------"); System.out.println("Message to sign:"); System.out.println(message); System.out.println("-----------------------------------------------------------------------------------------------------------------------------------------"); PrivateKey privateKey = PrivateKeyReader(privatePem).getPrivate(); PublicKey publicKey = get(publicPem); // Get SHA-256 byte[] messageAsByte = message.getBytes(Charset.forName( "UTF-8" )); byte[] sha256OfMessage = digestSha256(messageAsByte); byte[] sha512OfMessage = digestSha512(messageAsByte); byte[] base64encodedSha256 = Base64.getEncoder().encode(sha256OfMessage); byte[] base64encodedSha512 = Base64.getEncoder().encode(sha512OfMessage); String Sha256ContentDigest = new String(base64encodedSha256, StandardCharsets.UTF_8); String Sha512ContentDigest = new String(base64encodedSha512, StandardCharsets.UTF_8); byte[] signature256 = generateSignature256(messageAsByte, privateKey); String sig25664 = Base64.getEncoder().encodeToString(signature256); System.out.println("X-Content-Digest: SHA256 " + Sha256ContentDigest); System.out.println("X-Signature: RSA-SHA256 " + sig25664); System.out.println("-----------------------------------------------------------------------------------------------------------------------------------------"); byte[] signature512 = generateSignature512(messageAsByte, privateKey); String sig51264 = Base64.getEncoder().encodeToString(signature512); System.out.println("X-Content-Digest: SHA512 " + Sha512ContentDigest); System.out.println("X-Signature: RSA-SHA512 " + sig51264); System.out.println("-----------------------------------------------------------------------------------------------------------------------------------------"); System.out.println("Signature verification SHA256: " + verifySignature256(messageAsByte, sha256OfMessage, signature256, publicKey)); System.out.println("Signature verification SHA512: " + verifySignature512(messageAsByte, sha512OfMessage, signature512, publicKey)); System.out.println("-----------------------------------------------------------------------------------------------------------------------------------------"); } private static KeyPair PrivateKeyReader(String keyPath) { BufferedReader br = null; try { br = new BufferedReader(new FileReader(keyPath)); } catch (FileNotFoundException e) { e.printStackTrace(); } Security.addProvider(new BouncyCastleProvider()); PEMParser pp = new PEMParser(br); PEMKeyPair pemKeyPair = null; try { pemKeyPair = (PEMKeyPair) pp.readObject(); } catch (IOException e) { e.printStackTrace(); } try { KeyPair kp = new JcaPEMKeyConverter().getKeyPair(pemKeyPair); return kp; } catch (PEMException e) { e.printStackTrace(); } try { pp.close(); } catch (IOException e) { e.printStackTrace(); } return null; } public static byte[] generateSignature256(byte[] requestMessage, PrivateKey privateKey) throws Exception { byte[] contentDigest = digestSha256(requestMessage); Signature signature = Signature.getInstance("Sha256withRSA"); signature.initSign(privateKey); signature.update(contentDigest); return signature.sign(); } public static byte[] generateSignature512(byte[] requestMessage, PrivateKey privateKey) throws Exception { byte[] contentDigest = digestSha512(requestMessage); Signature signature = Signature.getInstance("Sha512withRSA"); signature.initSign(privateKey); signature.update(contentDigest); return signature.sign(); } public static boolean verifySignature256(byte[] requestMessage, byte[] requestContentDigest, byte[] requestSignature, PublicKey publicKey) throws Exception { byte[] contentDigest = digestSha256(requestMessage); if (!Arrays.equals(requestContentDigest, contentDigest)) { return false; } Signature signature = Signature.getInstance("Sha256withRSA"); signature.initVerify(publicKey); signature.update(contentDigest); return signature.verify(requestSignature); } public static boolean verifySignature512(byte[] requestMessage, byte[] requestContentDigest, byte[] requestSignature, PublicKey publicKey) throws Exception { byte[] contentDigest = digestSha512(requestMessage); if (!Arrays.equals(requestContentDigest, contentDigest)) { return false; } Signature signature = Signature.getInstance("Sha512withRSA"); signature.initVerify(publicKey); signature.update(contentDigest); return signature.verify(requestSignature); } public static byte[] digestSha256(byte[] requestMessage){ try { MessageDigest digest = MessageDigest.getInstance("SHA-256"); return digest.digest(requestMessage); } catch (Exception e){ return null; } } public static byte[] digestSha512(byte[] requestMessage){ try { MessageDigest digest = MessageDigest.getInstance("SHA-512"); return digest.digest(requestMessage); } catch (Exception e){ return null; } } public static PublicKey get(String keyPath) throws Exception { Reader reader = new FileReader(keyPath); PublicKey key; try { org.bouncycastle.util.io.pem.PemObject spki = new org.bouncycastle.util.io.pem.PemReader(reader).readPemObject(); key = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(spki.getContent())); } catch (Exception ex) { FileInputStream fin = new FileInputStream(keyPath); CertificateFactory f = CertificateFactory.getInstance("X.509"); X509Certificate certificate = (X509Certificate)f.generateCertificate(fin); key = certificate.getPublicKey(); } return key; } } Output:
----------------------------------------------------------------------------------------------------------------------------------------- Message to sign: abc123 ----------------------------------------------------------------------------------------------------------------------------------------- X-Content-Digest: SHA256 bKE9UspwyIPg8LsQHkJaiehiTeUdstI5JZOvaoQRgJA= X-Signature: RSA-SHA256 H9DF4NYV9YOZ3B3iogDIdlTzzQpKGWniQNHF5ZxladLes0MDcFopUSzyO6XiO1Y/AVBGLK18iq2nCc8ho+fXb6c4V08/PSE4lrGJu7z8dAs9UwodDgAx3+TXBV8iNkGtj3XThy7QhvruPA0txRLgdaRmKSJsBSoR7HK6LC0ES2LYzypQFXuQ+4LInWETPc4Ttp9bgSf/h07bZaQMlbO29hIQXZc31WCVTGmsJOG+TMBdF+CpWF04sj12ThR539VCpGrJRrE6xsYSg2VQMgo9t2XkcC/nn3Z4FOMD4o5yuwjHHJO1Hs4wyZfpSehIT96pYwvhkyMM5fS0Ms/Po9WUUg== ----------------------------------------------------------------------------------------------------------------------------------------- X-Content-Digest: SHA512 xwtd2ev7b1HQnUEytxcMnSB1CnhS8AaA9lZY8DEOgQBW5nY8NMmgCw6UAHb1RJXBafwjAszrMSA5JxxDRpUH3A== X-Signature: RSA-SHA512 UT0UlWI06+pYg+OuJGCaoIua23lq/k3yATkO9wQOl7BGLO56t7dvVZQz8UYtzIUhTrDktw9McqyTncDH8bZKMNMMCPLR7K3xAe3gCgipYE8VSP8uVeLDlqKhc/4OO+HDL6T6L44L1dwy5jKBVbVxDDKib7b0lLtTUtTHIh9WOX74hF6P3OiAZ8CD7tJg4QjngJ0GcM9WKXzfDNxVnOzGkhSarhCu3vsUP7QwG2um54uaADgqcJoJvVVyhlwOPF4kPH8SaAPItUIbz46h4bpF182YFZ7QJeg8TmsqXeOdO2MPdKOPYQsPfwZVs/UFkl7Z0oC5WE9UX7Ds9B7/VkOudw== ----------------------------------------------------------------------------------------------------------------------------------------- Signature verification SHA256: true Signature verification SHA512: true ----------------------------------------------------------------------------------------------------------------------------------------- .Net C# code attempt:
using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.OpenSsl; using Org.BouncyCastle.Security; using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace VAS { class Program { static void Main(string[] args) { Console.WriteLine("-----------------------------------------------------------------------------------------------------------------------------------------"); byte[] messageAsByte = File.ReadAllBytes(@"C:\Lab\Cert\data.txt"); Console.WriteLine("Message to sign:"); Console.WriteLine(Encoding.UTF8.GetString(messageAsByte)); Console.WriteLine("-----------------------------------------------------------------------------------------------------------------------------------------"); var publicKey = LoadPublicKey(@"C:\Lab\Cert\public.pem"); var privateKey = LoadPrivateKey(@"C:\Lab\Cert\private.pem"); var sha256OfMessage = digestSha256(messageAsByte); var sha512OfMessage = digestSha512(messageAsByte); string Sha256ContentDigest = Convert.ToBase64String(sha256OfMessage); string Sha512ContentDigest = Convert.ToBase64String(sha512OfMessage); HashAlgorithm hash256Algorith = SHA256Managed.Create(); HashAlgorithm hash512Algorith = SHA256Managed.Create(); byte[] sig256 = privateKey.SignData(messageAsByte, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); byte[] sig512 = privateKey.SignData(messageAsByte, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1); var sig64256 = Convert.ToBase64String(sig256); var sig64512 = Convert.ToBase64String(sig512); Console.WriteLine("X-Content-Digest: SHA256 " + Sha256ContentDigest); Console.WriteLine("X-Signature: RSA-SHA256 " + sig64256); Console.WriteLine("-----------------------------------------------------------------------------------------------------------------------------------------"); Console.WriteLine("X-Content-Digest: SHA512 " + Sha512ContentDigest); Console.WriteLine("X-Signature: RSA-SHA512 " + sig64512); Console.WriteLine("-----------------------------------------------------------------------------------------------------------------------------------------"); var verify256 = publicKey.VerifyData(messageAsByte, CryptoConfig.MapNameToOID("SHA256"), sig256); var verify512 = publicKey.VerifyData(messageAsByte, CryptoConfig.MapNameToOID("SHA512"), sig512); Console.WriteLine("Signature verify 256: " + verify256); Console.WriteLine("Signature verify 512: " + verify512); Console.ReadKey(); } public static RSACryptoServiceProvider LoadPublicKey(String path) { System.IO.StreamReader fileStream = File.OpenText(path); PemReader pemReader = new PemReader(fileStream); AsymmetricKeyParameter KeyParameter = (AsymmetricKeyParameter)pemReader.ReadObject(); RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)KeyParameter); RSACryptoServiceProvider csp = new RSACryptoServiceProvider();// cspParams); csp.ImportParameters(rsaParams); return csp; } public static RSACryptoServiceProvider LoadPrivateKey(String path) { System.IO.StreamReader fileStream = File.OpenText(path); PemReader pemReader = new PemReader(fileStream); AsymmetricCipherKeyPair KeyParameter = (AsymmetricCipherKeyPair)pemReader.ReadObject(); RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)KeyParameter.Private); RSACryptoServiceProvider csp = new RSACryptoServiceProvider();// cspParams); csp.ImportParameters(rsaParams); return csp; } public static byte[] digestSha256(byte[] requestMessage) { SHA256Managed shHash = new SHA256Managed(); return shHash.ComputeHash(requestMessage); } public static byte[] digestSha512(byte[] requestMessage) { SHA512Managed shHash = new SHA512Managed(); return shHash.ComputeHash(requestMessage); } } } Output:
----------------------------------------------------------------------------------------------------------------------------------------- Message to sign: abc123 ----------------------------------------------------------------------------------------------------------------------------------------- X-Content-Digest: SHA256 bKE9UspwyIPg8LsQHkJaiehiTeUdstI5JZOvaoQRgJA= X-Signature: RSA-SHA256 Wo0dFOfzAJJZTb4zpOHkPVdpgWS1K2Q5IdAAD1wQ+w1veAIbmu+XByBHAbme0PiazdqF6QokFm9IudF7NmyqNjNybIKSuTRPUiP474/kliQl7lDiJJoFejBIaVwQhHdds0CkomZZPulZZSYuIi7cqODaKCXxe/Js9tm/htMu3Wd6nejgaoMX3TGXHWyE6ixJI8Zq7ysD6yjksIWlYthsd0WmCR6mVTKR9zo7BiVPxYsOcJ7MFLSvyJgHHoFmXG9KBZhcA1rx8RquvWLGKxU+WWbt7u/9OqY+HKGPCPo2/S1xmdTP2kiVp1zhQ0JQ4uBgP9nkNqrBxh3QzSZgsCbJKg== ----------------------------------------------------------------------------------------------------------------------------------------- X-Content-Digest: SHA512 xwtd2ev7b1HQnUEytxcMnSB1CnhS8AaA9lZY8DEOgQBW5nY8NMmgCw6UAHb1RJXBafwjAszrMSA5JxxDRpUH3A== X-Signature: RSA-SHA512 V47yMVpBunwkUVz0lmi5ZJkYkj2+C9V3YX1MB7OaDvobCGc9F0vBoEsxsV0sDIR2gZsHVMowXFU2bHzIoNdeGz+iyichQ89fJXYP+qPQUZO42t0UXfefX/9LlMbkGlzOqFvfBkcOFidhF9x36ZGPcC6C9AjOC7r1sqL/IBxNENuknhcbBMzHHpJZXFzVo09U/p7LIs3kJxAE9TLkR4ir2syAfisKrbJYCTSZnwm38ikR35mMmigme8eByE6GuOmizshv7lrtd4K5d0RA1jWM1TrNKpLqil4IWbrYQXZCBnHUmLH4fTD7aGIpM+SxQXLBV/lDhWA3O8vXDdFnW0llxQ== ----------------------------------------------------------------------------------------------------------------------------------------- Signature verify 256: True Signature verify 512: True Testkeys and data
private.pem:
-----BEGIN RSA PRIVATE KEY----- MIIEoQIBAAKCAQBk04fDxgG0eV/b7wcTYK7kq72w4YMzlPyBy6hERHWD2DhuM6TQ MF7cafxc4b8krGMBqgV9m7AQxhWn4GCmCHljacXivTc1qBp3S54IitZFqvyGhnC0 dqKshqaL6z/S1kbiPZmiiXpZScYkje5pxY7k11PTopqnV9/g89Cu+PDEd7KcA0XE XbYaEZtufvahZBmbF5mQPAr5YwGDgrR16CiAGi3dcWqX7g7AJb6bSJQp1SEWYVHU klSdOtIJPgTDB57VIC8klKJ0c2Lnn3M+qPl6aD0qLTyl2QH1q97G+7E0e2dYAAbX j0uU8753iEE/nHeOz09ACkIdLw9e97Kmka4DAgMBAAECggEAV9DE1oaGxaFRFEVD bGUw7omGVaCUnUCODJ5Ml+joUUTpIVJpocn/VQoaeutDh7V9Jd3nmlcXKgTcp7KN ew62axec+rbCd0FKi8yYf+gsZ9Fcz+4YC5WoaYt9UzA6DnACnNn6Dc6feVT/9qaH mCgxJK9Gm3VsLYQjwdGZWEwJp5NhBXDHMAPIKJqGfI6v3XI3DOa/VPy4zCMrwMpb Pps0NOMXiwOmWlDVZsDdc36/oICHpib3qHH9Crgbo4i3hDiCCnC97fJiZW6FjfiJ TtXAIPDAfMIW/etLD6lI9O0s3IbcRf4GjnkmM/JMaJnV9mqqN4Nrn57uDyUC5Ged 2/v6gQKBgQCpWGSe16bFYZQsZunJAcdRGqoj0o3dCb3HpB1pnnKdahIsBYguLlnm y2QaVXuFPOUMkRfrOGDITP4hSUiN0hsFT1uThE5IsT4u2KdUe2kSlgWerihPWfuZ UO5w0ag3mgv4avUlg9/wAlRbq7L9s+QivnNxsR6aSuyb+cqLWW8WuQKBgQCYa2bp FTWO5MDRxia4rHvcj+/4bt7zFwX1JUwfbFR8VtUul/Wk5w2JnzEQgF+Td7gJJxv8 u4JJxZNh8TOqek58lyg1KQKSod8mp8CnW9A2utU2MapZsCxyY7T1jgmXVvcXCQ3W eJs1VpgQnoZxbzqbV9muQWjQRCCSR/WQ6hBMmwKBgG7G8vNxkJe30E0HeVFTR4ZH khri5og8khfhxJfN3Z4ZwA9qAv5qtcajMDWFy8qJ3i/NTj9B3xXIP8mYfczAL4rW scobF3a38zyD31oFbOOKndyCgr391/cgGQpWK9tLex8jIIBM9xWzAGoDNJB/t/H+ cdhii+lUr9kMmzFy7JeJAoGABR3V3o0vtxRGxMP6GMjxf331eEmAgniLYqdV3tgs HeBsV5wSSu7WrYACjaNBkhm6u9PsRJem0AMp52fJbDee2t/YIbC2vWVhsFKBTRzv 6GZtMdyI82nOlCh0sqmJ+OKaeNN8+24hB7FYeXZY3QX22bAhRpA7jII89awkujCh S3ECgYBNdGKf5NXxL1n//7GlBsH8sIyNUnHN4dQOORPdSSsynqDcpbdkRFkBIioF 5Q70DOhyS69F8Yu4d1qr09E7AbFpMmQjieDwzdZ6z0b9WInbcKo71FqCaZzz8azt AMG22E827GX9z7F207rPf7GWpvhpGjzbxHXGXSEyFy2CvetpAA== -----END RSA PRIVATE KEY----- public.pem:
-----BEGIN PUBLIC KEY----- MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBk04fDxgG0eV/b7wcTYK7k q72w4YMzlPyBy6hERHWD2DhuM6TQMF7cafxc4b8krGMBqgV9m7AQxhWn4GCmCHlj acXivTc1qBp3S54IitZFqvyGhnC0dqKshqaL6z/S1kbiPZmiiXpZScYkje5pxY7k 11PTopqnV9/g89Cu+PDEd7KcA0XEXbYaEZtufvahZBmbF5mQPAr5YwGDgrR16CiA Gi3dcWqX7g7AJb6bSJQp1SEWYVHUklSdOtIJPgTDB57VIC8klKJ0c2Lnn3M+qPl6 aD0qLTyl2QH1q97G+7E0e2dYAAbXj0uU8753iEE/nHeOz09ACkIdLw9e97Kmka4D AgMBAAE= -----END PUBLIC KEY----- data.txt:
abc123 I also tried signing with OpenSSL, and that gives the same result i get with C#. Any help would be appricated so I can handle the data that is generated in Java.
Thanks!