First, to choose the right encryption, it is important to understand the data to be encrypted. Factors like: performance, is data stored behind a firewall, size, how many records, the life of the data (is it purged after 14 days), does the data contain repeating or predicatable elements etc. In my own performance comparisons AES encryption with ECB mode outperformed GCM mode. Below are the results for encrypting then decrypting the same HL7 message containing 668 characters 100,000 times:
ECB took 1152ms about a second
GCM took 23407362ms OUCH! WHAT! 6.5 bleepen hours!
The above comparison wasn't a fair comparison since the SecretKey generation in the ECB implementation occured outside of the timed code. This accounts for the bulk of the difference. There were also other differences between the two above implementations. For example ECB does not require an Initialzation Vector where GCM does, which was prepended to the encrypted bytes making the GCM implemention propritary. If we change the GCM implementation by moving the Secret Key generation outside of the timed code, and reuse it, the results are closer:
ECB took 1128ms
GCM took 2054ms
But making this change weakens the GCM implementation. Looking closer we find that the bulk of the time in the original GCM implementation was due to this line used to generate a unique key for each iteration:
KeySpec spec = new PBEKeySpec(new String(password).toCharArray(), salt, 65536, 256);
The third parameter above is the Iteration Count (described here). Dropping this from 65536 to 1 in the original implementation gives the following results:
ECB took 1363ms
GCM took 4461ms
For a high transaction system GCM could potentially be a bottle neck depending on the implementation details. One might then decide to use another strategy. If the HL7 message can be broken down into individual columns, a system might take a more selective approach and encrypt only the sensitive bits. Testing with a shorter message, "Hello World", still shows that our ECB implementation is faster.
ECB took 1097ms
GCM took 3675ms
Second, a coworker pointed out, the image based explanation that follows may oversimplify the issues when encrypting text.
Using ECB to encrypt "Hello World" results in "0� � �,�̡m�%". Using another key results in "�Bi
"ds�hK��"�". Both produce results that appear more opaque than the image based examples below. Both would present an obstacle for all but the most technical prying eyes. In fact I would dare bet a $50 amazon gift card for the first person that could tell me what the original text for this "��K/C�G����L:��A��@�H|!:��@J��" is within 90 days of this posted date 12/28/2022.
The best explanation for not using ECB mode can be explained best visually.
The above image was sourced from this article:
The above Wikipedia article explains:
"The simplest (and not to be used anymore) of the encryption modes is the electronic codebook (ECB) mode...The disadvantage of this method is a lack of diffusion. Because ECB encrypts identical plaintext blocks into identical ciphertext blocks, it does not hide data patterns well. ECB is not recommended for use in cryptographic protocols."
Another visual example (using different keys):
The above image was sourced from this article and describes the procedure used to create the images.
As we can see the penguin is not well hidden in the encrypted versions. In the case of encrypted text, that doesn't have the same visual cues, it is still an issue. A real-world example of this is the Adobe data breach in 2013. Where ECB mode was used to encrypt passwords. In this case textual cues could be used to decrypt the passwords. For additional details see this article regarding the Adobe breach and how the passwords could be recovered:
The problems with ECB apply to AES encryption, DES encryption, etc. To avoid using ECB one needs to consider the defaults. For example, it is legal to obtain an AES encryption Cipher instance like this:
var cipher = javax.crypto.Cipher.getInstance("AES");
However, Java will default the mode and padding. The mode defaults to "ECB" in this case. To avoid ECB it needs to be more specific like this:
var cipher = javax.crypto.Cipher.getInstance("AES/GCM/NoPadding");
To see what modes are available in Java see the Java docs for the version of Java used. For Java 11 see the "Cipher Algorithm Modes" table in this link:
Quotes from other sources:
"ECB Electronic Codebook Mode, as defined in FIPS PUB 81 (generally this mode should not be used for multiple blocks of data)." Sourced here.
"ECB...it's not recommended for encryption." Sourced here.
"The simplest (and not to be used anymore) of the encryption modes is the electronic codebook (ECB) mode..." Sourced here.
"ECB - Don't use it. There are a very small number of situations where ECB is the correct choice, but unless you're a cryptographer you'll almost never run into them." Sourced here.
What cipher modes are recommended for encryption?
How can I use "AES/GCM/NoPadding" encryption/cipher mode in QIE?