views:

545

answers:

1

I am encrypting on JAVA using RSA and attempting to decrypt using .NET. I am including my JAVA code and .NET code in hopes that someone has some experience with this sort of thing.

JAVA Code:

   byte[] modulusBytes = Base64.decode("xTSiS4+I/x9awUXcF66Ffw7tracsQfGCn6g6k/hGkLquHYMFTCYk4mOB5NwLwqczwvl8HkQfDShGcvrm47XHKUzA8iadWdA5n4toBECzRxiCWCHm1KEg59LUD3fxTG5ogGiNxDj9wSguCIzFdUxBYq5ot2J4iLgGu0qShml5vwk=");
   byte[] exponentBytes = Base64.decode("AQAB");
   BigInteger modulus = new BigInteger(1, modulusBytes );               
   BigInteger exponent = new BigInteger(1, exponentBytes);

   RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, exponent);
   KeyFactory fact = KeyFactory.getInstance("RSA");
   PublicKey pubKey = fact.generatePublic(rsaPubKey);

   Cipher cipher = Cipher.getInstance("RSA");
   cipher.init(Cipher.ENCRYPT_MODE, pubKey);

   byte[] plainBytes = new String("big kitty dancing").getBytes("UTF-8");
   byte[] cipherData = cipher.doFinal( plainBytes );
   String encryptedString = Base64.encodeBytes(cipherData);

From this JAVA Code I take the results of the encryptedString which happen to be:

FoP4+AAIH6hcabXnrvNG5YUk/nBv9n9HU0CAgZjkIWQIDjbOpSwoPVBFERrZ6641x2QaoJw5yv18XAay+0WrCaSw4sveRX+hmPm5qeVUPcjoR4slsVZ/hBFJtAHj9tva4hOugWDZa9s3RVJlxkNfE+u+Kt/YKLOi2EYbH05HjeM=

And attempt to decrypt using the following .NET code

   const int PROVIDER_RSA_FULL = 1;
   const string CONTAINER_NAME = "Tracker";

   CspParameters cspParams;
   cspParams = new CspParameters(PROVIDER_RSA_FULL);
   cspParams.KeyContainerName = CONTAINER_NAME;
   RSACryptoServiceProvider rsa1 = new RSACryptoServiceProvider(cspParams);
   rsa1.FromXmlString("<RSAKeyValue><Modulus>xTSiS4+I/x9awUXcF66Ffw7tracsQfGCn6g6k/hGkLquHYMFTCYk4mOB5NwLwqczwvl8HkQfDShGcvrm47XHKUzA8iadWdA5n4toBECzRxiCWCHm1KEg59LUD3fxTG5ogGiNxDj9wSguCIzFdUxBYq5ot2J4iLgGu0qShml5vwk=</Modulus><Exponent>AQAB</Exponent><P>+lXMCEwIN/7+eMpBrq87kQppxu3jJBTwztGTfXNaPUTx+A6uqRwug5oHBbSpYXKNDNCBzVm/0VxB3bo4FJx+ZQ==</P><Q>yasOGaJaE9xlF9T2xRuKeG9ZxCiyjhYaYB/mbtL+SIbtkRLi/AxaU4g2Il/UxhxhSXArKxIzV28zktispPJx1Q==</Q><DP>ueRgQIEFUV+fY979a1RgrVHIPpqEI1URhOMH3Q59oiXCcOumM5njyIHmWQxRAzXnG+7xlKXi1PrnRll0L4oOKQ==</DP><DQ>dfEMNgG1HJhwpxdtmqkYuoakwQvsIRzcIAuIAJh1DoWaupWJGk8/JEstHb1d+t7uJrzrAi2KyT/HscH2diE0YQ==</DQ><InverseQ>YoYF9PF6FiC0YngVeaC/eqt/ea8wMYNN3YO1LuzWpcy2exPRj2U0ZbWMvHXMUb4ea2qmhZGx1QlK4ULAuWKpXQ==</InverseQ><D>g1WAWI4pEK9TA7CA2Yyy/2FzzNiu0uQCuE2TZYRNiomo96KQXpxwqAzZLw+VDXfJMypwDMAVZe/SqzSJnFEtZxjdxaEo3VLcZ1mnbIL0vS7D6iFeYutF9kF231165qGd3k2tgymNMMpY7oYKjS11Y6JqWDU0WE5hjS2X35iG6mE=</D></RSAKeyValue>");

   string data2Decrypt =    "FoP4+AAIH6hcabXnrvNG5YUk/nBv9n9HU0CAgZjkIWQIDjbOpSwoPVBFERrZ6641x2QaoJw5yv18XAay+0WrCaSw4sveRX+hmPm5qeVUPcjoR4slsVZ/hBFJtAHj9tva4hOugWDZa9s3RVJlxkNfE+u+Kt/YKLOi2EYbH05HjeM=";

   byte[] encyrptedBytes = Convert.FromBase64String(data2Decrypt);  

   byte[] plain = rsa1.Decrypt(encyrptedBytes, false);
   string decryptedString = System.Text.Encoding.UTF8.GetString(plain);
+2  A: 

On the Java side, you need to use "RSA/ECB/PKCS1Padding" as algorithm name. With the plain "RSA" name, Java does not add the PKCS#1 padding which the C# implementation expects, hence the "bad data".

The padding is a transformation of the input data (your encoded string) into a somewhat larger string which has the same length than the RSA modulus (128 bytes here). It is important for security and injects some randomness (the same input string will not yield the same encrypted string every time; but the decryption process removes that randomness and recovers the right string nonetheless).

Thomas Pornin
Always explicitly define the mode and padding in Java since there are no guarantees about what will be used when you don't. Does C#/.NET have some equivalent I wonder?
laz
Thomas I hope you are always around when I have encryption problems! That absolutely fixed the problem.laz - RSACryptoServiceProvider.KeyExchangeAlgorithm is the property you set. The default ( as Thomas Pornin pointed out ) is "RSA-PKCS1-KeyEx".
badMonkey
No. If you specify Cipher.getInstance("RSA") you get "RSA/ECB/PKCS1Padding".
GregS
Greg I didn't see that behaviour. When I implemented the single change that Thomas suggested the data was decryped OK on the .net side. "RSA-PKCS1-KeyEx" is the algorithm name on the .net side.
badMonkey