Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decrypt AES256 value created in Salesforce using C#

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?

like image 446
dotNetkow Avatar asked Mar 12 '13 20:03

dotNetkow


People also ask

What is an advantage of using the Apex Crypto class?

Apex provides the Crypto class to protect our data from eavesdroppers. Apex gives the flexibility to write our own cryptographic functions for ensuring the integrity of our data. Apex provides the Crypto class to protect our data from eavesdroppers.


1 Answers

User 'Doublehead Software" posted a correct solution over on the Salesforce developer boards. 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();
            }
        }
    }
}
like image 69
dotNetkow Avatar answered Oct 11 '22 23:10

dotNetkow