Skip to content

Commit

Permalink
doc: emphasize that createCipher is never secure
Browse files Browse the repository at this point in the history
The current documentation clearly states that createCipher() and
createDecipher() should not be used with ciphers in counter mode, but
(1) this is an understatement, and (2) these functions are
(semantically) insecure for ciphers in any other supported block cipher
mode as well.

Semantic security requires IND-CPA, but a deterministic cipher with
fixed key and IV, such as those generated by these functions, does not
fulfill IND-CPA.

Are there justified use cases for createCipher() and createDecipher()?
Yes and no. The only case in which these functions can be used in a
semantically secure manner arises only when the password argument is
not actually a password but rather a random or pseudo-random sequence
that is unpredictable and that is never reused (e.g., securely derived
from a password with a proper salt). Insofar, it is possible to use
these APIs without immediately creating a vulnerability. However,

- any application that manages to fulfill this requirement should also
  be able to fulfill the similar requirements of crypto.createCipheriv()
  and those of crypto.createDecipheriv(), which give much more control
  over key and initialization vector, and
- the MD5-based key derivation step generally does not help and might
  even reduce the overall security due to its many weaknesses.

Refs: #13821
Refs: #19343
Refs: #22089
PR-URL: #44538
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
  • Loading branch information
tniessen authored and RafaelGSS committed Sep 26, 2022
1 parent a733f7f commit a3360b1
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 2 deletions.
8 changes: 8 additions & 0 deletions doc/api/crypto.md
Expand Up @@ -3005,6 +3005,10 @@ The `password` is used to derive the cipher key and initialization vector (IV).
The value must be either a `'latin1'` encoded string, a [`Buffer`][], a
`TypedArray`, or a `DataView`.

<strong class="critical">This function is semantically insecure for all
supported ciphers and fatally flawed for ciphers in counter mode (such as CTR,
GCM, or CCM).</strong>

The implementation of `crypto.createCipher()` derives keys using the OpenSSL
function [`EVP_BytesToKey`][] with the digest algorithm set to MD5, one
iteration, and no salt. The lack of salt allows dictionary attacks as the same
Expand Down Expand Up @@ -3124,6 +3128,10 @@ cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) is used. In that case, the
authentication tag in bytes, see [CCM mode][].
For `chacha20-poly1305`, the `authTagLength` option defaults to 16 bytes.

<strong class="critical">This function is semantically insecure for all
supported ciphers and fatally flawed for ciphers in counter mode (such as CTR,
GCM, or CCM).</strong>

The implementation of `crypto.createDecipher()` derives keys using the OpenSSL
function [`EVP_BytesToKey`][] with the digest algorithm set to MD5, one
iteration, and no salt. The lack of salt allows dictionary attacks as the same
Expand Down
4 changes: 2 additions & 2 deletions doc/api/deprecations.md
Expand Up @@ -2114,10 +2114,10 @@ changes:

Type: Runtime

Using [`crypto.createCipher()`][] and [`crypto.createDecipher()`][] should be
Using [`crypto.createCipher()`][] and [`crypto.createDecipher()`][] must be
avoided as they use a weak key derivation function (MD5 with no salt) and static
initialization vectors. It is recommended to derive a key using
[`crypto.pbkdf2()`][] or [`crypto.scrypt()`][] and to use
[`crypto.pbkdf2()`][] or [`crypto.scrypt()`][] with random salts and to use
[`crypto.createCipheriv()`][] and [`crypto.createDecipheriv()`][] to obtain the
[`Cipher`][] and [`Decipher`][] objects respectively.

Expand Down

0 comments on commit a3360b1

Please sign in to comment.