Secure Your Salesforce Data with Encryption and Digital Signatures

May 02, 2025


 

 

In many Salesforce implementations, data security is a top priority. Whether you work with sensitive customer information or internal business secrets, it is necessary to protect data on rest. Salesforce provides strong equipment to handle encryption, and in this blog, we dive into a practical, custom-built example using trigger, Apex crypto methods, and digital signature.

 

Prerequisites

Before implementing the encryption and digital signature logic, let’s first set up the required custom object Test__c with its fields, and create a self-signed certificate in Salesforce named For_Encryption to be used for signing and verifying data.

Step 1: Create the Custom Object Test__c

  1. Navigate to Setup in Salesforce.
  2. Under the Object Manager in Setup, click Create, then select Custom Object.
  3. Name the object Test and set the API Name to Test__c (Salesforce will automatically append __c to the name for custom objects).
  4. Ensure the object is "Deployed" so it’s available for use.
  5. Check the box for Launch New Custom Tab Wizard after saving this custom object.
  6. Optionally, set the Record Name field type to Text or Auto Number, depending on how you want to identify records.

 

Step 2: Create the Fields on Test__c

Now that the custom object is created, we need to add the following fields:

1. Description (Long Text Area)

2. Description 2 (Long Text Area)

3. Checkbox (Checkbox)

 

Step 3: Create a Self-Signed Certificate in Salesforce

To digitally sign data in Apex using the Crypto.signWithCertificate method, you need a certificate stored in Salesforce. Follow these steps to create a self-signed certificate:

1. Navigate to Certificate and Key Management

2. Create a New Self-Signed Certificate

 

The Goal

We want to automatically encrypt or decrypt a field (Description1__c) on a custom object (Test__c) based on the value of a checkbox field (Check_Box__c). If the checkbox is checked, the field should be encrypted and signed. If it's unchecked, we want to decrypt and verify the signature before restoring the original data.

 

Trigger Overview

TestTrigger.apxt
trigger TestTrigger on Test__c (before update) {
    if(Trigger.isBefore) {
        if(Trigger.isUpdate) {
            List<Test__c> testsNew = Trigger.New;
            List<Test__c> testsOld = Trigger.Old;
            if(testsNew[0].Check_Box__c != testsOld[0].Check_Box__c) {
                if(testsNew[0].Check_Box__c == true) {
                    TestHandlerException.onCheck(testsNew[0]);
                }
                else {
                    TestHandlerException.onUncheck(testsNew[0]);
                }
            }
        }
    }
}
 

 

What It Does

This before update trigger watches for changes to the Check_Box__c field. If a user checks or unchecks it:

 

Encryption Handler Class

TestHandlerException.apxc
public class TestHandlerException extends Exception {
    static String algorithmName = 'AES128';
    static String CertName = 'For_Encryption';
    static String signAlgorithmName = 'RSA';
   
    public static void onCheck(Test__c testRecord) {
        try {
            Blob data = Blob.valueOf(testRecord.Description1__c);
            Blob key = Crypto.generateAesKey(128);
            Blob encryptedData = Crypto.encryptWithManagedIV(algorithmName, key, data);
           
            Blob signedEncryptedData = Crypto.signWithCertificate(signAlgorithmName, encryptedData, CertName);
           
            String base64Data = EncodingUtil.base64Encode(encryptedData);
            String base64Signed = EncodingUtil.base64Encode(signedEncryptedData);
            String base64Key = EncodingUtil.base64Encode(key);
           
            Blob specialChar = Blob.valueOf('!@#');
            String base64SpecialChar = EncodingUtil.base64Encode(specialChar);
           
            Integer length = testRecord.Description1__c.length();
            testRecord.Description1__c = testRecord.Description1__c.subString(0,3) + '**********' + testRecord.Description1__c.subString(length-3,length);
            testRecord.Description2__c = base64Data + base64SpecialChar + base64Signed + base64SpecialChar + base64Key;
        }
        catch(Exception e) {
            testRecord.addError('Error while Encryption.');
        }
    }
   
    public static void onUncheck(Test__c testRecord) {
        try {
            String encryptedData = testRecord.Description2__c;
           
            Blob specialChar = Blob.valueOf('!@#');
            String base64SpecialChar = EncodingUtil.base64Encode(specialChar);
           
            List<String> splittedData = encryptedData.split(base64SpecialChar);
            Blob data = EncodingUtil.base64Decode(splittedData[0]);
            Blob signedKey = EncodingUtil.base64Decode(splittedData[1]);
            Blob key = EncodingUtil.base64Decode(splittedData[2]);
           
            Boolean verified = false;
            verified = Crypto.verify(signAlgorithmName, data, signedKey, CertName);
           
            if(verified) {
                testRecord.Description1__c = Crypto.decryptWithManagedIV(algorithmName, key, data).toString();
                testRecord.Description2__c = '';
            }
            else {
                throw new TestHandlerException('Error While Verifying Data With Certificate.');
            }
        }
        catch(Exception e) {
            testRecord.addError(e);
        }
    }
}
 

Method Breakdown

What onCheck() method does:

  1. Converts the input text from Description1__c into a binary Blob.
  2. Generates a 128-bit AES encryption key.
  3. Encrypts the input data using Crypto.encryptWithManagedIV.
  4. Digitally signs the encrypted blob using a certificate named For_Encryption.
  5. Encodes the encrypted data, signature, and AES key into Base64 strings.
  6. Adds a special separator (!@#) between the encoded parts.
  7. Masks the original text in Description1__c for privacy (shows only the first and last 3 characters).
  8. Stores the combined, secure string in Description2__c.

 

What onUncheck() method does:

  1. Splits the Base64 string stored in Description2__c using the encoded !@# separator.
  2. Decodes the encrypted data, digital signature, and AES key from Base64 to Blob.
  3. Verifies the signature using the same certificate to ensure authenticity.
  4. If verified:
    • Decrypts the data and restores it to Description1__c.
    • Clears Description2__c to avoid storing duplicate/old data.
    • If verification fails:
    • Throws a custom exception and shows an error message on the record.

Output:

 

  • Connect with us

  • sales@phenoble.com

  • hr@phenoble.com

  • +91 7850952954


© 2025 Phenoble Software Private Limited