Back

Explore Courses Blog Tutorials Interview Questions
0 votes
1 view
in Salesforce by (11.9k points)

Running the following Apex code in Salesforce, I encrypt a string:

public static String getEncryptedData() { 

    Blob cryptoKey = Crypto.generateAesKey(256);  

    String dataToEncrypt =  'Test string';                                  

    Blob encryptedData = Crypto.encryptWithManagedIV('AES256', cryptoKey, Blob.valueOf(dataToEncrypt));  

    return EncodingUtil.base64Encode(encryptedData);

}

Assuming this implementation is correct, I need to decrypt it in C#. I have the following but am seeing a "Padding is invalid and cannot be removed" error. (Sample key & encrypted string value, of course):

private string Decrypt(string encryptedbase64Password)

{

    RijndaelManaged aes256 = new RijndaelManaged();

    aes256.KeySize = 256;

    aes256.Mode = CipherMode.CBC;

    aes256.Padding = PaddingMode.PKCS7;

    aes256.BlockSize = 128;

    // Salesforce.com stores the first 16 bytes as the IV

    // Extract first 16 bytes as IV, the rest as the Key

    string keyAndIv = "Ii7oSjjWuhp6J6/hj/wmivqx1h3N2HzJ2ByJOy1n89E="; // sample from SFDC

    // hard coded for this example:

    encryptedbase64Password = "hRVlbM79aEQi8Tz7JJIL7CEhSxZAJvCh8Ni6ORP1C55+qbJzjDshBYBjyP12/zT2";

    byte[] allBytes = Convert.FromBase64String(keyAndIv);

    byte[] iv = new byte[16];

    Array.Copy(allBytes, 0, iv, 0, iv.Length);

    byte[] key = new byte[allBytes.Length - 16];

    Array.Copy(allBytes, 16, key, 0, key.Length);

    aes256.Key = key;

    aes256.IV = iv;

    ICryptoTransform decrypto = aes256.CreateDecryptor();

    byte[] encryptedbytes = Convert.FromBase64String(encryptedbase64Password);

    byte[] decryptedText = decrypto.TransformFinalBlock(encryptedbytes, 0, encryptedbytes.Length);

    string result = Convert.ToBase64String(decryptedText);

    return result;

}

What am I doing wrong?

1 Answer

+1 vote
by (32.1k points)

When you encrypt in Salesforce using the encryptWithManagedIV method the first 16 bytes of the returned blob is the IV value the remaining bytes are the phase content.  The following C# code will decrypt your example.  Using the code below decrypting string returned "info string to be decrypted".  Hopefully, this resolves your issue. It appears as though CryptoStream handles the padding issue correctly. Full solution:

string plaintext;

byte[] Key = Convert.FromBase64String("Ii7oSjjWuhp6J6/hj/wmivqx1h3N2HzJ2ByJOy1n89E=");

string encryptedbase64Password = "hRVlbM79aEQi8Tz7JJIL7CEhSxZAJvCh8Ni6ORP1C55+qbJzjDshBYBjyP12/zT2";

byte[] IV = new byte[16];

byte[] phase = Convert.FromBase64String(encryptedbase64Password);

Array.Copy(phase, 0, IV, 0, IV.Length);

byte[] cipherText = new byte[phase.Length - 16];;

Array.Copy(phase, 16, cipherText, 0, cipherText.Length);

using (AesManaged aesAlg = new AesManaged())

{

    aesAlg.KeySize = 256;

    aesAlg.Mode = CipherMode.CBC;

    aesAlg.Padding = PaddingMode.PKCS7;

    aesAlg.Key = Key;

    aesAlg.IV = IV;

    // Create a decryptor to perform the stream transform.

    // NOTE: This is the difference between my original solution and the correct one.

    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

    // Create the streams used for decryption.

    using (MemoryStream msDecrypt = new MemoryStream(cipherText))

    {

        using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))

        {

            using (StreamReader srDecrypt = new StreamReader(csDecrypt))

            {

                // Read the decrypted bytes from the decrypting stream and place them in a string.

                plaintext = srDecrypt.ReadToEnd();

            }

        }

    }

}

Related questions

+1 vote
1 answer
0 votes
1 answer
0 votes
1 answer
0 votes
1 answer
Welcome to Intellipaat Community. Get your technical queries answered by top developers!

28.4k questions

29.7k answers

500 comments

94.2k users

Browse Categories

...