mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 13:48:44 +02:00
crypto: fix SHAKE128/256 breaking change introduced with OpenSSL 3.4
Some checks failed
Test and upload documentation to artifacts / build-docs (push) Failing after 7m39s
Linters / lint-addon-docs (push) Successful in 2m13s
Linters / format-cpp (push) Has been skipped
Linters / lint-cpp (push) Successful in 5m48s
Linters / lint-py (push) Successful in 2m38s
Linters / lint-yaml (push) Successful in 2m24s
Linters / lint-js-and-md (push) Successful in 9m18s
Linters / lint-codeowners (push) Failing after 56s
Linters / lint-pr-url (push) Has been skipped
Linters / lint-sh (push) Failing after 1m17s
Linters / lint-readme (push) Successful in 1m18s
Some checks failed
Test and upload documentation to artifacts / build-docs (push) Failing after 7m39s
Linters / lint-addon-docs (push) Successful in 2m13s
Linters / format-cpp (push) Has been skipped
Linters / lint-cpp (push) Successful in 5m48s
Linters / lint-py (push) Successful in 2m38s
Linters / lint-yaml (push) Successful in 2m24s
Linters / lint-js-and-md (push) Successful in 9m18s
Linters / lint-codeowners (push) Failing after 56s
Linters / lint-pr-url (push) Has been skipped
Linters / lint-sh (push) Failing after 1m17s
Linters / lint-readme (push) Successful in 1m18s
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 Backport-PR-URL: https://github.com/nodejs/node/pull/58961 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
7f8d1b2681
commit
89366abd4d
7 changed files with 112 additions and 22 deletions
|
@ -3589,6 +3589,39 @@ Type: Documentation-only
|
|||
Passing non-supported argument types is deprecated and, instead of returning `false`,
|
||||
will throw an error in a future version.
|
||||
|
||||
<!-- md-lint skip-deprecation DEP0188 -->
|
||||
|
||||
<!-- md-lint skip-deprecation DEP0189 -->
|
||||
|
||||
<!-- md-lint skip-deprecation DEP0190 -->
|
||||
|
||||
<!-- md-lint skip-deprecation DEP0191 -->
|
||||
|
||||
<!-- md-lint skip-deprecation DEP0192 -->
|
||||
|
||||
<!-- md-lint skip-deprecation DEP0193 -->
|
||||
|
||||
<!-- md-lint skip-deprecation DEP0194 -->
|
||||
|
||||
<!-- md-lint skip-deprecation DEP0195 -->
|
||||
|
||||
<!-- md-lint skip-deprecation DEP0196 -->
|
||||
|
||||
<!-- md-lint skip-deprecation DEP0197 -->
|
||||
|
||||
### 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.
|
||||
|
||||
[NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
|
||||
[RFC 6066]: https://tools.ietf.org/html/rfc6066#section-3
|
||||
[RFC 8247 Section 2.4]: https://www.rfc-editor.org/rfc/rfc8247#section-2.4
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -104,8 +104,8 @@ function getDeprecationWarningEmitter(
|
|||
shouldEmitWarning = () => true,
|
||||
) {
|
||||
let warned = false;
|
||||
return function() {
|
||||
if (!warned && shouldEmitWarning()) {
|
||||
return function(arg) {
|
||||
if (!warned && shouldEmitWarning(arg)) {
|
||||
warned = true;
|
||||
if (code !== undefined) {
|
||||
if (!codesWarned.has(code)) {
|
||||
|
@ -994,4 +994,6 @@ module.exports = {
|
|||
setOwnProperty,
|
||||
pendingDeprecate,
|
||||
WeakReference,
|
||||
isPendingDeprecation,
|
||||
getDeprecationWarningEmitter,
|
||||
};
|
||||
|
|
|
@ -341,10 +341,22 @@ bool Hash::HashInit(const EVP_MD* md, Maybe<unsigned int> xof_md_len) {
|
|||
}
|
||||
|
||||
md_len_ = EVP_MD_size(md);
|
||||
bool is_xof = (EVP_MD_flags(md) & EVP_MD_FLAG_XOF) != 0;
|
||||
if (is_xof && !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.
|
||||
if ((EVP_MD_flags(md) & EVP_MD_FLAG_XOF) == 0) {
|
||||
if (!is_xof) {
|
||||
EVPerr(EVP_F_EVP_DIGESTFINALXOF, EVP_R_NOT_XOF_OR_INVALID_LENGTH);
|
||||
return false;
|
||||
}
|
||||
|
|
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();
|
||||
}
|
|
@ -7,7 +7,6 @@ const assert = require('assert');
|
|||
const crypto = require('crypto');
|
||||
const fs = require('fs');
|
||||
|
||||
const { hasOpenSSL } = common;
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
let cryptoType;
|
||||
|
@ -183,21 +182,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 })
|
||||
|
|
|
@ -31,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') && common.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…
Add table
Add a link
Reference in a new issue