1

I have an encrypted value from a java server. I need to decrypt it. The documentation of the service gives me the following algorithm for decryption, and the provider will send me the "m" and "e" values:

Java Code:

private  String RSA_Decryption(String encryptedData) 
        throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException,     IOException, IllegalBlockSizeException, BadPaddingException, GeneralSecurityException 
{
    BigInteger m = new BigInteger("verylongnumber1");
    BigInteger e = new BigInteger("verylongnumber2");

    RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e);
    KeyFactory fact = KeyFactory.getInstance("RSA");
    PrivateKey privateKey = fact.generatePrivate(keySpec);

    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
    byte[] decValue = cipher.doFinal(decordedValue);
    String decryptedValue = new String(decValue, "UTF-8");

    return decryptedValue;     
}

I need to convert this in C#. So far, I tried the following C# code (Using BigInteger class from .NET):

string m = "verylongnumber1";
string e = "verylongnumber2";

RSAParameters info = new RSAParameters();
var modulus = BigInteger.Parse(m).ToByteArray();
if (modulus.Length == 129) Array.Resize(ref modulus, 128); // it gives me 129 characters, the last being 0

var exponent = BigInteger.Parse(e).ToByteArray();

info.Modulus = modulus.Reverse().ToArray();
info.D = exponent.Reverse().ToArray();

var encryptedData = Convert.FromBase64String(@"gEQwzXpaARzC2pz9ahiyji8G/K9xecMzh6qi7hMmih4kR4hBwwjfcX83lNet91/hzHX9if1XwAe7/fO5xgXR8qLY+sZu9mj+iXiaSgYyQO3VyxcMD6q/wiVBXpOCX/LmG6qCVbFgn6LZvvcx9fUjVEn3FJFpqUhQh9PvNjmg8ks=");

var decryptedValue = this.Decrypt(encryptedData, info);
string decryptedBarcode = Encoding.Default.GetString(decryptedValue);

byte[] decryptedBytes;
using (RSACryptoServiceProvider rsa1 = new RSACryptoServiceProvider())
{
    rsa1.ImportParameters(info); // throws exception with "Bad data" message
    decryptedBytes = rsa1.Decrypt(encryptedData, false);
}

However, I get an exception with "Bad Data" message when I want to import the keyInfo in rsa1 instance.

I have also tried:

  • setting info.Exponent instead of info.D
  • using BigInteger class provided by Chew Keong and the getBytes method to obtain bytes for modulus and exponent (also, set the arrays in both info.Exponent and info.D with and without reverse).

Everything leads to the same exception with "Bad Data" message.

Can anyone help me with the translation of this java code in a C# equivalent ?

Cosmin Vană
  • 1,562
  • 12
  • 28

1 Answers1

1

unfortunately the standard RSACryptoServiceProvider is not suitable for this specific case ... see for yourself:

if you try to import RSAParameters, there are several fields for you to fill ...

Modulus ... the common modulus for your keypair... m in your case
Exponent ... the public exponent ... part of the public key, used for encryption

D ... the private exponent ... part of the private key, used for decryption, e in your case

P and Q ... the 2 Primes of the keypair ... P*Q=Modulus
DP and DQ ... intermediate values for a mathematical shortcut (chinese remainder theorem) for a faster way of decryption

so ... you got the modulus and the private exponent ... while that's generally enough to be able to decrypt, it is not the full keypair ... P and Q are missing ... with P and Q we could calculate the rest...

the RSACryptoServiceProvider expects you to provide the full keypair if you want to decrypt ... one missing value, and you will get that nasty cryptographicexception telling you "bad data"

soo ... everything lost? no ... some time ago there was another question regarding RSA for which i wrote a few lines that handle RSA by only using bigintegers, and no RSACryptoServiceProvider at all ... Public key encryption with RSACryptoServiceProvider

maybe that helps you getting your value decrypted

Community
  • 1
  • 1
DarkSquirrel42
  • 10,167
  • 3
  • 20
  • 31
  • Your solution works. I've seen it before, however, I wasn't sure the RSACryptoServiceProvider isn't able to solve this task. However, I understand now why it won't work, thanks to your answer. Thank you! – Cosmin Vană Jan 08 '15 at 11:48
  • Note that the code in question asks for PKCS#1 padding. The solution pointed to does not yet remove the padding. The additional parameters are used to perform RSA decryption using the Chinese Remainder Theorem which is faster than RSA using just the private exponent and modulus. Probably the slower RSA version is not implemented. – Maarten Bodewes Jan 09 '15 at 02:30