key__c :- abcdefghijklmnop 
public static String decrypt(String data) {
    EncryptionSettings__c settings = EncryptionSettings__c.getOrgDefaults();
    if (settings.key__c == null) {
        throw new FacebookException('Cannot decrypt without a key!');
    Blob key = EncodingUtil.base64Decode(settings.key__c);
    return Crypto.decryptWithManagedIV('AES128', key, EncodingUtil.base64Decode(data)).toString();

public static String encrypt(String data) {    
    EncryptionSettings__c settings = EncryptionSettings__c.getOrgDefaults();
    Blob key = null;
    if (settings.key__c == null) {
        key = Crypto.generateAesKey(128);
        settings.key__c = EncodingUtil.base64Encode(key);
        insert settings;
    } else {
        key = EncodingUtil.base64Decode(settings.key__c);
    return EncodingUtil.base64Encode(Crypto.encryptWithManagedIV('AES128', key, Blob.valueOf(data)));

If key__c == 'abcdefghijklmnop', then it's not 16 bytes when decoded. This is because Base-64 encodes 3 bytes as 4 bytes, so this actually a 12-byte blob in the end. You would need to have a key more like this: 'abcdefghijklmnopqrstuv=' in order to get 16 bytes back out.

| improve this answer | |
  • Sir, I got Error :- Input length must be multiple of 16 when decrypting with padded cipher. Used "abcdefghijklmnopqrstuv=" as key. – Innodel Salesforce Jan 16 '17 at 9:29
  • @InnodelSalesforce So the key is okay now, but the input is wrong. Can you post how you encrypted and decrypted the data? – sfdcfox Jan 16 '17 at 15:53

The Crypto Class documentation calls a method to generate the key suggesting the key may not be something that you can arbitrarily set:

Blob key = Crypto.generateAesKey(128);
Blob data = Blob.valueOf('Data to be encrypted');
Blob encrypted = Crypto.encryptWithManagedIV('AES128', key, data);

Blob decrypted = Crypto.decryptWithManagedIV('AES128', key, encrypted);
String decryptedString = decrypted.toString();
System.assertEquals('Data to be encrypted', decryptedString);

In some working code that I have, the code generates and stores a base 64 encoded version of the key in a protected custom setting the first time it runs (i.e. when the custom setting is null), and from then on reads that custom setting and base 64 decodes the value back into a Blob to use the value.

| improve this answer | |
  • Yes, you can use any arbitrary key that meets the requirement. Blob secretKey = Blob.valueOf('1234567890123456'); Blob clearData = Blob.valueOf('Hello World'); Blob encryptedData = Crypto.encryptWithManagedIV('AES128', secretKey, clearData); Blob decryptedData = Crypto.decryptWithManagedIV('AES128', secretKey, encryptedData); System.debug(clearData.toString()); System.debug(EncodingUtil.convertToHex(encryptedData)); System.debug(decryptedData.toString()); – sfdcfox Jan 13 '17 at 13:38
  • This allows you to interact with other systems by obtaining a secret key from, say, ssh-keygen, or Eclipse IDE, or another salesforce org, or a certificate, etc... The Crypto.generateAesKey, and other related functions create secure keys, though, so if the key isn't coming from an outside source, it shouldn't be hand-crafted. There are algorithms in place for a reason. And I really hope I didn't just expose someone's private key... – sfdcfox Jan 13 '17 at 13:40

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.