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?
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.
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();
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With