Use Encryption in Custom Applications

Learning Objectives

After completing this unit, you'll be able to:

  • Describe the Apex Crypto class.
  • Explain the different use cases for the Apex Crypto class and custom encryption.
  • Use this knowledge to implement encryption in your own application.

What Is the Apex Crypto Class?

When it comes to implementing encryption in your Salesforce application, Apex gives you the flexibility to write your own custom cryptographic functions, while also granting you the ability to leverage a wide range of prebuilt functions. In this unit, we go through some of the powerful functions Salesforce offers at your disposal for creating digests, message authentication codes (MACs), signatures, and encryption/decryption functions via the Apex Crypto class.

The Crypto class provides sets of functions that are particularly valuable for safeguarding your communications against eavesdropping and ensuring integrity of your data. Using these functions, you can effectively shield confidential data from eavesdroppers, verify that message data is complete and unmodified, and verify the authenticity of senders and receivers. These functions each support a range of different algorithms, allowing you a good degree of control over the composition of your solution, while still minimizing the burden of extra work required to secure your application.

Encryption and Decryption to Protect Confidentiality 

Encryption and decryption can be handled with ease and flexibility with the Apex Crypto.Encrypt() and Crypto.Decrypt() functions, which support AES128, AES192, and AES256 algorithms. Encryption and decryption functions are essential for ensuring the confidentiality of your application data. You then have the option to generate your own encryption key, or use the Crypto.generateAESKey(Integer keylength) method. To secure the encryption keys, you can use techniques you practiced in the previous unit for storing secrets in protected custom metadata types or protected custom settings.

Hash Digests to Protect Integrity

Another useful function for verifying data integrity is the Apex Crypto.generateDigest() function. This method generates a one-way hash digest, and supports algorithms such as MD5, SHA1, SHA256, and SHA512. These hash digests can serve a valuable purpose in identifying accidental data corruption (or other unwanted modifications). By performing comparison checks on hash digests, you can quickly discover changes to data, because the recomputed digest of that data will not match the original digest, thus confirming that the data has been modified. This can alert you to events such as data corruption, accidental changes, or malicious alterations.

Note that hashing algorithms have varying degrees of strength in terms of security. Although MD5 is supported by the Crypto class, it’s considered as a weak hashing algorithm, so Salesforce suggests using SHA1 or higher to compute hash digests.

Hash-Based Message Authentication Codes (MAC) to Prove Authenticity and Integrity

Another useful function is the Apex Crypto.generateMac() method, which can be used to create message authentication codes (MACs). MACs can be used alongside message digest functions to set up hashed MACs (HMACs). HMACs are used in both TLS and IPSec protocols for authenticating message senders and ensuring that messages are not modified (or interceptable) in transit.

The Crypto.generateMac() method supports the HMACMD5, HMACSHA1, HMACSHA256, and HMAC512 algorithms. HMAC functions involve the use of message digests and a private key that the sender uses to encrypt a MAC, and which the receiver uses to decrypt the MAC. Because the receiver has to decrypt the MAC using the shared private key, you can verify the authenticity of the message sender. The message digests can then be compared to allow the receiver to confirm that the message wasn’t modified in transit (that is, via a Man-in-the-Middle attack).

Creating a Digital Signature

To generate a digital signature, you can use the Crypto.sign() function, which uses the SHA1 algorithm to create a digest, which is then subsequently encrypted with a private key using RSA. Digital signatures ensure both the integrity and authenticity of messages. With this setup, the receiver of a message can use a public key to decrypt a message (which was encrypted with the sender’s private key), and then compare the message digest sent with a digest generated from the received message, allowing the receiver to verify its integrity.

Use Apex Crypto

