mirror of
https://github.com/nodejs/node.git
synced 2026-10-14 10:26:26 -04:00
crypto: move DEP0198 to End-of-Life
Signed-off-by: Filip Skokan <panva.ip@gmail.com> PR-URL: https://github.com/nodejs/node/pull/64000 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
This commit is contained in:
1 parent
b734ff562f
commit
b116861e88
10 files changed
+194
-106
No files matched your search
+12
-2
@@ -3771,6 +3771,10 @@ and description of each available elliptic curve.
|
||||
<!-- YAML
|
||||
added: v0.1.92
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/64000
|
||||
description: The `outputLength` option is now required for XOF
|
||||
hash functions without default output lengths.
|
||||
- version: v12.8.0
|
||||
pr-url: https://github.com/nodejs/node/pull/28805
|
||||
description: The `outputLength` option was added for XOF hash functions.
|
||||
@@ -3783,7 +3787,8 @@ changes:
|
||||
Creates and returns a `Hash` object that can be used to generate hash digests
|
||||
using the given `algorithm`. Optional `options` argument controls stream
|
||||
behavior. For XOF hash functions such as `'shake256'`, the `outputLength` option
|
||||
can be used to specify the desired output length in bytes.
|
||||
specifies the desired output length in bytes. It is required for XOF hash
|
||||
functions without a default output length.
|
||||
|
||||
The `algorithm` is dependent on the available algorithms supported by the
|
||||
version of OpenSSL on the platform. Examples are `'sha256'`, `'sha512'`, etc.
|
||||
@@ -4889,6 +4894,10 @@ added:
|
||||
- v21.7.0
|
||||
- v20.12.0
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/64000
|
||||
description: The `outputLength` option is now required for XOF
|
||||
hash functions without default output lengths.
|
||||
- version:
|
||||
- v25.5.0
|
||||
- v24.13.1
|
||||
@@ -4909,7 +4918,8 @@ changes:
|
||||
* `outputEncoding` {string} [Encoding][encoding] used to encode the
|
||||
returned digest. **Default:** `'hex'`.
|
||||
* `outputLength` {number} For XOF hash functions such as 'shake256',
|
||||
the outputLength option can be used to specify the desired output length in bytes.
|
||||
specifies the desired output length in bytes. This option is required for
|
||||
XOF hash functions without a default output length.
|
||||
* Returns: {string|Buffer}
|
||||
|
||||
A utility for creating one-shot hash digests of data. It can be faster than
|
||||
|
||||
@@ -4354,6 +4354,9 @@ npx codemod@latest @nodejs/types-is-native-error
|
||||
|
||||
<!-- YAML
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/64000
|
||||
description: End-of-Life.
|
||||
- version: v25.0.0
|
||||
pr-url: https://github.com/nodejs/node/pull/59008
|
||||
description: Runtime deprecation.
|
||||
@@ -4365,9 +4368,10 @@ changes:
|
||||
description: Documentation-only deprecation with support for `--pending-deprecation`.
|
||||
-->
|
||||
|
||||
Type: Runtime
|
||||
Type: End-of-Life
|
||||
|
||||
Creating SHAKE-128 and SHAKE-256 digests without an explicit `options.outputLength` is deprecated.
|
||||
Creating SHAKE-128 and SHAKE-256 digests without an explicit
|
||||
`options.outputLength` is no longer supported.
|
||||
|
||||
### DEP0199: `require('node:_http_*')`
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
const {
|
||||
FunctionPrototypeCall,
|
||||
ObjectSetPrototypeOf,
|
||||
StringPrototypeReplace,
|
||||
StringPrototypeToLowerCase,
|
||||
Symbol,
|
||||
TypedArrayPrototypeGetBuffer,
|
||||
@@ -73,25 +72,6 @@ const LazyTransform = require('internal/streams/lazy_transform');
|
||||
const kState = Symbol('kState');
|
||||
const kFinalized = Symbol('kFinalized');
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @returns {string}
|
||||
*/
|
||||
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) => {
|
||||
const normalized = normalizeAlgorithm(algorithm);
|
||||
return normalized === 'shake128' || normalized === 'shake256';
|
||||
},
|
||||
);
|
||||
|
||||
const emitHmacDigestDeprecation = getDeprecationWarningEmitter(
|
||||
'DEP0206',
|
||||
'Calling Hmac.digest() more than once is deprecated.',
|
||||
@@ -117,9 +97,6 @@ function Hash(algorithm, options) {
|
||||
this[kState] = {
|
||||
[kFinalized]: false,
|
||||
};
|
||||
if (!isCopy && xofLen === undefined) {
|
||||
maybeEmitDeprecationWarning(algorithm);
|
||||
}
|
||||
FunctionPrototypeCall(LazyTransform, this, options);
|
||||
}
|
||||
|
||||
@@ -334,10 +311,6 @@ function hash(algorithm, input, options) {
|
||||
outputLength += 0;
|
||||
}
|
||||
|
||||
if (outputLength === undefined) {
|
||||
maybeEmitDeprecationWarning(algorithm);
|
||||
}
|
||||
|
||||
return oneShotDigest(algorithm, getCachedHashId(algorithm), getHashCache(),
|
||||
input, normalized, encodingsMap[normalized], outputLength);
|
||||
}
|
||||
|
||||
+48
-30
@@ -246,6 +246,39 @@ const EVP_MD* GetDigestImplementation(Environment* env,
|
||||
#endif
|
||||
}
|
||||
|
||||
void MarkInvalidXofLength() {
|
||||
EVPerr(EVP_F_EVP_DIGESTFINALXOF, EVP_R_NOT_XOF_OR_INVALID_LENGTH);
|
||||
}
|
||||
|
||||
// DEP0198 EOL requires XOFs without an OpenSSL-defined default output length
|
||||
// to fail when outputLength is omitted. OpenSSL 3.4 and later report a digest
|
||||
// size of 0 for such XOFs, including SHAKE, which had weak historical defaults
|
||||
// before OpenSSL 3.4. For older OpenSSL versions, identify those resolved
|
||||
// EVP_MD values explicitly to keep the missing-outputLength error
|
||||
// version-independent.
|
||||
#if !OPENSSL_VERSION_PREREQ(3, 4)
|
||||
bool IsShakeDigest(const EVP_MD* md) {
|
||||
#if OPENSSL_VERSION_MAJOR >= 3
|
||||
return EVP_MD_is_a(md, "SHAKE128") || EVP_MD_is_a(md, "SHAKE256");
|
||||
#else
|
||||
const char* name = OBJ_nid2sn(EVP_MD_type(md));
|
||||
return name != nullptr &&
|
||||
(strcmp(name, "SHAKE128") == 0 || strcmp(name, "SHAKE256") == 0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ShouldRejectMissingXofLength(const EVP_MD* md, size_t default_length) {
|
||||
if (default_length == 0) return true;
|
||||
|
||||
#if !OPENSSL_VERSION_PREREQ(3, 4)
|
||||
return IsShakeDigest(md);
|
||||
#else
|
||||
static_cast<void>(md);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// crypto.digest(algorithm, algorithmId, algorithmCache,
|
||||
// input, outputEncoding, outputEncodingId, outputLength)
|
||||
void Hash::OneShotDigest(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -287,18 +320,10 @@ void Hash::OneShotDigest(const FunctionCallbackInfo<Value>& args) {
|
||||
} else if (is_xof) {
|
||||
if (!args[6]->IsUndefined()) {
|
||||
output_length = args[6].As<Uint32>()->Value();
|
||||
} else if (output_length == 0) {
|
||||
// This is to handle OpenSSL 3.4's breaking change in SHAKE128/256
|
||||
// default lengths
|
||||
// TODO(@panva): remove this behaviour when DEP0198 is End-Of-Life
|
||||
const char* name = OBJ_nid2sn(EVP_MD_type(md));
|
||||
if (name != nullptr) {
|
||||
if (strcmp(name, "SHAKE128") == 0) {
|
||||
output_length = 16;
|
||||
} else if (strcmp(name, "SHAKE256") == 0) {
|
||||
output_length = 32;
|
||||
}
|
||||
}
|
||||
} else if (ShouldRejectMissingXofLength(md, output_length)) {
|
||||
MarkInvalidXofLength();
|
||||
return ThrowCryptoError(
|
||||
env, ERR_get_error(), "Digest method not supported");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,6 +412,12 @@ void Hash::RegisterExternalReferences(ExternalReferenceRegistry* registry) {
|
||||
void Hash::New(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
|
||||
Maybe<unsigned int> xof_md_len = Nothing<unsigned int>();
|
||||
if (!args[1]->IsUndefined()) {
|
||||
CHECK(args[1]->IsUint32());
|
||||
xof_md_len = Just<unsigned int>(args[1].As<Uint32>()->Value());
|
||||
}
|
||||
|
||||
const Hash* orig = nullptr;
|
||||
const EVP_MD* md = nullptr;
|
||||
if (args[0]->IsObject()) {
|
||||
@@ -397,12 +428,6 @@ void Hash::New(const FunctionCallbackInfo<Value>& args) {
|
||||
md = GetDigestImplementation(env, args[0], args[2], args[3]);
|
||||
}
|
||||
|
||||
Maybe<unsigned int> xof_md_len = Nothing<unsigned int>();
|
||||
if (!args[1]->IsUndefined()) {
|
||||
CHECK(args[1]->IsUint32());
|
||||
xof_md_len = Just<unsigned int>(args[1].As<Uint32>()->Value());
|
||||
}
|
||||
|
||||
Hash* hash = new Hash(env, args.This());
|
||||
if (md == nullptr || !hash->HashInit(md, xof_md_len)) {
|
||||
return ThrowCryptoError(env, ERR_get_error(),
|
||||
@@ -423,18 +448,11 @@ bool Hash::HashInit(const EVP_MD* md, Maybe<unsigned int> xof_md_len) {
|
||||
|
||||
md_len_ = mdctx_.getDigestSize();
|
||||
|
||||
// This is to handle OpenSSL 3.4's breaking change in SHAKE128/256
|
||||
// default lengths
|
||||
// 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 (mdctx_.hasXofFlag() && !xof_md_len.IsJust() &&
|
||||
ShouldRejectMissingXofLength(md, md_len_)) {
|
||||
MarkInvalidXofLength();
|
||||
mdctx_.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (xof_md_len.IsJust() && xof_md_len.FromJust() != md_len_) {
|
||||
|
||||
@@ -4,17 +4,34 @@ const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
if (process.features.openssl_is_boringssl)
|
||||
common.skip('not supported by BoringSSL');
|
||||
const {
|
||||
getHashes,
|
||||
hash,
|
||||
} = require('crypto');
|
||||
|
||||
const { hash } = require('crypto');
|
||||
if (!getHashes().includes('shake128'))
|
||||
common.skip('unsupported shake128 test');
|
||||
|
||||
common.expectWarning({
|
||||
DeprecationWarning: {
|
||||
DEP0198: 'Creating SHAKE128/256 digests without an explicit options.outputLength is deprecated.',
|
||||
}
|
||||
});
|
||||
const assert = require('assert');
|
||||
|
||||
{
|
||||
hash('shake128', 'test');
|
||||
const invalidXofLength = {
|
||||
code: 'ERR_OSSL_EVP_NOT_XOF_OR_INVALID_LENGTH',
|
||||
name: 'Error',
|
||||
message: /not XOF or invalid length/,
|
||||
};
|
||||
|
||||
const shakeAlgorithms = [
|
||||
'shake128',
|
||||
'SHAKE128',
|
||||
'shake256',
|
||||
'SHAKE256',
|
||||
];
|
||||
|
||||
for (const algorithm of shakeAlgorithms) {
|
||||
assert.throws(() => hash(algorithm, 'test'), invalidXofLength);
|
||||
assert.throws(() => hash(algorithm, 'test', 'hex'), invalidXofLength);
|
||||
assert.throws(
|
||||
() => hash(algorithm, 'test', { outputEncoding: 'buffer' }),
|
||||
invalidXofLength);
|
||||
assert.throws(() => hash(algorithm, 'test', {}), invalidXofLength);
|
||||
}
|
||||
@@ -4,19 +4,39 @@ const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const crypto = require('crypto');
|
||||
if (!crypto.getHashes().includes('shake128')) {
|
||||
const {
|
||||
createHash,
|
||||
getHashes,
|
||||
} = require('crypto');
|
||||
|
||||
if (!getHashes().includes('shake128'))
|
||||
common.skip('unsupported shake128 test');
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
const invalidXofLength = {
|
||||
code: 'ERR_OSSL_EVP_NOT_XOF_OR_INVALID_LENGTH',
|
||||
name: 'Error',
|
||||
message: /not XOF or invalid length/,
|
||||
};
|
||||
|
||||
const shakeAlgorithms = [
|
||||
'shake128',
|
||||
'SHAKE128',
|
||||
'shake256',
|
||||
'SHAKE256',
|
||||
];
|
||||
|
||||
for (const algorithm of shakeAlgorithms) {
|
||||
assert.throws(() => createHash(algorithm), invalidXofLength);
|
||||
assert.throws(() => createHash(algorithm, null), invalidXofLength);
|
||||
assert.throws(() => createHash(algorithm, {}), invalidXofLength);
|
||||
}
|
||||
|
||||
const { createHash } = require('crypto');
|
||||
const shake128 = createHash('shake128', { outputLength: 5 });
|
||||
const shake128Copy = shake128.copy({ outputLength: 5 });
|
||||
|
||||
common.expectWarning({
|
||||
DeprecationWarning: {
|
||||
DEP0198: 'Creating SHAKE128/256 digests without an explicit options.outputLength is deprecated.',
|
||||
}
|
||||
});
|
||||
|
||||
{
|
||||
createHash('shake128').update('test').digest();
|
||||
}
|
||||
assert.throws(() => shake128.copy(), invalidXofLength);
|
||||
assert.throws(() => shake128.copy(null), invalidXofLength);
|
||||
assert.throws(() => shake128.copy({}), invalidXofLength);
|
||||
assert.throws(() => shake128Copy.copy(), invalidXofLength);
|
||||
@@ -8,10 +8,6 @@ common.expectWarning({
|
||||
DeprecationWarning: [
|
||||
['crypto.Hash constructor is deprecated.',
|
||||
'DEP0179'],
|
||||
...(process.features.openssl_is_boringssl ? [] : [[
|
||||
'Creating SHAKE128/256 digests without an explicit options.outputLength is deprecated.',
|
||||
'DEP0198',
|
||||
]]),
|
||||
]
|
||||
});
|
||||
|
||||
@@ -194,16 +190,29 @@ assert.throws(
|
||||
|
||||
// Test XOF hash functions and the outputLength option.
|
||||
if (!process.features.openssl_is_boringssl) {
|
||||
// Default outputLengths.
|
||||
assert.strictEqual(crypto.createHash('shake128').digest('hex'),
|
||||
const invalidXofLength = {
|
||||
code: 'ERR_OSSL_EVP_NOT_XOF_OR_INVALID_LENGTH',
|
||||
name: 'Error',
|
||||
message: /not XOF or invalid length/,
|
||||
};
|
||||
|
||||
assert.throws(() => crypto.createHash('shake128'), invalidXofLength);
|
||||
assert.throws(() => crypto.createHash('shake128', null), invalidXofLength);
|
||||
assert.throws(() => crypto.createHash('shake256'), invalidXofLength);
|
||||
assert.throws(() => crypto.createHash('shake256', {}), invalidXofLength);
|
||||
|
||||
assert.strictEqual(crypto.createHash('shake128', { outputLength: 16 })
|
||||
.digest('hex'),
|
||||
'7f9c2ba4e88f827d616045507605853e');
|
||||
assert.strictEqual(crypto.createHash('shake128', null).digest('hex'),
|
||||
'7f9c2ba4e88f827d616045507605853e');
|
||||
assert.strictEqual(crypto.createHash('shake256').digest('hex'),
|
||||
assert.strictEqual(crypto.createHash('shake256', { outputLength: 32 })
|
||||
.digest('hex'),
|
||||
'46b9dd2b0ba88d13233b3feb743eeb24' +
|
||||
'3fcd52ea62b81b82b50c27646ed5762f');
|
||||
assert.strictEqual(crypto.createHash('shake256', { outputLength: 0 })
|
||||
.copy() // Default outputLength.
|
||||
const shake256 = crypto.createHash('shake256', { outputLength: 0 });
|
||||
assert.throws(() => shake256.copy(), invalidXofLength);
|
||||
assert.throws(() => shake256.copy(null), invalidXofLength);
|
||||
assert.throws(() => shake256.copy({}), invalidXofLength);
|
||||
assert.strictEqual(shake256.copy({ outputLength: 32 })
|
||||
.digest('hex'),
|
||||
'46b9dd2b0ba88d13233b3feb743eeb24' +
|
||||
'3fcd52ea62b81b82b50c27646ed5762f');
|
||||
|
||||
@@ -13,35 +13,47 @@ if (process.features.openssl_is_boringssl) {
|
||||
|
||||
// Test XOF hash functions and the outputLength option.
|
||||
{
|
||||
// Default outputLengths.
|
||||
const invalidXofLength = {
|
||||
code: 'ERR_OSSL_EVP_NOT_XOF_OR_INVALID_LENGTH',
|
||||
name: 'Error',
|
||||
message: /not XOF or invalid length/,
|
||||
};
|
||||
|
||||
assert.throws(() => crypto.hash('shake128', ''), invalidXofLength);
|
||||
assert.throws(() => crypto.hash('shake128', '', 'hex'), invalidXofLength);
|
||||
assert.throws(
|
||||
() => crypto.hash('shake128', '', { outputEncoding: 'buffer' }),
|
||||
invalidXofLength);
|
||||
assert.throws(() => crypto.hash('shake256', ''), invalidXofLength);
|
||||
|
||||
assert.strictEqual(
|
||||
crypto.hash('shake128', ''),
|
||||
crypto.hash('shake128', '', { outputLength: 16 }),
|
||||
'7f9c2ba4e88f827d616045507605853e'
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
crypto.hash('shake256', ''),
|
||||
crypto.hash('shake256', '', { outputLength: 32 }),
|
||||
'46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762f'
|
||||
);
|
||||
|
||||
// outputEncoding as an option.
|
||||
assert.strictEqual(
|
||||
crypto.hash('shake128', '', { outputEncoding: 'base64url' }),
|
||||
crypto.hash('shake128', '', { outputEncoding: 'base64url', outputLength: 16 }),
|
||||
'f5wrpOiPgn1hYEVQdgWFPg'
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
crypto.hash('shake256', '', { outputEncoding: 'base64url' }),
|
||||
crypto.hash('shake256', '', { outputEncoding: 'base64url', outputLength: 32 }),
|
||||
'RrndKwuojRMjOz_rdD7rJD_NUupiuBuCtQwnZG7Vdi8'
|
||||
);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
crypto.hash('shake128', '', { outputEncoding: 'buffer' }),
|
||||
crypto.hash('shake128', '', { outputEncoding: 'buffer', outputLength: 16 }),
|
||||
Buffer.from('f5wrpOiPgn1hYEVQdgWFPg', 'base64url')
|
||||
);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
crypto.hash('shake256', '', { outputEncoding: 'buffer' }),
|
||||
crypto.hash('shake256', '', { outputEncoding: 'buffer', outputLength: 32 }),
|
||||
Buffer.from('RrndKwuojRMjOz_rdD7rJD_NUupiuBuCtQwnZG7Vdi8', 'base64url')
|
||||
);
|
||||
|
||||
|
||||
@@ -10,6 +10,17 @@ const crypto = require('crypto');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const fs = require('fs');
|
||||
|
||||
const invalidXofLengthCode = 'ERR_OSSL_EVP_NOT_XOF_OR_INVALID_LENGTH';
|
||||
|
||||
function getXofOptions(method) {
|
||||
try {
|
||||
crypto.createHash(method);
|
||||
} catch (err) {
|
||||
if (err?.code !== invalidXofLengthCode) throw err;
|
||||
return { outputLength: 16 };
|
||||
}
|
||||
}
|
||||
|
||||
// Test errors for invalid arguments.
|
||||
[undefined, null, true, 1, () => {}, {}].forEach((invalid) => {
|
||||
assert.throws(() => { crypto.hash(invalid, 'test'); }, { code: 'ERR_INVALID_ARG_TYPE' });
|
||||
@@ -31,12 +42,20 @@ const methods = crypto.getHashes();
|
||||
const input = fs.readFileSync(fixtures.path('utf8_test_text.txt'));
|
||||
|
||||
for (const method of methods) {
|
||||
const xofOptions = getXofOptions(method);
|
||||
|
||||
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);
|
||||
const options = xofOptions === undefined || outputEncoding === undefined ?
|
||||
xofOptions : { ...xofOptions, outputEncoding };
|
||||
const oldDigest = crypto.createHash(method, xofOptions)
|
||||
.update(input)
|
||||
.digest(outputEncoding || 'hex');
|
||||
const digestFromBuffer = crypto.hash(
|
||||
method, input, options === undefined ? outputEncoding : options);
|
||||
assert.deepStrictEqual(digestFromBuffer, oldDigest,
|
||||
`different result from ${method} with encoding ${outputEncoding}`);
|
||||
const digestFromString = crypto.hash(method, input.toString(), outputEncoding);
|
||||
const digestFromString = crypto.hash(
|
||||
method, input.toString(), options === undefined ? outputEncoding : options);
|
||||
assert.deepStrictEqual(digestFromString, oldDigest,
|
||||
`different result from ${method} with encoding ${outputEncoding}`);
|
||||
}
|
||||
|
||||
@@ -151,8 +151,14 @@ if (!process.features.openssl_is_boringssl) {
|
||||
}
|
||||
validateList(crypto.getHashes());
|
||||
// Make sure all of the hashes are supported by OpenSSL
|
||||
for (const algo of crypto.getHashes())
|
||||
crypto.createHash(algo);
|
||||
for (const algo of crypto.getHashes()) {
|
||||
try {
|
||||
crypto.createHash(algo);
|
||||
} catch (err) {
|
||||
if (err?.code !== 'ERR_OSSL_EVP_NOT_XOF_OR_INVALID_LENGTH') throw err;
|
||||
crypto.createHash(algo, { outputLength: 0 });
|
||||
}
|
||||
}
|
||||
|
||||
// Assume that we have at least secp384r1.
|
||||
assert.notStrictEqual(crypto.getCurves().length, 0);
|
||||
|
||||
Reference in new issue
Block a user