4

I had given an cipher text (of JSON string), an IV and a key. I tried decrypting using Apex Crypto class's method:

decryptWithManagedIV(algorithmName, privateKey, IVAndCipherText)

  //Sample code
  Blob key = Blob.valueOf(decryptionKey);
  Blob encryptedDatafor = EncodingUtil.base64Decode(bodystring);
  Blob decryptedData = Crypto.decryptwithManagedIV('AES128', key, encryptedDatafor);

  cipher = decryptedData.toString();
  System.debug('Encrypted BodyString: ' +cipher);

and I was able to decrypt the cipher successfully. But when I use the provided IV with the following method:

decrypt(algorithmName, privateKey, initializationVector, cipherText)

 //Sample code
 Blob exampleIV = Blob.valueOf('HSDlUkhrmfEo7SgM'); //provided IV 
 Blob key = Blob.valueOf(decryptionKey);
 Blob encryptedDatafor = EncodingUtil.base64Decode(bodystring);
 Blob decryptedDataIV = Crypto.decrypt('AES128', key, exampleIV, encryptedDatafor);

 cipher = EncodingUtil.base64Encode(decryptedDataIV );
 System.debug('Encrypted BodyString: ' +cipher);

I get some string which looks like, it is still in the encrypted form (different from the encrypted string I have passed).

Update: I have tried the below code-snippet based on the suggestion from @identigral, but I am still unable to decrypt the cipher using the IV:

Blob exampleIV = Blob.valueOf('HSDlUkhrmfEo7SgM'); //provided IV 
Blob key = Blob.valueOf(decryptionKey);
Blob encryptedDatafor = EncodingUtil.base64Decode(bodystring);

String encodedCipherTextAndIV = EncodingUtil.convertToHex(encryptedDatafor);
String encodedCipherText = encodedCipherTextAndIV.substring(32);
String finCipher = encodedCipherText.difference(encodedCipherTextAndIV);
Blob ciphertext = EncodingUtil.convertFromHex(finCipher); 

Blob decryptedDataIV = Crypto.decrypt('AES128', key, exampleIV, ciphertext);

decryptStg = EncodingUtil.base64Encode(decryptedDataIV );
System.debug('Decrypted BodyString: ' +decryptStg);

1 Answer 1

5

You can't decrypt the same ciphertext (bodystring) in your example with both decryptWithManagedIV and decrypt methods, only one of them will work. decryptWithManagedIV assumes that the ciphertext includes an initialization vector. If this is indeed the case, then bodystring consists of an IV (first 16 bytes), then the rest of it is actual stuff that was originally encrypted. Using decrypt on the same ciphertext will only work if you remove the IV from bodystring.

To remove the first 16 bytes from a binary Blob, you have to manipulate its hex representation. From this answer:

Use EncodingUtil.convertToHex() to get a hexadecimal (base 16) representation of the blob. So the first two characters in the hexadecimal string will represent the first byte of the encryptedData. To get the first 16 bytes you will need the first 32 hexadecimal characters.

Example with a complete roundtrip:

String text = 'The quick brown fox jumps over 13 lazy dogs.';
Blob key = Crypto.generateAesKey(128);
Blob data = Blob.valueOf(text);
String b64Data = EncodingUtil.base64Encode(data);

Blob ciphertextAndIV = Crypto.encryptWithManagedIV('AES128', key, data);
Blob plaintext = Crypto.decryptWithManagedIV('AES128', key, ciphertextAndIV);
String b64Decrypted = EncodingUtil.base64Encode(plaintext);
System.debug('Text = plaintext: ' + (text == plaintext.toString()));
System.debug('Base64-text = Base64-plaintext: ' + (b64Decrypted == b64Data));

String encodedCiphertextAndIV = EncodingUtil.convertToHex(ciphertextAndIV);
String encodedCiphertext = encodedCiphertextAndIV.substring(32);
String encodedIV = encodedCiphertextAndIV.substring(0,32);
Blob ciphertext = EncodingUtil.convertFromHex(encodedCiphertext);
Blob IV = EncodingUtil.convertFromHex(encodedIV);
Blob plaintext2 = Crypto.decrypt('AES128', key, IV, ciphertext);
String b64Decrypted2 = EncodingUtil.base64Encode(plaintext2);
System.debug('Text = plaintext: ' + (text == plaintext2.toString()));
System.debug('Base64-text = Base64-plaintext: ' + (b64Decrypted2 == b64Data));
7
  • That makes sense to me. But, how can I separate the first 16 bytes from the encrypted body string? Do I need to delete the first 16 characters from the body? If so, I did that too. And I get an error that says: System.SecurityException: last block incomplete in decryption. Any workaround?
    – Arnold Jr.
    Jul 30, 2019 at 15:35
  • @ArnoldJr. See updated answer
    – identigral
    Jul 30, 2019 at 15:50
  • One quick question: Looks like your ciphertext is actually the IV bytes, right (first 16 bytes)? Correct me if I am wrong. I am guessing this as I am still getting some encrypted text.
    – Arnold Jr.
    Jul 30, 2019 at 16:15
  • I added a more complete example
    – identigral
    Jul 30, 2019 at 17:38
  • 1
    encodedCiphertext is the substring after the 32nd character, yes.
    – identigral
    Jul 30, 2019 at 17:49

You must log in to answer this question.

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