mirror of
https://github.com/nodejs/node.git
synced 2025-12-28 07:50:41 +00:00
crypto: fix SHAKE128/256 breaking change introduced with OpenSSL 3.4
Reverts: https://github.com/nodejs/node/pull/56160 Fixes: https://github.com/nodejs/node/issues/56159 Fixes: https://github.com/nodejs/node/issues/58913 Refs: https://github.com/nodejs/node/pull/58121 PR-URL: https://github.com/nodejs/node/pull/58942 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This commit is contained in:
parent
053467253d
commit
f5da8f89ee
@ -4061,6 +4061,19 @@ Type: Documentation-only
|
||||
|
||||
The [`util.types.isNativeError`][] API is deprecated. Please use [`Error.isError`][] instead.
|
||||
|
||||
### DEP0198: Creating SHAKE-128 and SHAKE-256 digests without an explicit `options.outputLength`
|
||||
|
||||
<!-- YAML
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/58942
|
||||
description: Documentation-only deprecation with support for `--pending-deprecation`.
|
||||
-->
|
||||
|
||||
Type: Documentation-only (supports [`--pending-deprecation`][])
|
||||
|
||||
Creating SHAKE-128 and SHAKE-256 digests without an explicit `options.outputLength` is deprecated.
|
||||
|
||||
[DEP0142]: #dep0142-repl_builtinlibs
|
||||
[NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
|
||||
[RFC 6066]: https://tools.ietf.org/html/rfc6066#section-3
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
const {
|
||||
ObjectSetPrototypeOf,
|
||||
ReflectApply,
|
||||
StringPrototypeReplace,
|
||||
StringPrototypeToLowerCase,
|
||||
Symbol,
|
||||
} = primordials;
|
||||
@ -33,6 +34,8 @@ const {
|
||||
lazyDOMException,
|
||||
normalizeEncoding,
|
||||
encodingsMap,
|
||||
isPendingDeprecation,
|
||||
getDeprecationWarningEmitter,
|
||||
} = require('internal/util');
|
||||
|
||||
const {
|
||||
@ -63,6 +66,25 @@ const LazyTransform = require('internal/streams/lazy_transform');
|
||||
const kState = Symbol('kState');
|
||||
const kFinalized = Symbol('kFinalized');
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
function normalizeAlgorithm(name) {
|
||||
return StringPrototypeReplace(StringPrototypeToLowerCase(name), '-', '');
|
||||
}
|
||||
|
||||
const maybeEmitDeprecationWarning = getDeprecationWarningEmitter(
|
||||
'DEP0198',
|
||||
'Creating SHAKE128/256 digests without an explicit options.outputLength is deprecated.',
|
||||
undefined,
|
||||
false,
|
||||
(algorithm) => {
|
||||
if (!isPendingDeprecation()) return false;
|
||||
const normalized = normalizeAlgorithm(algorithm);
|
||||
return normalized === 'shake128' || normalized === 'shake256';
|
||||
},
|
||||
);
|
||||
|
||||
function Hash(algorithm, options) {
|
||||
if (!new.target)
|
||||
return new Hash(algorithm, options);
|
||||
@ -80,6 +102,9 @@ function Hash(algorithm, options) {
|
||||
this[kState] = {
|
||||
[kFinalized]: false,
|
||||
};
|
||||
if (!isCopy && xofLen === undefined) {
|
||||
maybeEmitDeprecationWarning(algorithm);
|
||||
}
|
||||
ReflectApply(LazyTransform, this, [options]);
|
||||
}
|
||||
|
||||
@ -213,6 +238,12 @@ function hash(algorithm, input, outputEncoding = 'hex') {
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: ideally we have to ship https://github.com/nodejs/node/pull/58121 so
|
||||
// that a proper DEP0198 deprecation can be done here as well.
|
||||
const normalizedAlgorithm = normalizeAlgorithm(algorithm);
|
||||
if (normalizedAlgorithm === 'shake128' || normalizedAlgorithm === 'shake256') {
|
||||
return new Hash(algorithm).update(input).digest(normalized);
|
||||
}
|
||||
return oneShotDigest(algorithm, getCachedHashId(algorithm), getHashCache(),
|
||||
input, normalized, encodingsMap[normalized]);
|
||||
}
|
||||
|
||||
@ -110,8 +110,8 @@ function getDeprecationWarningEmitter(
|
||||
shouldEmitWarning = () => true,
|
||||
) {
|
||||
let warned = false;
|
||||
return function() {
|
||||
if (!warned && shouldEmitWarning()) {
|
||||
return function(arg) {
|
||||
if (!warned && shouldEmitWarning(arg)) {
|
||||
warned = true;
|
||||
if (code === 'ExperimentalWarning') {
|
||||
process.emitWarning(msg, code, deprecated);
|
||||
@ -1011,4 +1011,6 @@ module.exports = {
|
||||
setOwnProperty,
|
||||
pendingDeprecate,
|
||||
WeakReference,
|
||||
isPendingDeprecation,
|
||||
getDeprecationWarningEmitter,
|
||||
};
|
||||
|
||||
@ -331,6 +331,18 @@ bool Hash::HashInit(const EVP_MD* md, Maybe<unsigned int> xof_md_len) {
|
||||
}
|
||||
|
||||
md_len_ = mdctx_.getDigestSize();
|
||||
// TODO(@panva): remove this behaviour when DEP0198 is End-Of-Life
|
||||
if (mdctx_.hasXofFlag() && !xof_md_len.IsJust() && md_len_ == 0) {
|
||||
const char* name = OBJ_nid2sn(EVP_MD_type(md));
|
||||
if (name != nullptr) {
|
||||
if (strcmp(name, "SHAKE128") == 0) {
|
||||
md_len_ = 16;
|
||||
} else if (strcmp(name, "SHAKE256") == 0) {
|
||||
md_len_ = 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (xof_md_len.IsJust() && xof_md_len.FromJust() != md_len_) {
|
||||
// This is a little hack to cause createHash to fail when an incorrect
|
||||
// hashSize option was passed for a non-XOF hash function.
|
||||
|
||||
18
test/parallel/test-crypto-default-shake-lengths.js
Normal file
18
test/parallel/test-crypto-default-shake-lengths.js
Normal file
@ -0,0 +1,18 @@
|
||||
// Flags: --pending-deprecation
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const { createHash } = require('crypto');
|
||||
|
||||
common.expectWarning({
|
||||
DeprecationWarning: {
|
||||
DEP0198: 'Creating SHAKE128/256 digests without an explicit options.outputLength is deprecated.',
|
||||
}
|
||||
});
|
||||
|
||||
{
|
||||
createHash('shake128').update('test').digest();
|
||||
}
|
||||
@ -8,7 +8,6 @@ const assert = require('assert');
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs');
|
||||
|
||||
const { hasOpenSSL } = require('../common/crypto');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
let cryptoType;
|
||||
@ -184,21 +183,19 @@ assert.throws(
|
||||
|
||||
// Test XOF hash functions and the outputLength option.
|
||||
{
|
||||
// Default outputLengths. Since OpenSSL 3.4 an outputLength is mandatory
|
||||
if (!hasOpenSSL(3, 4)) {
|
||||
assert.strictEqual(crypto.createHash('shake128').digest('hex'),
|
||||
'7f9c2ba4e88f827d616045507605853e');
|
||||
assert.strictEqual(crypto.createHash('shake128', null).digest('hex'),
|
||||
'7f9c2ba4e88f827d616045507605853e');
|
||||
assert.strictEqual(crypto.createHash('shake256').digest('hex'),
|
||||
'46b9dd2b0ba88d13233b3feb743eeb24' +
|
||||
'3fcd52ea62b81b82b50c27646ed5762f');
|
||||
assert.strictEqual(crypto.createHash('shake256', { outputLength: 0 })
|
||||
.copy() // Default outputLength.
|
||||
.digest('hex'),
|
||||
'46b9dd2b0ba88d13233b3feb743eeb24' +
|
||||
'3fcd52ea62b81b82b50c27646ed5762f');
|
||||
}
|
||||
// Default outputLengths.
|
||||
assert.strictEqual(crypto.createHash('shake128').digest('hex'),
|
||||
'7f9c2ba4e88f827d616045507605853e');
|
||||
assert.strictEqual(crypto.createHash('shake128', null).digest('hex'),
|
||||
'7f9c2ba4e88f827d616045507605853e');
|
||||
assert.strictEqual(crypto.createHash('shake256').digest('hex'),
|
||||
'46b9dd2b0ba88d13233b3feb743eeb24' +
|
||||
'3fcd52ea62b81b82b50c27646ed5762f');
|
||||
assert.strictEqual(crypto.createHash('shake256', { outputLength: 0 })
|
||||
.copy() // Default outputLength.
|
||||
.digest('hex'),
|
||||
'46b9dd2b0ba88d13233b3feb743eeb24' +
|
||||
'3fcd52ea62b81b82b50c27646ed5762f');
|
||||
|
||||
// Short outputLengths.
|
||||
assert.strictEqual(crypto.createHash('shake128', { outputLength: 0 })
|
||||
|
||||
@ -8,7 +8,6 @@ if (!common.hasCrypto)
|
||||
const assert = require('assert');
|
||||
const crypto = require('crypto');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { hasOpenSSL } = require('../common/crypto');
|
||||
const fs = require('fs');
|
||||
|
||||
// Test errors for invalid arguments.
|
||||
@ -32,9 +31,6 @@ const methods = crypto.getHashes();
|
||||
const input = fs.readFileSync(fixtures.path('utf8_test_text.txt'));
|
||||
|
||||
for (const method of methods) {
|
||||
// Skip failing tests on OpenSSL 3.4.0
|
||||
if (method.startsWith('shake') && hasOpenSSL(3, 4))
|
||||
continue;
|
||||
for (const outputEncoding of ['buffer', 'hex', 'base64', undefined]) {
|
||||
const oldDigest = crypto.createHash(method).update(input).digest(outputEncoding || 'hex');
|
||||
const digestFromBuffer = crypto.hash(method, input, outputEncoding);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user