This one won’t mean much to most folks. Unless you have taken a deep dive into encryption and had to work with encrypting/decrypting data without side systems and they are using CBC (Cipher Block Chaining) as the operation method.
I barely understand encryption at this low of a level myself, and definitely not at a level where I can explain it to others in coherent fashion. But here it goes 🙂
For Example: When you use the CryptStandard to preform AES128 encryption (cryptAES128 – algorithm) and CBC (cryptCBC) as the operating method, which are the defaults by the way. It breaks the data to be encrypted into 128 bit blocks, and each block is the encrypted separately. It is important to note we are talking about 128 bits, which is 16 bytes. That distinction really caused me issues as I worked through this!
So how it works, is it generates a random 128 bit block of data, the Initialization Vector. The initialization vector is then XOR with the first 128 bit block of data, and then finally that result is then encrypted using the key provided. Then the next 128 bit block of data is XOR with the encrypted first block, and then encrypted with the key the same as the first block. This repeats until there is no more data to encrypt.
And now we know why it is called Chained Blocks, each block of data depends on the previous block as part of the encryption. This makes it more difficult for hackers, as it helps prevent patterns for showing in the data. For example, with ECB (Electronic Codebook) two identical 128 bit blocks of data, would be identical in the resulting encrypted string. However with CBC those 2 blocks would be entirely different since each block is seeded using the previous block of data. Pattern recognition of one of the many methods that hackers use to crack encryption.
Likewise, since each block depends on the previous block so all blocks have to be present in order to decrypt, making it harder for a hacker to sniff out and decrypt just a portion of an encrypted message.
Again that is a very oversimplified explanation, and might not even be 100% accurate but it is as close to explaining encryption at that low of a level as my overtaxed brain can get. I should note I used AES128 in the above example, but a similar thing happens with AES256, just the blocks are larger.
So where’s the issue? The issue is that come other libraries return the initialization vector when you use the encrypt function, and you then have to provide that to the decrypt function, or they take the initialization vector as a parameters of the encryption function and again you need to provide that for decryption. One such library is CryptoJS, which I was using to do some browser encryption when I ran into this issue.
On the browser I was encrypting some data and sending it to the server. Think of it as double batch of SSL 🙂 If hackers were able to get the private key for the SSL certificate they could decrypt the data between the browser and the server, however if that data is also encrypted with yet a different key, one that we randomly generate for each session, then all they get is yet more encrypted data.
The issue was that the CryptoJS function was returning an initialization vector to me as part of the encryption, however there is no way to pass that to the DecryptStandard function in WL. Therefore the first 128 bits of data was always corrupted. For example:
When I encrypted the below string:
What DecryptStandard returned was:
Note the first 16 bytes (128 bits) is corrupted, because it didn’t know the initialization vector for the first block. I solved this by adding 128 bits of random text to the beginning of my string before encrypting it. And then ignoring the first 16 bytes of the decrypted string in WL, which was still corrupted but I didn’t care sense it was just random text at that point. This solved my issue, since I had control of both sides of the encryption, but could/would be an issue if you are receiving encrypted data from an outside source, where you wouldn’t have the luxury of adding 16 bytes to the front of the data.
This isn’t an issue when you are working completely in WL, since EncryptStandard and DecryptStandard are somehow avoiding this issue. I am not 100% sure how, but I suspect it has something to do with not all encryption libraries generate and use a truly random initialization vector, but again that is way above my pay grade! But the good news is for the few of use that have had to dive this deep into encryption, starting with v27 we will be able to specify the initialization vector and avoid this issue.