4

Our security team has found an issue in our lightning experience site where a link to an external system is adding the account # in the URL. That system is then using that account # to display data on their site related to the account.

This means any user who can access this link can modify the account # in the URL and see other people's data in the external system (big oops to whomever designed that).

I was thinking the easiest way to fix this is to encrypt the account # so the external system can still grab the encrypted # from the URL, decrypt it, and show the correct information.

Below is the code I created to encrypt this account # in Apex (This is just a sample key):

private static final Blob KEY = EncodingUtil.base64Decode('ZZZB0LSDWRlPSpOR3LgqSpZdN0DCJYcxohJ/K3oPsA=');

private static String encryptString(String clearText) {
    Blob encryptedBlob = Crypto.encryptWithManagedIV('AES256', KEY, Blob.valueOf(clearText));
    String encryptedText = EncodingUtil.base64Encode(encryptedBlob);
    return encryptedText;
}

I told the external systems developer to use the key provided above as well as AES256 to decrypt the value and he says this isn't enough info.

How can I encrypt a value in a way where another system can decrypt it? Is it as simple as giving him the key and the encryption method (AES256)?

Thanks

2 Answers 2

7

David is absolutely right and I'd like to add some extra information and provide code examples regarding Apex-encryption/C#-decryption.

To encrypt some String in Apex using the AES256-CBC algorithm you can:

  1. Generate private key:
final Blob privateKey = Crypto.generateAesKey(256);
  1. Store somewhere the generated key as Base64 String:
// System.debug(LoggingLevel.INFO, EncodingUtil.base64Encode(privateKey)); 
// e.g. 'lX8rtkgjlgQ5fyWH+G8XUPLlc04zZ8lTtrxpJSlmdhs='
  1. Create the encrypt method in the Encryptor class:
public static String encrypt(final String clearText, final String key) {
    final Blob encrypted = Crypto.encryptWithManagedIV(
        'AES256',
        EncodingUtil.base64Decode(key),
        Blob.valueOf(clearText)
    );
    return EncodingUtil.base64Encode(encrypted);
}

The catch here is that Crypto.encryptWithManagedIV() method

stores the initialization vector as the first 128 bits (16 bytes) of the encrypted Blob.

This information is crucial and we will use it for decryption later.

  1. Then you can encrypt some string text and send it to an external system as Base64 string:
Encryptor.encrypt('Hello World', 'lX8rtkgjlgQ5fyWH+G8XUPLlc04zZ8lTtrxpJSlmdhs='); 
// 'QEwvBfLu5luAdlWb0Yk96eu4X0egOIYtHl0nJn+UJlc='
  1. To decrypt a string using AES256-CBC algorithm in C# write the next method using Aes Class (AesManaged, RijndaelManaged and Rijndael classes are obsolete):
static string Decrypt(string iVAndCipherText, string keyStr) {
    byte[] encryptedBytes = Convert.FromBase64String(iVAndCipherText);
    byte[] cipherTextBuffer = new byte[encryptedBytes.Length - 16];
    // Copies a payload skipping first 16 bytes into cipherTextBuffer var
    Array.Copy(encryptedBytes, 16, cipherTextBuffer, 0, cipherTextBuffer.Length); 
    byte[] iv = new byte[16];
    // Copies the first 16 bytes of a payload as IV into iv var
    Array.Copy(encryptedBytes, iv, 16);
    Aes aes = Aes.Create("AesManaged")!;
    // aes.BlockSize = 128; by default
    // aes.KeySize = 256; by default
    // aes.Mode = CipherMode.CBC; by default
    // aes.Padding = PaddingMode.PKCS7; by default
    aes.Key = Convert.FromBase64String(keyStr);
    aes.IV = iv;
    ICryptoTransform decryptor = aes.CreateDecryptor();
    byte[] decryptedData = decryptor.TransformFinalBlock(cipherTextBuffer, 0, cipherTextBuffer.Length);
    return Encoding.UTF8.GetString(decryptedData);
}

Once again, the catch here was to take first 16 bytes as IV and the rest bytes as the payload to be decrypted.

Result:

string iVAndCipherText = "QEwvBfLu5luAdlWb0Yk96eu4X0egOIYtHl0nJn+UJlc="; // Payload gotten from Apex (p.4)
string key = "lX8rtkgjlgQ5fyWH+G8XUPLlc04zZ8lTtrxpJSlmdhs="; // AES256 generated key (p.2)
string decrypted = Decrypt(iVAndCipherText, key);
Console.WriteLine(decrypted); // "Hello World"
4

The data I would think an external systems developer would need are:

  • The algorithm: AES256.
  • The cipher mode: Cipher Block Chaining (CBC), as documented for the Apex Crypto class.
  • The padding mode: PKCS7 (same link).
  • The fact that you are using a managed initialization vector.
  • The fact they you're transmitting the data in Base64.
  • And of course, the key.

Apex cryptography provides a much more limited set of options than most cryptography libraries in other languages, so you'll probably need to share these built-in assumptions with your colleague.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.