| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2926,6 +2926,10 @@ Checks the primality of the `candidate`. | |||
| 2926 | 2926 | added: v0.1.94 | |
| 2927 | 2927 | deprecated: v10.0.0 | |
| 2928 | 2928 | changes: | |
| 2929 | + - version: REPLACEME | ||
| 2930 | + pr-url: https://github.com/nodejs/node/pull/42427 | ||
| 2931 | + description: The `authTagLength` option is now optional when using the | ||
| 2932 | + `chacha20-poly1305` cipher and defaults to 16 bytes. | ||
| 2929 | 2933 | - version: v15.0.0 | |
| 2930 | 2934 | pr-url: https://github.com/nodejs/node/pull/35093 | |
| 2931 | 2935 | description: The password argument can be an ArrayBuffer and is limited to | |
@@ -2950,12 +2954,12 @@ Creates and returns a `Cipher` object that uses the given `algorithm` and | |||
| 2950 | 2954 | `password`. | |
| 2951 | 2955 | ||
| 2952 | 2956 | The `options` argument controls stream behavior and is optional except when a | |
| 2953 | - cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) or `chacha20-poly1305` is used. | ||
| 2954 | - In that case, the | ||
| 2957 | + cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) is used. In that case, the | ||
| 2955 | 2958 | `authTagLength` option is required and specifies the length of the | |
| 2956 | 2959 | authentication tag in bytes, see [CCM mode][]. In GCM mode, the `authTagLength` | |
| 2957 | 2960 | option is not required but can be used to set the length of the authentication | |
| 2958 | 2961 | tag that will be returned by `getAuthTag()` and defaults to 16 bytes. | |
| 2962 | + For `chacha20-poly1305`, the `authTagLength` option defaults to 16 bytes. | ||
| 2959 | 2963 | ||
| 2960 | 2964 | The `algorithm` is dependent on OpenSSL, examples are `'aes192'`, etc. On | |
| 2961 | 2965 | recent OpenSSL releases, `openssl list -cipher-algorithms` will | |
@@ -2986,6 +2990,10 @@ Adversaries][] for details. | |||
| 2986 | 2990 | <!-- YAML | |
| 2987 | 2991 | added: v0.1.94 | |
| 2988 | 2992 | changes: | |
| 2993 | + - version: REPLACEME | ||
| 2994 | + pr-url: https://github.com/nodejs/node/pull/42427 | ||
| 2995 | + description: The `authTagLength` option is now optional when using the | ||
| 2996 | + `chacha20-poly1305` cipher and defaults to 16 bytes. | ||
| 2989 | 2997 | - version: v15.0.0 | |
| 2990 | 2998 | pr-url: https://github.com/nodejs/node/pull/35093 | |
| 2991 | 2999 | description: The password and iv arguments can be an ArrayBuffer and are | |
@@ -3022,12 +3030,12 @@ Creates and returns a `Cipher` object, with the given `algorithm`, `key` and | |||
| 3022 | 3030 | initialization vector (`iv`). | |
| 3023 | 3031 | ||
| 3024 | 3032 | The `options` argument controls stream behavior and is optional except when a | |
| 3025 | - cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) or `chacha20-poly1305` is used. | ||
| 3026 | - In that case, the | ||
| 3033 | + cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) is used. In that case, the | ||
| 3027 | 3034 | `authTagLength` option is required and specifies the length of the | |
| 3028 | 3035 | authentication tag in bytes, see [CCM mode][]. In GCM mode, the `authTagLength` | |
| 3029 | 3036 | option is not required but can be used to set the length of the authentication | |
| 3030 | 3037 | tag that will be returned by `getAuthTag()` and defaults to 16 bytes. | |
| 3038 | + For `chacha20-poly1305`, the `authTagLength` option defaults to 16 bytes. | ||
| 3031 | 3039 | ||
| 3032 | 3040 | The `algorithm` is dependent on OpenSSL, examples are `'aes192'`, etc. On | |
| 3033 | 3041 | recent OpenSSL releases, `openssl list -cipher-algorithms` will | |
@@ -3055,6 +3063,10 @@ given IV will be. | |||
| 3055 | 3063 | added: v0.1.94 | |
| 3056 | 3064 | deprecated: v10.0.0 | |
| 3057 | 3065 | changes: | |
| 3066 | + - version: REPLACEME | ||
| 3067 | + pr-url: https://github.com/nodejs/node/pull/42427 | ||
| 3068 | + description: The `authTagLength` option is now optional when using the | ||
| 3069 | + `chacha20-poly1305` cipher and defaults to 16 bytes. | ||
| 3058 | 3070 | - version: v10.10.0 | |
| 3059 | 3071 | pr-url: https://github.com/nodejs/node/pull/21447 | |
| 3060 | 3072 | description: Ciphers in OCB mode are now supported. | |
@@ -3071,10 +3083,10 @@ Creates and returns a `Decipher` object that uses the given `algorithm` and | |||
| 3071 | 3083 | `password` (key). | |
| 3072 | 3084 | ||
| 3073 | 3085 | The `options` argument controls stream behavior and is optional except when a | |
| 3074 | - cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) or `chacha20-poly1305` is used. | ||
| 3075 | - In that case, the | ||
| 3086 | + cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) is used. In that case, the | ||
| 3076 | 3087 | `authTagLength` option is required and specifies the length of the | |
| 3077 | 3088 | authentication tag in bytes, see [CCM mode][]. | |
| 3089 | + For `chacha20-poly1305`, the `authTagLength` option defaults to 16 bytes. | ||
| 3078 | 3090 | ||
| 3079 | 3091 | The implementation of `crypto.createDecipher()` derives keys using the OpenSSL | |
| 3080 | 3092 | function [`EVP_BytesToKey`][] with the digest algorithm set to MD5, one | |
@@ -3093,6 +3105,10 @@ to create the `Decipher` object. | |||
| 3093 | 3105 | <!-- YAML | |
| 3094 | 3106 | added: v0.1.94 | |
| 3095 | 3107 | changes: | |
| 3108 | + - version: REPLACEME | ||
| 3109 | + pr-url: https://github.com/nodejs/node/pull/42427 | ||
| 3110 | + description: The `authTagLength` option is now optional when using the | ||
| 3111 | + `chacha20-poly1305` cipher and defaults to 16 bytes. | ||
| 3096 | 3112 | - version: v11.6.0 | |
| 3097 | 3113 | pr-url: https://github.com/nodejs/node/pull/24234 | |
| 3098 | 3114 | description: The `key` argument can now be a `KeyObject`. | |
@@ -3125,12 +3141,12 @@ Creates and returns a `Decipher` object that uses the given `algorithm`, `key` | |||
| 3125 | 3141 | and initialization vector (`iv`). | |
| 3126 | 3142 | ||
| 3127 | 3143 | The `options` argument controls stream behavior and is optional except when a | |
| 3128 | - cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) or `chacha20-poly1305` is used. | ||
| 3129 | - In that case, the | ||
| 3144 | + cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) is used. In that case, the | ||
| 3130 | 3145 | `authTagLength` option is required and specifies the length of the | |
| 3131 | 3146 | authentication tag in bytes, see [CCM mode][]. In GCM mode, the `authTagLength` | |
| 3132 | 3147 | option is not required but can be used to restrict accepted authentication tags | |
| 3133 | 3148 | to those with the specified length. | |
| 3149 | + For `chacha20-poly1305`, the `authTagLength` option defaults to 16 bytes. | ||
| 3134 | 3150 | ||
| 3135 | 3151 | The `algorithm` is dependent on OpenSSL, examples are `'aes192'`, etc. On | |
| 3136 | 3152 | recent OpenSSL releases, `openssl list -cipher-algorithms` will | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -571,9 +571,17 @@ bool CipherBase::InitAuthenticated( | |||
| 571 | 571 | } | |
| 572 | 572 | } else { | |
| 573 | 573 | if (auth_tag_len == kNoAuthTagLength) { | |
| 574 | - THROW_ERR_CRYPTO_INVALID_AUTH_TAG( | ||
| 575 | - env(), "authTagLength required for %s", cipher_type); | ||
| 576 | - return false; | ||
| 574 | + // We treat ChaCha20-Poly1305 specially. Like GCM, the authentication tag | ||
| 575 | + // length defaults to 16 bytes when encrypting. Unlike GCM, the | ||
| 576 | + // authentication tag length also defaults to 16 bytes when decrypting, | ||
| 577 | + // whereas GCM would accept any valid authentication tag length. | ||
| 578 | + if (EVP_CIPHER_CTX_nid(ctx_.get()) == NID_chacha20_poly1305) { | ||
| 579 | + auth_tag_len = 16; | ||
| 580 | + } else { | ||
| 581 | + THROW_ERR_CRYPTO_INVALID_AUTH_TAG( | ||
| 582 | + env(), "authTagLength required for %s", cipher_type); | ||
| 583 | + return false; | ||
| 584 | + } | ||
| 577 | 585 | } | |
| 578 | 586 | ||
| 579 | 587 | // TODO(tniessen) Support CCM decryption in FIPS mode | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -96,10 +96,9 @@ for (const test of TEST_CASES) { | |||
| 96 | 96 | ||
| 97 | 97 | const isCCM = /^aes-(128|192|256)-ccm$/.test(test.algo); | |
| 98 | 98 | const isOCB = /^aes-(128|192|256)-ocb$/.test(test.algo); | |
| 99 | - const isChacha20Poly1305 = test.algo === 'chacha20-poly1305'; | ||
| 100 | 99 | ||
| 101 | 100 | let options; | |
| 102 | - if (isCCM || isOCB || isChacha20Poly1305) | ||
| 101 | + if (isCCM || isOCB) | ||
| 103 | 102 | options = { authTagLength: test.tag.length / 2 }; | |
| 104 | 103 | ||
| 105 | 104 | const inputEncoding = test.plainIsHex ? 'hex' : 'ascii'; | |
@@ -659,8 +658,7 @@ for (const test of TEST_CASES) { | |||
| 659 | 658 | assert.throws(() => crypto.createCipheriv( | |
| 660 | 659 | valid.algo, | |
| 661 | 660 | Buffer.from(valid.key, 'hex'), | |
| 662 | - Buffer.from(H(prefix) + valid.iv, 'hex'), | ||
| 663 | - { authTagLength: valid.tag.length / 2 } | ||
| 661 | + Buffer.from(H(prefix) + valid.iv, 'hex') | ||
| 664 | 662 | ), errMessages.length, `iv length ${ivLength} was not rejected`); | |
| 665 | 663 | ||
| 666 | 664 | function H(length) { return '00'.repeat(length); } | |
@@ -745,3 +743,46 @@ for (const test of TEST_CASES) { | |||
| 745 | 743 | } | |
| 746 | 744 | } | |
| 747 | 745 | } | |
| 746 | + | ||
| 747 | + // ChaCha20-Poly1305 should default to an authTagLength of 16. When encrypting, | ||
| 748 | + // this matches the behavior of GCM ciphers. When decrypting, however, it is | ||
| 749 | + // stricter than GCM in that it only allows authentication tags that are exactly | ||
| 750 | + // 16 bytes long, whereas, when no authTagLength was specified, GCM would accept | ||
| 751 | + // shorter tags as long as their length was valid according to NIST SP 800-38D. | ||
| 752 | + // For ChaCha20-Poly1305, we intentionally deviate from that because there are | ||
| 753 | + // no recommended or approved authentication tag lengths below 16 bytes. | ||
| 754 | + { | ||
| 755 | + const rfcTestCases = TEST_CASES.filter(({ algo, tampered }) => { | ||
| 756 | + return algo === 'chacha20-poly1305' && tampered === false; | ||
| 757 | + }); | ||
| 758 | + assert.strictEqual(rfcTestCases.length, 1); | ||
| 759 | + | ||
| 760 | + const [testCase] = rfcTestCases; | ||
| 761 | + const key = Buffer.from(testCase.key, 'hex'); | ||
| 762 | + const iv = Buffer.from(testCase.iv, 'hex'); | ||
| 763 | + const aad = Buffer.from(testCase.aad, 'hex'); | ||
| 764 | + | ||
| 765 | + for (const opt of [ | ||
| 766 | + undefined, | ||
| 767 | + { authTagLength: undefined }, | ||
| 768 | + { authTagLength: 16 }, | ||
| 769 | + ]) { | ||
| 770 | + const cipher = crypto.createCipheriv('chacha20-poly1305', key, iv, opt); | ||
| 771 | + const ciphertext = Buffer.concat([ | ||
| 772 | + cipher.setAAD(aad).update(testCase.plain, 'hex'), | ||
| 773 | + cipher.final(), | ||
| 774 | + ]); | ||
| 775 | + const authTag = cipher.getAuthTag(); | ||
| 776 | + | ||
| 777 | + assert.strictEqual(ciphertext.toString('hex'), testCase.ct); | ||
| 778 | + assert.strictEqual(authTag.toString('hex'), testCase.tag); | ||
| 779 | + | ||
| 780 | + const decipher = crypto.createDecipheriv('chacha20-poly1305', key, iv, opt); | ||
| 781 | + const plaintext = Buffer.concat([ | ||
| 782 | + decipher.setAAD(aad).update(ciphertext), | ||
| 783 | + decipher.setAuthTag(authTag).final(), | ||
| 784 | + ]); | ||
| 785 | + | ||
| 786 | + assert.strictEqual(plaintext.toString('hex'), testCase.plain); | ||
| 787 | + } | ||
| 788 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments