0

How can I generate an AES encrypted token with a shared key and using the following AES cipher attributes in apex?

  • Rijndael cipher
  • Electronic Code Book mode (ECB) / Galois Counter Mode (GCM)
  • No built in padding (such as PKCS)
    • This one is a bit of a concern to me given that Salesforce includes in its documentation, "They use cipher block chaining (CBC) and PKCS7 padding."
  • Resultant encrypted buffer should be manually padded with spaces to achieve the total length a multiple of 32. That is: length(encrypted padded string) mod 32 = 0

The API docs provides the following sample values:

  • Key: 4FCD5FAE2AC493C0F8CE8E1E6105D194
  • Raw Token: iframe=true;customer.firstName=John;customer.lastName=Smith;header.accountNumber=6759370;header.authToken1=12345;header.paymentTypeCode=UTILITY;header.amount=123.45
  • Encrypted Token: 4BA596898953113C3D8AAF6BC30F9FE8EB04C699FEE510707725146937227946D8C1AD49500D7AAE72EE2D2CEA4FA1663703F00B730DACB7DB5F4FFB07DE716C7E339FFA25FBE7F61237EC11FCC53989ADAC97B10C7EFB3DC5CBBA526CD43CD3D84E10BD687329F627A52015960ABF1D5546F53447B2B3D9D6734F2FB6E3538D97F8332953B930A5953DAB3FEC2C8C9A423F63D9D6B51CD72F7E3AF644973F15A4BB7D901ACA6B96558C80C5271EF95A1CE53A43557C295F3D6FC9678EE0557F

My assumption is that I need to provide the initialization vector in Crypto.encrypt(algorithmName, privateKey, initializationVector, clearText), but how do I do that with the provided key?

1
  • OOTB with Crypto class, you can't do it in ECB/GCM without padding regardless of whether you use IV or not. The only mode supported is CBC with padding as the docs clearly state. You'd have to use one of the 3rd party crypto libraries and then integrate with SF. One option is Functions.
    – identigral
    Commented Apr 26, 2023 at 15:26

1 Answer 1

0

The AES implementations are limited. If you're trying to just deal with what Apex can do, you can use Crypto.encryptWithManagedIv, then you can decrypt with Crypto.decryptWithManagedIv, as follows:

String clearText = 'iframe=true;customer.firstName=John;customer.lastName=Smith;header.accountNumber=6759370;header.authToken1=12345;header.paymentTypeCode=UTILITY;header.amount=123.45';
Blob key = EncodingUtil.convertFromHex('4FCD5FAE2AC493C0F8CE8E1E6105D194');

// To encrypt:
Blob clearBlob = Blob.valueOf(clearText);
Blob encryptedBlob = Crypto.encryptWithManagedIV('AES128', key, clearBlob);
// Final hex-encoded output
String encryptedText = EncodingUtil.convertToHex(encryptedBlob);

// To decrypt:
Blob encryptedData = EncodingUtil.convertFromHex(encryptedText);
Blob decryptedBlob = Crypto.decryptWithManagedIV('AES128', key, encryptedData);
// Final original clear text
String decryptedText = decryptedBlob.toString();

Otherwise, the far end would need to separately give you its IV, which must have been used in the original calculation. Just as a trial, I did try to use a blank IV:

Blob encrypted = EncodingUtil.convertFromHex('4BA596898953113C3D8AAF6BC30F9FE8EB04C699FEE510707725146937227946D8C1AD49500D7AAE72EE2D2CEA4FA1663703F00B730DACB7DB5F4FFB07DE716C7E339FFA25FBE7F61237EC11FCC53989ADAC97B10C7EFB3DC5CBBA526CD43CD3D84E10BD687329F627A52015960ABF1D5546F53447B2B3D9D6734F2FB6E3538D97F8332953B930A5953DAB3FEC2C8C9A423F63D9D6B51CD72F7E3AF644973F15A4BB7D901ACA6B96558C80C5271EF95A1CE53A43557C295F3D6FC9678EE0557F');
Blob key = EncodingUtil.convertFromHex('4FCD5FAE2AC493C0F8CE8E1E6105D194');
Blob iv = EncodingUtil.convertFromHex('0'.repeat(32));
Blob decryptedBlob = Crypto.decrypt('AES128', key, iv, encrypted);
String decryptedText = decryptedBlob.toString();

But this also failed. You'll need the IV, or you'll need to use an implementation that is Apex compatible.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .