What Are The Differences Between C# And Java (Android) When Encrypting Using RSA With PKCS1 Padding?

- 1 answer

I'm encrypting a text using RSA with PKCS1 padding in Java (Android), that I have to send afterwards as part of the body in a webservice. The output of my Java code doesn't work, but if I do it in C#, technically the same algorithm, then it works fine.

This is the C# code that works fine:

static void Main(string[] args)
        var plainData = "plain_text";
        RSA publicKeyEncryptor = getRSAPublic(@"<public_key>");
        var plainBytes = Encoding.ASCII.GetBytes(plainData);
        string encryptedPayload = System.Convert.ToBase64String(publicKeyEncryptor.Encrypt(plainBytes, RSAEncryptionPadding.Pkcs1));

public static RSA getRSAPublic(string publicKey)
        string publicKeyPem = $"-----BEGIN PUBLIC KEY-----\r\n{ publicKey }\r\n-----END PUBLIC KEY-----\r\n";
        var pemReader = new PemReader(new StringReader(publicKeyPem));
        AsymmetricKeyParameter keyPairRaw = (AsymmetricKeyParameter)pemReader.ReadObject();
        RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)keyPairRaw);
        RSA rsaObj = System.Security.Cryptography.RSA.Create();
        return rsaObj;

When I try to convert it to Java (Android), this is the code I came up with, but it doesn't generate a valid output:

public static void main(String args[]) {
    String stringToEncrypt = "plain_text";
    String publicKey = "<public_key>";
    System.out.println(encrypt(stringToEncrypt, publicKey))

public String encrypt(String plain, String publicKey) {
    try {
        byte[] keyBytes = Base64.decode(publicKey, Base64.DEFAULT);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        PublicKey rsaPublicKey = KeyFactory.getInstance("RSA").generatePublic(spec);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);
        byte[] plainTextBytes = plain.getBytes(Charset.forName("US-ASCII"));
        byte[] encryptedBytes = cipher.doFinal(plainTextBytes);
        return Base64.encodeToString(encryptedBytes, Base64.NO_WRAP));
    } catch (Exception e) {
    return "";

What can be different?




Both codes are right. You can encrypt data in same way with Java version and C# version. If one of them is working and another one is failing, probably you are using an incorrect public key (copy/paste error, some different bytes, etc...)