mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
Co-authored-by: Filip Skokan <panva.ip@gmail.com> Co-authored-by: James M Snell <jasnell@gmail.com> PR-URL: https://github.com/nodejs/node/pull/50353 Reviewed-By: Ethan Arrowood <ethan@arrowood.dev> Reviewed-By: Filip Skokan <panva.ip@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
140 lines
5.2 KiB
JavaScript
140 lines
5.2 KiB
JavaScript
'use strict';
|
|
const common = require('../common');
|
|
if (!common.hasCrypto)
|
|
common.skip('missing crypto');
|
|
|
|
const { hasOpenSSL } = require('../common/crypto');
|
|
|
|
if (!hasOpenSSL(3, 2))
|
|
common.skip('requires OpenSSL >= 3.2');
|
|
|
|
const assert = require('node:assert');
|
|
const crypto = require('node:crypto');
|
|
|
|
function runArgon2(algorithm, options) {
|
|
const syncResult = crypto.argon2Sync(algorithm, options);
|
|
|
|
crypto.argon2(algorithm, options,
|
|
common.mustSucceed((asyncResult) => {
|
|
assert.deepStrictEqual(asyncResult, syncResult);
|
|
}));
|
|
|
|
return syncResult;
|
|
}
|
|
|
|
const message = Buffer.alloc(32, 0x01);
|
|
const nonce = Buffer.alloc(16, 0x02);
|
|
const secret = Buffer.alloc(8, 0x03);
|
|
const associatedData = Buffer.alloc(12, 0x04);
|
|
const defaults = { message, nonce, parallelism: 1, tagLength: 64, memory: 8, passes: 3 };
|
|
|
|
const good = [
|
|
// Test vectors from RFC 9106 https://www.rfc-editor.org/rfc/rfc9106.html#name-test-vectors
|
|
// and OpenSSL 3.2 https://github.com/openssl/openssl/blob/6dfa998f7ea150f9c6d4e4727cf6d5c82a68a8da/test/recipes/30-test_evp_data/evpkdf_argon2.txt
|
|
//
|
|
// OpenSSL defaults are:
|
|
// - outlen: 64
|
|
// - passes: 3
|
|
// - parallelism: 1
|
|
// - memory: 8
|
|
// https://github.com/openssl/openssl/blob/6dfa998f7ea150f9c6d4e4727cf6d5c82a68a8da/providers/implementations/kdfs/argon2.c#L77-L82
|
|
[
|
|
'argon2d',
|
|
{ secret, associatedData, parallelism: 4, tagLength: 32, memory: 32 },
|
|
'512b391b6f1162975371d30919734294f868e3be3984f3c1a13a4db9fabe4acb',
|
|
],
|
|
[
|
|
'argon2i',
|
|
{ secret, associatedData, parallelism: 4, tagLength: 32, memory: 32 },
|
|
'c814d9d1dc7f37aa13f0d77f2494bda1c8de6b016dd388d29952a4c4672b6ce8',
|
|
],
|
|
[
|
|
'argon2id',
|
|
{ secret, associatedData, parallelism: 4, tagLength: 32, memory: 32 },
|
|
'0d640df58d78766c08c037a34a8b53c9d01ef0452d75b65eb52520e96b01e659',
|
|
],
|
|
[
|
|
'argon2d',
|
|
{ message: '1234567890', nonce: 'saltsalt' },
|
|
'd16ad773b1c6400d3193bc3e66271603e9de72bace20af3f89c236f5434cdec9' +
|
|
'9072ddfc6b9c77ea9f386c0e8d7cb0c37cec6ec3277a22c92d5be58ef67c7eaa',
|
|
],
|
|
[
|
|
'argon2id',
|
|
{ message: '', parallelism: 4, tagLength: 32, memory: 32 },
|
|
'0a34f1abde67086c82e785eaf17c68382259a264f4e61b91cd2763cb75ac189a',
|
|
],
|
|
[
|
|
'argon2d',
|
|
{ message: '1234567890', nonce: 'saltsalt', parallelism: 2, memory: 65536 },
|
|
'5ca0ab135de1241454840172696c301c7b8fd99a788cd11cf9699044cadf7fca' +
|
|
'0a6e3762cb3043a71adf6553db3fd7925101b0ccf8868b098492a4addb2486bc',
|
|
],
|
|
[
|
|
'argon2i',
|
|
{ parallelism: 4, tagLength: 32, memory: 32 },
|
|
'a9a7510e6db4d588ba3414cd0e094d480d683f97b9ccb612a544fe8ef65ba8e0',
|
|
],
|
|
[
|
|
'argon2id',
|
|
{ parallelism: 4, tagLength: 32, memory: 32 },
|
|
'03aab965c12001c9d7d0d2de33192c0494b684bb148196d73c1df1acaf6d0c2e',
|
|
],
|
|
[
|
|
'argon2d',
|
|
{ message: '1234567890', nonce: 'saltsalt', parallelism: 2, tagLength: 128, memory: 65536 },
|
|
'a86c83a19f0b234ecba8c275d16d059153f961e4c39ec9b1be98b3e73d791789' +
|
|
'363682443ad594334048634e91c493affed0bc29fd329a0e553c00149d6db19a' +
|
|
'f4e4a354aec14dbd575d78ba87d4a4bc4746666e7a4e6ee1572bbffc2eba308a' +
|
|
'2d825cb7b41fde3a95d5cff0dfa2d0fdd636b32aea8b4a3c532742d330bd1b90',
|
|
],
|
|
];
|
|
|
|
// Test vectors that should fail.
|
|
const bad = [
|
|
['argon2id', { nonce: nonce.subarray(0, 7) }, 'parameters.nonce.byteLength'], // nonce.byteLength < 8
|
|
['argon2id', { tagLength: 3 }, 'parameters.tagLength'], // tagLength < 4
|
|
['argon2id', { tagLength: 2 ** 32 }, 'parameters.tagLength'], // tagLength > 2^(32)-1
|
|
['argon2id', { passes: 0 }, 'parameters.passes'], // passes < 2
|
|
['argon2id', { passes: 2 ** 32 }, 'parameters.passes'], // passes > 2^(32)-1
|
|
['argon2id', { parallelism: 0 }, 'parameters.parallelism'], // parallelism < 1
|
|
['argon2id', { parallelism: 2 ** 24 }, 'parameters.parallelism'], // Parallelism > 2^(24)-1
|
|
['argon2id', { parallelism: 4, memory: 16 }, 'parameters.memory'], // Memory < 8 * parallelism
|
|
['argon2id', { memory: 2 ** 32 }, 'parameters.memory'], // memory > 2^(32)-1
|
|
];
|
|
|
|
for (const [algorithm, overrides, expected] of good) {
|
|
const parameters = { ...defaults, ...overrides };
|
|
const actual = runArgon2(algorithm, parameters);
|
|
assert.strictEqual(actual.toString('hex'), expected);
|
|
}
|
|
|
|
for (const [algorithm, overrides, param] of bad) {
|
|
const expected = {
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: new RegExp(`The value of "${param}" is out of range`),
|
|
};
|
|
const parameters = { ...defaults, ...overrides };
|
|
assert.throws(() => crypto.argon2(algorithm, parameters, () => {}), expected);
|
|
assert.throws(() => crypto.argon2Sync(algorithm, parameters), expected);
|
|
}
|
|
|
|
for (const key of Object.keys(defaults)) {
|
|
const expected = {
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message: new RegExp(`"parameters\\.${key}"`),
|
|
};
|
|
const parameters = { ...defaults };
|
|
delete parameters[key];
|
|
assert.throws(() => crypto.argon2('argon2id', parameters, () => {}), expected);
|
|
assert.throws(() => crypto.argon2Sync('argon2id', parameters), expected);
|
|
}
|
|
|
|
{
|
|
const expected = { code: 'ERR_INVALID_ARG_TYPE' };
|
|
assert.throws(() => crypto.argon2(), expected);
|
|
assert.throws(() => crypto.argon2('argon2id', null), expected);
|
|
assert.throws(() => crypto.argon2('argon2id', defaults, null), expected);
|
|
assert.throws(() => crypto.argon2('argon2id', defaults, {}), expected);
|
|
}
|