From 6cf4de24b54942eb9448798d35f991cd40d37917 Mon Sep 17 00:00:00 2001 From: Jonathan Buhacoff Date: Mon, 27 Apr 2020 08:30:42 -0700 Subject: [PATCH 1/2] Update crypto.md According to the [NodeJS CCM example](https://nodejs.org/docs/latest-v14.x/api/crypto.html#crypto_ccm_mode], when decrypting the `plaintextLength` parameter actually refers to the ciphertext length, not the plaintext length: ``` decipher.setAAD(aad, { plaintextLength: ciphertext.length }); ``` The same can be seen in the [OpenSSL docs](https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption) where a call to `EVP_DecryptUpdate` passes the ciphertext length: ``` /* Provide the total ciphertext length */ if(1 != EVP_DecryptUpdate(ctx, NULL, &len, NULL, ciphertext_len)) handleErrors(); ``` This parameter probably should have been called `inputLength` or `bufferLength` instead of `plaintextLength`, so that it makes sense both when encrypting and decrypting, but at least we can correct the sentence in the documentation for now to refer to the correct value. --- doc/api/crypto.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index e1c8596abe6a68..c7304829788d25 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -493,7 +493,7 @@ _additional authenticated data_ (AAD) input parameter. The `options` argument is optional for `GCM`. When using `CCM`, the `plaintextLength` option must be specified and its value must match the length -of the plaintext in bytes. See [CCM mode][]. +of the ciphertext in bytes. See [CCM mode][]. The `decipher.setAAD()` method must be called before [`decipher.update()`][]. From 7fda32fbd7eddde9171c28a9511b3ae2061a28f1 Mon Sep 17 00:00:00 2001 From: Jonathan Buhacoff Date: Mon, 27 Apr 2020 08:30:42 -0700 Subject: [PATCH 2/2] Update crypto.md Add explanation in [CCM mode](https://nodejs.org/docs/latest-v14.x/api/crypto.html#crypto_ccm_mode], that ciphertext length is equal to plaintext length in Node.js crypto output because the authentication tag is returned separately: ``` decipher.setAAD(aad, { plaintextLength: ciphertext.length }); ``` The same can be seen in the [OpenSSL docs](https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption) where a call to `EVP_DecryptUpdate` passes the ciphertext length: ``` /* Provide the total ciphertext length */ if(1 != EVP_DecryptUpdate(ctx, NULL, &len, NULL, ciphertext_len)) handleErrors(); ``` --- doc/api/crypto.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index e1c8596abe6a68..c95868c1c057b3 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -3095,7 +3095,12 @@ mode must adhere to certain restrictions when using the cipher API: mode might fail as CCM cannot handle more than one chunk of data per instance. * When passing additional authenticated data (AAD), the length of the actual message in bytes must be passed to `setAAD()` via the `plaintextLength` - option. This is not necessary if no AAD is used. + option. + Many crypto libraries include the authentication tag in the ciphertext, + which means that they produce ciphertexts of the length + `plaintextLength + authTagLength`. Node.js does not include the authentication + tag, so the ciphertext length is always `plaintextLength`. + This is not necessary if no AAD is used. * As CCM processes the whole message at once, `update()` can only be called once. * Even though calling `update()` is sufficient to encrypt/decrypt the message,