We ran into the problem that obviously only 1 million byte (or 1MB) may be passed into the decrypt function. Does anybody know a workaround for this problem? There are JavaScript frameworks but they would require to pass the private key to the client which is not acceptable from a security point of view. Heroku is also not an option as passing the data over for decryption and pulling the decrypted data would also be a major security issue. Partitioning the encrypted data would be an excellent solution but I dimly remember that this cannot easily be done, right?
2 Answers
You can't stitch together independently encrypted AES blocks, even with the same IV and key, because salesforce.com uses the CBC (Cipher Block Chaining) mode in AES. This means that each block depends upon the block before it, so the stitch point would cause a decryption error. You would have to decrypt the data using the same basic algorithm as encryption: encrypt blocks of data (e.g. 512kb blocks), and append them together. For decryption, you would have to split along 512kb boundaries, then decrypt and put them back together when you're done.
Heroku should be a viable alternative, however, as Heroku uses TLS 1.0 for over-the-wire communication, which is at least as secure as the data after encryption anyways. I'm not sure where the "major security issue" comes into play, since you would own the source code, would have total control over your dynos, and would have encrypted communications between the two servers. And, as you say, it's far more secure than a JavaScript solution that would expose your private key to anyone with enough technical know-how to read cookies or JavaScript, etc.
At some point, you have to accept the fact that no security is "perfect", and you should aim for security that is "nearly perfect." In fact, I'm fairly certain that the US government would consider use salesforce.com with Heroku to store top secret military documents if it didn't already have its own private, firewalled server clusters on dedicated point-to-point communication lines (assuming, of course, that the NSA hasn't poisoned AES with a backdoor that allows them to decrypt any message without a key).
-
Your question on Crypto SE seems to suggest that you can do this with some care.– sfdcfox ♦Commented Dec 6, 2013 at 15:22
-
Yes and I tried it as suggested by the crypto experts however Apex does not allow splitting of a Blob on byte level. I tried to convert the blob to a string in order to split on character level but this resulted in a "BLOB is not a valid UTF-8 string" exception. So here I reached the dead end. So your answer is right (seems to be impossible on the platform) but the explanation is not entirely correct.– h9nryCommented Dec 9, 2013 at 7:43
-
@h9nry You would have to use
EncodingUtil.base64decode
to convert the blob to an encoded string, split the string into equal parts, then re-encode them back into blobs for the encryption sequence. It's not "impossible", but it is a lot of work.– sfdcfox ♦Commented Dec 9, 2013 at 14:32 -
@sfdcfox I have followed the suggested way.. But after I split the blob and encrypt the first iteration with IV and key (16bytes) the result is 32Bytes (The extra 16bytes is due to the CBC padding)... So now i cannot use this 32 bytes to encrypt my next chunk because the IV must be 16Bytes only. Im stuck at this stage.. any help ? Commented May 16, 2017 at 5:50
-
1Finally I've decided to take the first solution.. splitting the file into 512KB, encrypting.. so while decrypt I also I follow the same logic and IT WORKS !....... BUT...... PLOT TWIST.. Salesforce has a heap memory of 6MB so no matter what work around I do, it always fails if your file (or string) is above 6MB. Commented May 17, 2017 at 7:53
You could chunk your data into < 1MB chunks and encrypt those wherever they originate. Then decrypt the chunks and concatenate them. I know that's not ideal since it's more work for you as the coder.
Full disclosure: I don't have experience with the decrypt function. This is just what I would do when faced with such a limit.