Now that we’ve covered some of the functions in the Apex Crypto class, let’s try them out.

  1. Log in to the Kingdom Management org.

  2. Select the Secret Storage app from the App Picker.

  3. Click the Apex Encryption Demo tab. Currently in this demo, monarchs of the royal family are sending cleartext, unencrypted messages from one kingdom to another. The goal of this demo is to implement custom encryption using functions of the Apex Crypto class so that kingdoms can exchange messages securely. The kingdom that receives the message can decrypt it by clicking Decrypt Message. The most recent messages are always at the top.

    use-encryption-in-custom-applications

  4. Click the Apex Controller link at the bottom of the page to view the code.

  5. Oops—looks like the kingdom developers haven’t implemented encryption correctly! Currently the messages are shown in clear text or unencrypted form. We’re going to change that and implement encryption on these messages so that only those with access to our crypto key can decrypt the messages. Here’s the Save() function code that saves the messages in the database.

     public PageReference Save(){ 
     if (!Schema.sObjectType.Encrypt_DecryptC__c.fields.Name.isCreateable()){
       return NULL; 
       } try { 
        if(pitemName != NULL && pitemName != '') { 
         if(encrypt.Name.length < 80) { 
          //Add code here
          
           insert encrypt; 
           encrypt.id = null; 
           getMessage();
           } 
          } } catch (Exception e){ 
          ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severrity.FATAL, 'Empty string or handling an error!'); 
          ApexPages.addMessage(myMsg); 
         } 
         return NULL; 
        } 
        
  6. Let’s modify our class and add functionality to encrypt the messages. Search for a function called Save() and implement AES128 (For production enviornment we recommend AES256) encryption. We’re using encryptWithManagedIV function from the Apex Crypto class. The final code looks like this.

     public PageReference Save(){ 
      if (!Schema.sObjectType.EnCrypt_DecryptC__c.fields.Name.isCreateable()) { 
        return NULL; 
          } try { 
            if(pitemName != NULL && pitemName != ''){ 
              if(encrypt.Name.length() < 80) { 
              Blob data = Blob.valueOf(encrypt.Name); 
              Blob encryptedData = Crypto.encryptWithManagedIV('AES128', cryptoKey, data ); 
              String b64Data = EncodingUtil.base64Encode(encryptedData); 
              encrypt.name = b64Data; 
              insert encrypt;encrypt.id = null; 
              getMessages(); 
            } 
          } } catch (Exception e){ 
          ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.FATAL, 'String empty or handling an error!'); 
          ApexPages.addMessage(myMsg); 
        } 
      return null; 
      } 
    

  7. So far, we’ve successfully modified the Save function(), which is used to encrypt and save the messages. Now we’re going to modify the decryption function to properly decode the messages. In the same class, search for a function named DecryptMe() and use Crypto.decryptWithManagedIV() method with cryptokey to decrypt the messages and display them in plaintext to the user. The final code looks like this.

     public PageReference DecryptMe(){ 
      if(pitemName != NULL && pitemName != ''){ 
       Blob data = EncodingUtil.base64Decode(pitemName); 
       Blob decryptedData = Crypto.decryptWithManagedIV('AES128', cryptoKey, data); 
       String dryptData = decryptedData.toString(); 
       paramValue = dryptData; 
      } else { 
       System.debug('PitemName was NULL '); 
      } 
     return null; 
    } 

  8. If you’ve been following along and modifying the code in your org, delete any existing messages and try sending some new messages between the kingdoms. Now that you’ve implemented AES128 (For production environment we recommend AES256) encryption, the messages should now be encrypted. No rival kingdoms can eavesdrop or intercept them, because these messages can only be decrypted with the right cryptographic key, which we’ll keep safely stored away in protected custom metadata fields or settings.

That’s it! Now our kingdom can use this application to send secure encrypted messages to other kingdoms.

Conclusion

In the first unit, we reviewed the basics of application secrets, and the vital importance of keeping them secure. Throughout the second and third units, we learned how to use the Salesforce platform effectively to safeguard these secrets. We went through some of the powerful functions offered by the Apex Crypto class that we can use to implement secure communications. We also learned how protected custom settings and protected custom metadata fields can be used to securely store application secrets, such as encryption keys. When used in tandem, the techniques and methods practiced in these units can comprise a security solution powerful enough to turn a defenseless kingdom into an impenetrable fortress.

Resources

Apex Developer Guide: Crypto Class

Note

Note

Remember, this module is meant for Salesforce Classic. When you launch your hands-on org, switch to Salesforce Classic to complete this challenge.

retargeting