I have a VF page that I pass in parameters to such as Contact Id. As such, I don't want people clicking the links to see the actual Id since that doesn't seem very secure.

So I build a simple encrypt/decrypt routine which is what I use in an email merge etc

Blob cipherText = Crypto.encryptWithManagedIV('AES256', getKey(), Blob.valueOf(sLink));
String encodedCipherText = EncodingUtil.convertToHex(cipherText); 
return EncodingUtil.urlEncode(encodedCipherText,'UTF-8') ;

This works fine, but the generated URL is very long which makes it difficult to copy and share. I know I can use URL shortners but I was wondering if there is a way to make a shorter link that I can still then read with my decryption utility?

  • Why don't you feel the Id is secure? It's a unique identifier for the record whether it's encrypted or not. – Alex Tennant Jun 16 '14 at 11:08
  • 2
    Because you can easily guess them if you know the format - insert a bunch of contacts, and you'll see a sequence - I don't want someone to see an Id in the URL on a public page, and think, if I change the last letter from p to q, what happens, and someone else's data appears... – BritishBoyinDC Jun 16 '14 at 11:10

I think one way would be sum up the URL to SHA-256 and store it to different table together with actual URL. Then on page load search for it.

Using SHA1/MD5 would result to similar length of Salesforce ID, hence it's kind of pointless, unless you are still building a gatekeeper that is smart enough (hint: it wont, unless you use machine learning) to monitor requests.

The basis of your question is a fallacy. You wan't to introduce some security, but then you wan't to reduce it :)

Below some code and results.

    Blob key = Blob.valueOf('1234567812345678');
    Blob data = Blob.valueOf('Data to be encrypted');
    Blob encrypted = Crypto.encryptWithManagedIV('AES128', key, data);
system.debug('MD5 '+ EncodingUtil.base64Encode((Crypto.generateDigest('MD5',encrypted))).length() +
            ' SHA1 '+ EncodingUtil.base64Encode((Crypto.generateDigest('SHA1',encrypted))).length() +
            ' SHA-256 '+ EncodingUtil.base64Encode((Crypto.generateDigest('SHA-256',encrypted))).length() +
            ' SHA-512 '+ EncodingUtil.base64Encode((Crypto.generateDigest('SHA-512',encrypted))).length() +
            ' AES128 '+ EncodingUtil.base64Encode(encrypted).length());

USER_DEBUG [17]|DEBUG|MD5 24 SHA1 28 SHA-256 44 SHA-512 88 AES128 64

Edit: I now see that you are using function convertToHex. Base64Encode will result in shorter URLs as it is using more characters to encode URL.

| improve this answer | |

I know this is a year late but I had similar concerns in the past and the information I have should help remedy those.

To answer your question, here is a standard example of how to encrypt strings using apex.

Source: https://developer.salesforce.com/page/Apex_Crypto_Class

// Generate an AES key for the purpose of this sample. 
// Normally this key should be stored in a protected custom setting 
// or an encrypted field on a custom object
Blob cryptoKey = Crypto.generateAesKey(256);

// Generate the data to be encrypted.
Blob data = Blob.valueOf('Test data to encrypted');
// Encrypt the data and have Salesforce.com generate the initialization vector
Blob encryptedData = Crypto.encryptWithManagedIV('AES256', cryptoKey, data);
// Decrypt the data - the first 16 bytes contain the initialization vector
Blob decryptedData = Crypto.decryptWithManagedIV('AES256', cryptoKey, encryptedData);

// Decode the decrypted data for subsequent use
String decryptedDataString = decryptedData.toString();

However, I would urge you not to do this because you should instead manage object/field permissions based on profile/roles to protect data that shouldn't be seen by particular users. Encrypting ids will become a huge hassle and ultimately give a false sense of security as you're merely making the task take just a little bit more time. You'll do yourself and everyone in your organization a huge favor by investing a bit of time into using the standard security tools in your org rather than relying on secret keys in code and awkward implementations to prevent users from url cracking.

| improve this answer | |
  • Just to clarify - this is nothing to do with internal users - this is when I want to send a link to an external Contact that takes them to a force.com sites page, and it will pre-populate their contact data so they can take an action. So FLS etc won't help me - what I need to make sure is that someone with a link can't guess the Id of another contact - the encryption route isn't foolproof, but it significantly reduces that risk – BritishBoyinDC Jun 4 '15 at 15:25
  • That definitely seems like a huge security risk: exposing contact data to whoever can brute force encrypted contact ids. Have you considered using a one-time use token that expires within 24 hours (or another short time span) so pages cannot be accessed unless the link from the email is taken? – user19038 Jun 4 '15 at 18:47

We have faced this situation in past and the rationale we discussed was to not encrypt id in url (can encrypt other sensitive details). The reason was simple, entire salesforce uses same format to enable data access and any person having access to salesforce org. would anyways be able to see id with little HTML knowledge. Instead, in order to secure data "Data sharing" should be enabled and appropriately used.

If you still have a valid use case to encrypt data and want to minimize url length, then an option can be to store entire url in a custom setting and generate a smaller token for that (date time stamp etc.) and pass the token in url. In receiving visualforce page, use token to retrieve actual url parameters and delete the custom setting record. Same stuff can be implemented in various flavours, but I would still suggest using "Data sharing" for actual data security implementation.

| improve this answer | |

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.