Create an Encryption Utility Class


Hello, and welcome to Another Salesforce Blog!  Here I will be posting solutions to problems that I couldn’t find an answer to in hopes of helping those who find themselves stuck when using the Salesforce platform.

User Story

We want to mask our data with an AES encryption key, and don’t want to fork out cash for the Salesforce Data Masking package. For example, we are speaking at Forcelandia on July 12th and 13th, 2023, and want to mask some phone numbers in our API project dev org. 😉

Background

The Crypto Class allows us to encrypt and decrypt messages.

Solution

This one was a little bit finicky, but after about an hour of playing around with it, I was able to come up with a solution.

Step One – Create a Custom Metadata Type

A Custom Metadata Type is a piece of metadata that is structurally similar to an sObject that allows us to set a default value for something in our Salesforce org. We are going to call our Custom Metadata Type AES_Key:

A screenshot of the AES Key Custom Metadata Type configuration page.

We will add a custom field called key__c to keep track of, you guessed it, our key.

Step Two – Generate an AES key

Next, we are going to generate our key using Developer Console.

A screenshot of the Anonymous Apex window.

We will enter the command:

System.debug(EncodingUtil.base64Encode(Crypto.generateAesKey(128)));

which will output a key for us in our debug log. Going back to our Custom Metadata Type, we will add a record.

A screenshot of the window to add an AES Key record.

Step Three – Write Apex class

public with sharing class EncryptionUtil {
    
    public static final String CIPHER = 'AES128';

    public static Blob key {
        get {
            return EncodingUtil.base64Decode((AES_Key__mdt.getInstance('Encryption_Key').key__c));
        }
        set;
    }

    public static String encryptString(String stringToEncrypt) {
        Blob data = Blob.valueOf(stringToEncrypt);

        Blob encryptedBlob = Crypto.encryptWithManagedIV(CIPHER, EncryptionUtil.key, data);

        String encryptedString = EncodingUtil.base64Encode(encryptedBlob);

        return encryptedString;
    }

    public static String decryptString(String stringToDecrypt) {
        Blob data = EncodingUtil.base64Decode(stringToDecrypt);

        Blob decryptedBlob = Crypto.decryptWithManagedIV(CIPHER, EncryptionUtil.key, data);

        String decryptedString = decryptedBlob.toString();
        
        return decryptedString;
    }
}

The trickiest part about this was figuring out which decoding methods to use. Let’s break it down line by line.

First, our getter:

    public static Blob key {
        get {
            return EncodingUtil.base64Decode((AES_Key__mdt.getInstance('Encryption_Key').key__c));
        }
        set;
    }

Our encryption key is currently stored as a string in our Custom Metadata setting, so we have to decode it into a Blob.

In our encryptString method, we accept a parameter of a string, convert that string into a blob for use in the Crypto.encryptWithMAnagedIV(String, Blob, Blob) method, output a blob, and then encode that Blob into a String.

    public static String encryptString(String stringToEncrypt) {
        Blob data = Blob.valueOf(stringToEncrypt);

        Blob encryptedBlob = Crypto.encryptWithManagedIV(CIPHER, EncryptionUtil.key, data);

        String encryptedString = EncodingUtil.base64Encode(encryptedBlob);

        return encryptedString;
    }

In our decryptString method, we basically do this in reverse.

We take our parameter of a string, decode it into a blob, and convert it to a string using the .toString() method of the Blob class.

    public static String decryptString(String stringToDecrypt) {
        Blob data = EncodingUtil.base64Decode(stringToDecrypt);

        Blob decryptedBlob = Crypto.decryptWithManagedIV(CIPHER, EncryptionUtil.key, data);

        String decryptedString = decryptedBlob.toString();
        
        return decryptedString;
    }

The trickiest thing about this is knowing which Blob, Crypto, and EncodingUtil methods to use and when.

Basically, we are taking a string, decoding it into Binary, encrypting it, and encoding it back into a String. When we decrypt, we do the opposite.

Step Four – Test our methods

We can test our methods by using Anonymous Apex again:

A screenshot of the Anonymous Apex window in which both the encryptString and decryptString methods are called.

This will yield the following results in the debug log:

A screenshot of the Execution Log with two debug statements showing that the strings were encoded and decoded correctly.

I hope to see you at Forcelandia this summer!

Thanks for reading, let me know if you have any comments or questions!

Evelyn Maguire

Another Salesforce Blog

One-Time
Monthly
Yearly

Make a one-time donation

Make a monthly donation

Make a yearly donation

Choose an amount

$5.00
$15.00
$50.00
$5.00
$15.00
$50.00
$5.00
$15.00
$50.00

Or enter a custom amount

$

Help keep Another Salesforce Blog on the internet by donating today!

Your contribution is appreciated.

Your contribution is appreciated.

DonateDonate monthlyDonate yearly

Leave a Reply

Discover more from Another Salesforce Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading