Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Port RSA encryption Java code to C#

I'm trying to port the following Java code to a C# equivalent:

public static String encrypt(String value, String key) throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
    byte[] bytes = value.getBytes(Charset.forName("UTF-8"));
    X509EncodedKeySpec x509 = new X509EncodedKeySpec(DatatypeConverter.parseBase64Binary(key));
    KeyFactory factory = KeyFactory.getInstance("RSA");
    PublicKey publicKey = factory.generatePublic(x509);
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    bytes = cipher.doFinal(bytes);
    return DatatypeConverter.printBase64Binary(bytes);
}

So far I managed to write the following in C#, using the BouncyCastle library for .NET:

public static string Encrypt(string value, string key)
    {
        var bytes = Encoding.UTF8.GetBytes(value);
        var publicKeyBytes = Convert.FromBase64String(key);
        var asymmetricKeyParameter = PublicKeyFactory.CreateKey(publicKeyBytes);
        var rsaKeyParameters = (RsaKeyParameters) asymmetricKeyParameter;
        var cipher = CipherUtilities.GetCipher("RSA");
        cipher.Init(true, rsaKeyParameters);
        var processBlock = cipher.DoFinal(bytes);
        return Convert.ToBase64String(processBlock);
    }

The two methods, though, produce different results even if called with the same parameters. For testing purposes, I'm using the following public RSA key:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLCZahTj/oz8mL6xsIfnX399Gt6bh8rDHx2ItTMjUhQrE/9kGznP5PVP19vFkQjHhcBBJ0Xi1C1wPWMKMfBsnCPwKTF/g4yga6yw26awEy4rvfjTCuFUsrShSPOz9OxwJ4t0ZIjuKxTRCDVUO7d/GZh2r7lx4zJCxACuHci0DvTQIDAQAB

Could you please help me to port the Java code successfully or suggest an alternative to get the same result in C#?

EDIT1: output in Java is different each time I run the program. I don't think that any padding was specified, so I don't understand what makes the output random.

EDIT2: Java uses PKCS1 by default, so it was enough to specify it in the C# cipher initialization to get the same encryption type (although not the same result, which was irrelevant at this point).

like image 598
user1098567 Avatar asked Jun 14 '12 23:06

user1098567


1 Answers

As an educated guess, I would say that Java adds random padding to create a stronger encryption.

Most practical implementations of RSA do this, and as the wiki puts it...

Because RSA encryption is a deterministic encryption algorithm – i.e., has no random component – an attacker can successfully launch a chosen plaintext attack against the cryptosystem, by encrypting likely plaintexts under the public key and test if they are equal to the ciphertext. A cryptosystem is called semantically secure if an attacker cannot distinguish two encryptions from each other even if the attacker knows (or has chosen) the corresponding plaintexts. As described above, RSA without padding is not semantically secure.

This is likely why your two methods don't output the same.

like image 107
James Williams Avatar answered Nov 14 '22 13:11

James Williams