diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 6776c790d0a433..b531f99a2491ce 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -4562,12 +4562,15 @@ removed in a future version of Node.js. -Type: Documentation-only +Type: Runtime Calling `hmac.digest()` more than once returns an empty buffer instead of throwing an error. This behavior is inconsistent with `hash.digest()` and diff --git a/lib/internal/crypto/hash.js b/lib/internal/crypto/hash.js index 5aec1614cb92e9..7d4adcb43ba51a 100644 --- a/lib/internal/crypto/hash.js +++ b/lib/internal/crypto/hash.js @@ -87,6 +87,11 @@ const maybeEmitDeprecationWarning = getDeprecationWarningEmitter( }, ); +const emitHmacDigestDeprecation = getDeprecationWarningEmitter( + 'DEP0206', + 'Calling Hmac.digest() more than once is deprecated.', +); + function Hash(algorithm, options) { if (!new.target) return new Hash(algorithm, options); @@ -183,6 +188,7 @@ Hmac.prototype.digest = function digest(outputEncoding) { const state = this[kState]; if (state[kFinalized]) { + emitHmacDigestDeprecation(); const buf = Buffer.from(''); if (outputEncoding && outputEncoding !== 'buffer') return buf.toString(outputEncoding); diff --git a/test/parallel/test-crypto-dep0181.js b/test/parallel/test-crypto-dep0181.js new file mode 100644 index 00000000000000..96e8119dfdb6d7 --- /dev/null +++ b/test/parallel/test-crypto-dep0181.js @@ -0,0 +1,19 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const crypto = require('crypto'); + +common.expectWarning({ + DeprecationWarning: { + DEP0181: 'crypto.Hmac constructor is deprecated.', + }, +}); + +const Hmac = crypto.Hmac; +const instance = crypto.Hmac('sha256', 'Node'); +assert(instance instanceof Hmac, 'Hmac is expected to return a new instance' + + ' when called without `new`'); diff --git a/test/parallel/test-crypto-dep0206.js b/test/parallel/test-crypto-dep0206.js new file mode 100644 index 00000000000000..4c48ddad6f9eca --- /dev/null +++ b/test/parallel/test-crypto-dep0206.js @@ -0,0 +1,56 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const crypto = require('crypto'); + +common.expectWarning({ + DeprecationWarning: { + DEP0206: 'Calling Hmac.digest() more than once is deprecated.', + }, +}); + +// Verify runtime deprecation warning for calling digest() more than once. +{ + const h = crypto.createHmac('sha1', 'key').update('data'); + h.digest('hex'); + h.digest('hex'); +} + +// Check initialized -> uninitialized state transition after calling digest(). +{ + const expected = + '\u0010\u0041\u0052\u00c5\u00bf\u00dc\u00a0\u007b\u00c6\u0033' + + '\u00ee\u00bd\u0046\u0019\u009f\u0002\u0055\u00c9\u00f4\u009d'; + { + const h = crypto.createHmac('sha1', 'key').update('data'); + assert.deepStrictEqual(h.digest('buffer'), Buffer.from(expected, 'latin1')); + assert.deepStrictEqual(h.digest('buffer'), Buffer.from('')); + } + { + const h = crypto.createHmac('sha1', 'key').update('data'); + assert.strictEqual(h.digest('latin1'), expected); + assert.strictEqual(h.digest('latin1'), ''); + } +} + +// Check initialized -> uninitialized state transition after calling digest(). +// Calls to update() omitted intentionally. +{ + const expected = + '\u00f4\u002b\u00b0\u00ee\u00b0\u0018\u00eb\u00bd\u0045\u0097' + + '\u00ae\u0072\u0013\u0071\u001e\u00c6\u0007\u0060\u0084\u003f'; + { + const h = crypto.createHmac('sha1', 'key'); + assert.deepStrictEqual(h.digest('buffer'), Buffer.from(expected, 'latin1')); + assert.deepStrictEqual(h.digest('buffer'), Buffer.from('')); + } + { + const h = crypto.createHmac('sha1', 'key'); + assert.strictEqual(h.digest('latin1'), expected); + assert.strictEqual(h.digest('latin1'), ''); + } +} diff --git a/test/parallel/test-crypto-hmac.js b/test/parallel/test-crypto-hmac.js index afb5f74cbf076b..7af6ce37b578e2 100644 --- a/test/parallel/test-crypto-hmac.js +++ b/test/parallel/test-crypto-hmac.js @@ -7,13 +7,6 @@ if (!common.hasCrypto) { const assert = require('assert'); const crypto = require('crypto'); -{ - const Hmac = crypto.Hmac; - const instance = crypto.Hmac('sha256', 'Node'); - assert(instance instanceof Hmac, 'Hmac is expected to return a new instance' + - ' when called without `new`'); -} - assert.throws( () => crypto.createHmac(null), { @@ -411,41 +404,6 @@ assert.strictEqual( crypto.createHmac('sha256', 'w00t').digest('ucs2'), crypto.createHmac('sha256', 'w00t').digest().toString('ucs2')); -// Check initialized -> uninitialized state transition after calling digest(). -{ - const expected = - '\u0010\u0041\u0052\u00c5\u00bf\u00dc\u00a0\u007b\u00c6\u0033' + - '\u00ee\u00bd\u0046\u0019\u009f\u0002\u0055\u00c9\u00f4\u009d'; - { - const h = crypto.createHmac('sha1', 'key').update('data'); - assert.deepStrictEqual(h.digest('buffer'), Buffer.from(expected, 'latin1')); - assert.deepStrictEqual(h.digest('buffer'), Buffer.from('')); - } - { - const h = crypto.createHmac('sha1', 'key').update('data'); - assert.strictEqual(h.digest('latin1'), expected); - assert.strictEqual(h.digest('latin1'), ''); - } -} - -// Check initialized -> uninitialized state transition after calling digest(). -// Calls to update() omitted intentionally. -{ - const expected = - '\u00f4\u002b\u00b0\u00ee\u00b0\u0018\u00eb\u00bd\u0045\u0097' + - '\u00ae\u0072\u0013\u0071\u001e\u00c6\u0007\u0060\u0084\u003f'; - { - const h = crypto.createHmac('sha1', 'key'); - assert.deepStrictEqual(h.digest('buffer'), Buffer.from(expected, 'latin1')); - assert.deepStrictEqual(h.digest('buffer'), Buffer.from('')); - } - { - const h = crypto.createHmac('sha1', 'key'); - assert.strictEqual(h.digest('latin1'), expected); - assert.strictEqual(h.digest('latin1'), ''); - } -} - { assert.throws( () => crypto.createHmac('sha7', 'key'), @@ -460,13 +418,3 @@ assert.strictEqual( crypto.createHmac('sha256', keyObject).update('foo').digest(), ); } - -{ - crypto.Hmac('sha256', 'Node'); - common.expectWarning({ - DeprecationWarning: [ - ['crypto.Hmac constructor is deprecated.', - 'DEP0181'], - ] - }); -}