2

I have read that GCM is almost always more secure than CBC when implemented correctly.

However, in the documentation of NodeJS, CBC is being used as an example instead. The key-pair will be stored in the node environment.

Since the private key is being stored locally and CBC is an acceptable encryption for local files according to this answer, is it a secure enough implementation, or should GCM be used such as in this sample code?

  • That uses keyObject.export which is designed not only for local storage but also interop; it uses either PKCS8, whose (password-based) encryption was defined by PKCS5 which even at v2.0 in 2000 used only CBC, or for the specific formats (pkcs1 and sec1) by PEM encryption as defined by 1421 in 1993. GCM was proposed in 2004, which is later in time than 1993 and 2000. If you want nodejs-only storage you have more flexibility; something newer like say JWK can use AES-GCM. – dave_thompson_085 Dec 4 '19 at 8:23
2

The Cipher-Block-Chaining Mode becomes problematic if your threat model includes an attacker who actively manipulates the encrypted data. This allows an attacker to flip specific bits in the cipher to flip the same bits in the resulting plaintext - a property called malleability. If not paired with a MAC to ensure integrity, CBC is not very secure.

When encrypting a private key to be stored on a local device, the only requirement is confidentiality. An attacker could flip specific bits, but it is most likely that this will result in the private key becoming unusable instead. CBC is still good enough at providing confidentiality, and without the AES-NI extension, it's a lot faster than AES-GCM, as you can see in the following graphic:

Benchmark of AES-CBC and AES-GCM

Source: kazoo.ga

To give a succinct answer: Node.JS uses AES-CBC because for this case, the extra benefits offered by AES-GCM don't matter and AES-CBC is usually faster.


In the above graphic, the performance of AES-CBC without AES-NI is used as 100% performance. The relevant other category is AES-128-GCM w/o AES-NI. Of course, if NodeJS supports AES-NI, then AES-GCM is a better choice.

  • Thanks for explaining it in an easy-to-understand way! – Yuu Dec 3 '19 at 9:27
  • Do these performance numbers account for the need to also do a MAC for CBC? – paj28 Dec 3 '19 at 9:59
  • 1
    @paj28 As you can see, the rightmost bar uses AES-128-CBC-HMAC-SHA1 with AES-NI. Sadly, there is no benchmark for AES-128-CBC-HMAC-SHA1 without AES-NI, but it would be consistently worse than plain AES-128-CBC w/o AES-NI. In this situation, HMAC is actually not required, as there is no requirement for integrity, only confidentiality. – MechMK1 Dec 3 '19 at 10:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.