crypto: support authTagLength in GCM encryption
The authTagLength option can now be used to produce GCM authentication tags with a specific length. PR-URL: https://github.com/nodejs/node/pull/20235 Refs: https://github.com/nodejs/node/pull/20039 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Yihong Wang <yh.wang@ibm.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
parent
6606a2604a
commit
f9b9974f55
@ -1321,6 +1321,11 @@ This property is deprecated. Please use `crypto.setFips()` and
|
||||
<!-- YAML
|
||||
added: v0.1.94
|
||||
deprecated: v10.0.0
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/20235
|
||||
description: The `authTagLength` option can now be used to produce shorter
|
||||
authentication tags in GCM mode and defaults to 16 bytes.
|
||||
-->
|
||||
|
||||
> Stability: 0 - Deprecated: Use [`crypto.createCipheriv()`][] instead.
|
||||
@ -1336,7 +1341,9 @@ Creates and returns a `Cipher` object that uses the given `algorithm` and
|
||||
The `options` argument controls stream behavior and is optional except when a
|
||||
cipher in CCM mode is used (e.g. `'aes-128-ccm'`). In that case, the
|
||||
`authTagLength` option is required and specifies the length of the
|
||||
authentication tag in bytes, see [CCM mode][].
|
||||
authentication tag in bytes, see [CCM mode][]. In GCM mode, the `authTagLength`
|
||||
option is not required but can be used to set the length of the authentication
|
||||
tag that will be returned by `getAuthTag()` and defaults to 16 bytes.
|
||||
|
||||
The `algorithm` is dependent on OpenSSL, examples are `'aes192'`, etc. On
|
||||
recent OpenSSL releases, `openssl list-cipher-algorithms` will display the
|
||||
@ -1366,6 +1373,10 @@ Adversaries][] for details.
|
||||
<!-- YAML
|
||||
added: v0.1.94
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/20235
|
||||
description: The `authTagLength` option can now be used to produce shorter
|
||||
authentication tags in GCM mode and defaults to 16 bytes.
|
||||
- version: v9.9.0
|
||||
pr-url: https://github.com/nodejs/node/pull/18644
|
||||
description: The `iv` parameter may now be `null` for ciphers which do not
|
||||
@ -1383,7 +1394,9 @@ initialization vector (`iv`).
|
||||
The `options` argument controls stream behavior and is optional except when a
|
||||
cipher in CCM mode is used (e.g. `'aes-128-ccm'`). In that case, the
|
||||
`authTagLength` option is required and specifies the length of the
|
||||
authentication tag in bytes, see [CCM mode][].
|
||||
authentication tag in bytes, see [CCM mode][]. In GCM mode, the `authTagLength`
|
||||
option is not required but can be used to set the length of the authentication
|
||||
tag that will be returned by `getAuthTag()` and defaults to 16 bytes.
|
||||
|
||||
The `algorithm` is dependent on OpenSSL, examples are `'aes192'`, etc. On
|
||||
recent OpenSSL releases, `openssl list-cipher-algorithms` will display the
|
||||
|
@ -3106,9 +3106,10 @@ bool CipherBase::Final(unsigned char** out, int *out_len) {
|
||||
ok = EVP_CipherFinal_ex(ctx_, *out, out_len) == 1;
|
||||
|
||||
if (ok && kind_ == kCipher && IsAuthenticatedMode()) {
|
||||
// For GCM, the tag length is static (16 bytes), while the CCM tag length
|
||||
// must be specified in advance.
|
||||
if (mode == EVP_CIPH_GCM_MODE)
|
||||
// In GCM mode, the authentication tag length can be specified in advance,
|
||||
// but defaults to 16 bytes when encrypting. In CCM mode, it must always
|
||||
// be given by the user.
|
||||
if (mode == EVP_CIPH_GCM_MODE && auth_tag_len_ == kNoAuthTagLength)
|
||||
auth_tag_len_ = sizeof(auth_tag_);
|
||||
// TOOD(tniessen) Use EVP_CTRL_AEAP_GET_TAG in OpenSSL 1.1.0
|
||||
static_assert(EVP_CTRL_CCM_GET_TAG == EVP_CTRL_GCM_GET_TAG,
|
||||
|
@ -727,6 +727,18 @@ for (const test of TEST_CASES) {
|
||||
message: `Invalid GCM authentication tag length: ${length}`
|
||||
});
|
||||
|
||||
common.expectsError(() => {
|
||||
crypto.createCipheriv('aes-256-gcm',
|
||||
'FxLKsqdmv0E9xrQhp0b1ZgI0K7JFZJM8',
|
||||
'qkuZpJWCewa6Szih',
|
||||
{
|
||||
authTagLength: length
|
||||
});
|
||||
}, {
|
||||
type: Error,
|
||||
message: `Invalid GCM authentication tag length: ${length}`
|
||||
});
|
||||
|
||||
common.expectsError(() => {
|
||||
crypto.createDecipheriv('aes-256-gcm',
|
||||
'FxLKsqdmv0E9xrQhp0b1ZgI0K7JFZJM8',
|
||||
@ -741,6 +753,23 @@ for (const test of TEST_CASES) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test that GCM can produce shorter authentication tags than 16 bytes.
|
||||
{
|
||||
const fullTag = '1debb47b2c91ba2cea16fad021703070';
|
||||
for (const [authTagLength, e] of [[undefined, 16], [12, 12], [4, 4]]) {
|
||||
const cipher = crypto.createCipheriv('aes-256-gcm',
|
||||
'FxLKsqdmv0E9xrQhp0b1ZgI0K7JFZJM8',
|
||||
'qkuZpJWCewa6Szih', {
|
||||
authTagLength
|
||||
});
|
||||
cipher.setAAD(Buffer.from('abcd'));
|
||||
cipher.update('01234567', 'hex');
|
||||
cipher.final();
|
||||
const tag = cipher.getAuthTag();
|
||||
assert.strictEqual(tag.toString('hex'), fullTag.substr(0, 2 * e));
|
||||
}
|
||||
}
|
||||
|
||||
// Test that users can manually restrict the GCM tag length to a single value.
|
||||
{
|
||||
const decipher = crypto.createDecipheriv('aes-256-gcm',
|
||||
|
Loading…
x
Reference in New Issue
Block a user