Java equivalent of .NET RSACryptoServiceProvider with SHA-1
.net, android, c#, cryptography, java
Solution
Use `Signature.getInstance("SHA1withRSA")`. Encryption is not the same as signature generation. Different padding mechanisms for one.
Update by Afshin
Complete solution. Note the use of the private exponent, ie `<D>`, rather the public `<Exponent>`
String modulusElem = "...";
String dElem = "...";
byte[] modulusBytes = Base64.decode(modulusElem, Base64.DEFAULT);
byte[] dBytes = Base64.decode(dElem, Base64.DEFAULT);
BigInteger modulus = new BigInteger(1, modulusBytes);
BigInteger d = new BigInteger(1, dBytes);
String data = "my data";
try {
Signature signature = Signature.getInstance("SHA1withRSA");
KeyFactory factory = KeyFactory.getInstance("RSA");
RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(modulus, d);
PrivateKey privateKey = factory.generatePrivate(privateKeySpec);
signature.initSign(privateKey);
signature.update(data.getBytes("UTF-8"));
byte[] SignedByteData = signature.sign();
} catch(Exception e) {
e.printStackTrace();
}
Problem
I have the following data signing code in C# ``` RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); string PrivateKeyText = "<RSAKeyValue><Modulus>....</D></RSAKeyValue>"; rsa.FromXmlString(PrivateKeyText); string data = "my data"; byte[] SignedByteData = rsa.SignData(Encoding.UTF8.GetBytes(data), new SHA1CryptoServiceProvider()); ``` and I want reproduce the same code in Java (Android): ``` String modulusElem = "..."; String expElem = "..."; byte[] expBytes = Base64.decode(expElem, Base64.DEFAULT); byte[] modulusBytes = Base64.decode(modulusElem, Base64.DEFAULT); BigInteger modulus = new BigInteger(1, modulusBytes); BigInteger exponent = new BigInteger(1, expBytes); try { KeyFactory factory = KeyFactory.getInstance("RSA"); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); String data = "my data"; MessageDigest md = MessageDigest.getInstance("SHA-1"); byte[] hashedData = md.digest(data.getBytes("UTF-8")); RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(modulus, exponent); PublicKey publicKey = factory.generatePublic(pubSpec); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] SignedByteData = cipher.doFinal(hashedData); } catch (Exception e){ } ``` But I get mismatched output byte arrays. Where am I wrong and What should be the transformation used in `Cipher.getInstance(...)` ?