11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ciconst common = require('../common'); 31cb0ef41Sopenharmony_ciif (!common.hasCrypto) 41cb0ef41Sopenharmony_ci common.skip('missing crypto'); 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_ciconst assert = require('assert'); 71cb0ef41Sopenharmony_ciconst crypto = require('crypto'); 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_cifunction runPBKDF2(password, salt, iterations, keylen, hash) { 101cb0ef41Sopenharmony_ci const syncResult = 111cb0ef41Sopenharmony_ci crypto.pbkdf2Sync(password, salt, iterations, keylen, hash); 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ci crypto.pbkdf2(password, salt, iterations, keylen, hash, 141cb0ef41Sopenharmony_ci common.mustSucceed((asyncResult) => { 151cb0ef41Sopenharmony_ci assert.deepStrictEqual(asyncResult, syncResult); 161cb0ef41Sopenharmony_ci })); 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci return syncResult; 191cb0ef41Sopenharmony_ci} 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_cifunction testPBKDF2(password, salt, iterations, keylen, expected, encoding) { 221cb0ef41Sopenharmony_ci const actual = runPBKDF2(password, salt, iterations, keylen, 'sha256'); 231cb0ef41Sopenharmony_ci assert.strictEqual(actual.toString(encoding || 'latin1'), expected); 241cb0ef41Sopenharmony_ci} 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ci// 271cb0ef41Sopenharmony_ci// Test PBKDF2 with RFC 6070 test vectors (except #4) 281cb0ef41Sopenharmony_ci// 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_citestPBKDF2('password', 'salt', 1, 20, 311cb0ef41Sopenharmony_ci '\x12\x0f\xb6\xcf\xfc\xf8\xb3\x2c\x43\xe7\x22\x52' + 321cb0ef41Sopenharmony_ci '\x56\xc4\xf8\x37\xa8\x65\x48\xc9'); 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_citestPBKDF2('password', 'salt', 2, 20, 351cb0ef41Sopenharmony_ci '\xae\x4d\x0c\x95\xaf\x6b\x46\xd3\x2d\x0a\xdf\xf9' + 361cb0ef41Sopenharmony_ci '\x28\xf0\x6d\xd0\x2a\x30\x3f\x8e'); 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_citestPBKDF2('password', 'salt', 4096, 20, 391cb0ef41Sopenharmony_ci '\xc5\xe4\x78\xd5\x92\x88\xc8\x41\xaa\x53\x0d\xb6' + 401cb0ef41Sopenharmony_ci '\x84\x5c\x4c\x8d\x96\x28\x93\xa0'); 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_citestPBKDF2('passwordPASSWORDpassword', 431cb0ef41Sopenharmony_ci 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 441cb0ef41Sopenharmony_ci 4096, 451cb0ef41Sopenharmony_ci 25, 461cb0ef41Sopenharmony_ci '\x34\x8c\x89\xdb\xcb\xd3\x2b\x2f\x32\xd8\x14\xb8\x11' + 471cb0ef41Sopenharmony_ci '\x6e\x84\xcf\x2b\x17\x34\x7e\xbc\x18\x00\x18\x1c'); 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_citestPBKDF2('pass\0word', 'sa\0lt', 4096, 16, 501cb0ef41Sopenharmony_ci '\x89\xb6\x9d\x05\x16\xf8\x29\x89\x3c\x69\x62\x26\x65' + 511cb0ef41Sopenharmony_ci '\x0a\x86\x87'); 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_citestPBKDF2('password', 'salt', 32, 32, 541cb0ef41Sopenharmony_ci '64c486c55d30d4c5a079b8823b7d7cb37ff0556f537da8410233bcec330ed956', 551cb0ef41Sopenharmony_ci 'hex'); 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci// Error path should not leak memory (check with valgrind). 581cb0ef41Sopenharmony_ciassert.throws( 591cb0ef41Sopenharmony_ci () => crypto.pbkdf2('password', 'salt', 1, 20, 'sha1'), 601cb0ef41Sopenharmony_ci { 611cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 621cb0ef41Sopenharmony_ci name: 'TypeError' 631cb0ef41Sopenharmony_ci } 641cb0ef41Sopenharmony_ci); 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_cifor (const iterations of [-1, 0, 2147483648]) { 671cb0ef41Sopenharmony_ci assert.throws( 681cb0ef41Sopenharmony_ci () => crypto.pbkdf2Sync('password', 'salt', iterations, 20, 'sha1'), 691cb0ef41Sopenharmony_ci { 701cb0ef41Sopenharmony_ci code: 'ERR_OUT_OF_RANGE', 711cb0ef41Sopenharmony_ci name: 'RangeError', 721cb0ef41Sopenharmony_ci } 731cb0ef41Sopenharmony_ci ); 741cb0ef41Sopenharmony_ci} 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci['str', null, undefined, [], {}].forEach((notNumber) => { 771cb0ef41Sopenharmony_ci assert.throws( 781cb0ef41Sopenharmony_ci () => { 791cb0ef41Sopenharmony_ci crypto.pbkdf2Sync('password', 'salt', 1, notNumber, 'sha256'); 801cb0ef41Sopenharmony_ci }, { 811cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 821cb0ef41Sopenharmony_ci name: 'TypeError', 831cb0ef41Sopenharmony_ci message: 'The "keylen" argument must be of type number.' + 841cb0ef41Sopenharmony_ci `${common.invalidArgTypeHelper(notNumber)}` 851cb0ef41Sopenharmony_ci }); 861cb0ef41Sopenharmony_ci}); 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci[Infinity, -Infinity, NaN].forEach((input) => { 891cb0ef41Sopenharmony_ci assert.throws( 901cb0ef41Sopenharmony_ci () => { 911cb0ef41Sopenharmony_ci crypto.pbkdf2('password', 'salt', 1, input, 'sha256', 921cb0ef41Sopenharmony_ci common.mustNotCall()); 931cb0ef41Sopenharmony_ci }, { 941cb0ef41Sopenharmony_ci code: 'ERR_OUT_OF_RANGE', 951cb0ef41Sopenharmony_ci name: 'RangeError', 961cb0ef41Sopenharmony_ci message: 'The value of "keylen" is out of range. It ' + 971cb0ef41Sopenharmony_ci `must be an integer. Received ${input}` 981cb0ef41Sopenharmony_ci }); 991cb0ef41Sopenharmony_ci}); 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci[-1, 2147483648, 4294967296].forEach((input) => { 1021cb0ef41Sopenharmony_ci assert.throws( 1031cb0ef41Sopenharmony_ci () => { 1041cb0ef41Sopenharmony_ci crypto.pbkdf2('password', 'salt', 1, input, 'sha256', 1051cb0ef41Sopenharmony_ci common.mustNotCall()); 1061cb0ef41Sopenharmony_ci }, { 1071cb0ef41Sopenharmony_ci code: 'ERR_OUT_OF_RANGE', 1081cb0ef41Sopenharmony_ci name: 'RangeError', 1091cb0ef41Sopenharmony_ci }); 1101cb0ef41Sopenharmony_ci}); 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci// Should not get FATAL ERROR with empty password and salt 1131cb0ef41Sopenharmony_ci// https://github.com/nodejs/node/issues/8571 1141cb0ef41Sopenharmony_cicrypto.pbkdf2('', '', 1, 32, 'sha256', common.mustSucceed()); 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ciassert.throws( 1171cb0ef41Sopenharmony_ci () => crypto.pbkdf2('password', 'salt', 8, 8, common.mustNotCall()), 1181cb0ef41Sopenharmony_ci { 1191cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1201cb0ef41Sopenharmony_ci name: 'TypeError', 1211cb0ef41Sopenharmony_ci message: 'The "digest" argument must be of type string. ' + 1221cb0ef41Sopenharmony_ci 'Received undefined' 1231cb0ef41Sopenharmony_ci }); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ciassert.throws( 1261cb0ef41Sopenharmony_ci () => crypto.pbkdf2Sync('password', 'salt', 8, 8), 1271cb0ef41Sopenharmony_ci { 1281cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1291cb0ef41Sopenharmony_ci name: 'TypeError', 1301cb0ef41Sopenharmony_ci message: 'The "digest" argument must be of type string. ' + 1311cb0ef41Sopenharmony_ci 'Received undefined' 1321cb0ef41Sopenharmony_ci }); 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ciassert.throws( 1351cb0ef41Sopenharmony_ci () => crypto.pbkdf2Sync('password', 'salt', 8, 8, null), 1361cb0ef41Sopenharmony_ci { 1371cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1381cb0ef41Sopenharmony_ci name: 'TypeError', 1391cb0ef41Sopenharmony_ci message: 'The "digest" argument must be of type string. ' + 1401cb0ef41Sopenharmony_ci 'Received null' 1411cb0ef41Sopenharmony_ci }); 1421cb0ef41Sopenharmony_ci[1, {}, [], true, undefined, null].forEach((input) => { 1431cb0ef41Sopenharmony_ci assert.throws( 1441cb0ef41Sopenharmony_ci () => crypto.pbkdf2(input, 'salt', 8, 8, 'sha256', common.mustNotCall()), 1451cb0ef41Sopenharmony_ci { 1461cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1471cb0ef41Sopenharmony_ci name: 'TypeError', 1481cb0ef41Sopenharmony_ci } 1491cb0ef41Sopenharmony_ci ); 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci assert.throws( 1521cb0ef41Sopenharmony_ci () => crypto.pbkdf2('pass', input, 8, 8, 'sha256', common.mustNotCall()), 1531cb0ef41Sopenharmony_ci { 1541cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1551cb0ef41Sopenharmony_ci name: 'TypeError', 1561cb0ef41Sopenharmony_ci } 1571cb0ef41Sopenharmony_ci ); 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci assert.throws( 1601cb0ef41Sopenharmony_ci () => crypto.pbkdf2Sync(input, 'salt', 8, 8, 'sha256'), 1611cb0ef41Sopenharmony_ci { 1621cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1631cb0ef41Sopenharmony_ci name: 'TypeError', 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci ); 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ci assert.throws( 1681cb0ef41Sopenharmony_ci () => crypto.pbkdf2Sync('pass', input, 8, 8, 'sha256'), 1691cb0ef41Sopenharmony_ci { 1701cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1711cb0ef41Sopenharmony_ci name: 'TypeError', 1721cb0ef41Sopenharmony_ci } 1731cb0ef41Sopenharmony_ci ); 1741cb0ef41Sopenharmony_ci}); 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci['test', {}, [], true, undefined, null].forEach((i) => { 1771cb0ef41Sopenharmony_ci const received = common.invalidArgTypeHelper(i); 1781cb0ef41Sopenharmony_ci assert.throws( 1791cb0ef41Sopenharmony_ci () => crypto.pbkdf2('pass', 'salt', i, 8, 'sha256', common.mustNotCall()), 1801cb0ef41Sopenharmony_ci { 1811cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1821cb0ef41Sopenharmony_ci name: 'TypeError', 1831cb0ef41Sopenharmony_ci message: `The "iterations" argument must be of type number.${received}` 1841cb0ef41Sopenharmony_ci } 1851cb0ef41Sopenharmony_ci ); 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci assert.throws( 1881cb0ef41Sopenharmony_ci () => crypto.pbkdf2Sync('pass', 'salt', i, 8, 'sha256'), 1891cb0ef41Sopenharmony_ci { 1901cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1911cb0ef41Sopenharmony_ci name: 'TypeError', 1921cb0ef41Sopenharmony_ci message: `The "iterations" argument must be of type number.${received}` 1931cb0ef41Sopenharmony_ci } 1941cb0ef41Sopenharmony_ci ); 1951cb0ef41Sopenharmony_ci}); 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci// Any TypedArray should work for password and salt. 1981cb0ef41Sopenharmony_cifor (const SomeArray of [Uint8Array, Uint16Array, Uint32Array, Float32Array, 1991cb0ef41Sopenharmony_ci Float64Array, ArrayBuffer, SharedArrayBuffer]) { 2001cb0ef41Sopenharmony_ci runPBKDF2(new SomeArray(10), 'salt', 8, 8, 'sha256'); 2011cb0ef41Sopenharmony_ci runPBKDF2('pass', new SomeArray(10), 8, 8, 'sha256'); 2021cb0ef41Sopenharmony_ci} 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ciassert.throws( 2051cb0ef41Sopenharmony_ci () => crypto.pbkdf2('pass', 'salt', 8, 8, 'md55', common.mustNotCall()), 2061cb0ef41Sopenharmony_ci { 2071cb0ef41Sopenharmony_ci code: 'ERR_CRYPTO_INVALID_DIGEST', 2081cb0ef41Sopenharmony_ci name: 'TypeError', 2091cb0ef41Sopenharmony_ci message: 'Invalid digest: md55' 2101cb0ef41Sopenharmony_ci } 2111cb0ef41Sopenharmony_ci); 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_ciassert.throws( 2141cb0ef41Sopenharmony_ci () => crypto.pbkdf2Sync('pass', 'salt', 8, 8, 'md55'), 2151cb0ef41Sopenharmony_ci { 2161cb0ef41Sopenharmony_ci code: 'ERR_CRYPTO_INVALID_DIGEST', 2171cb0ef41Sopenharmony_ci name: 'TypeError', 2181cb0ef41Sopenharmony_ci message: 'Invalid digest: md55' 2191cb0ef41Sopenharmony_ci } 2201cb0ef41Sopenharmony_ci); 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ciif (!common.hasOpenSSL3) { 2231cb0ef41Sopenharmony_ci const kNotPBKDF2Supported = ['shake128', 'shake256']; 2241cb0ef41Sopenharmony_ci crypto.getHashes() 2251cb0ef41Sopenharmony_ci .filter((hash) => !kNotPBKDF2Supported.includes(hash)) 2261cb0ef41Sopenharmony_ci .forEach((hash) => { 2271cb0ef41Sopenharmony_ci runPBKDF2(new Uint8Array(10), 'salt', 8, 8, hash); 2281cb0ef41Sopenharmony_ci }); 2291cb0ef41Sopenharmony_ci} 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci{ 2321cb0ef41Sopenharmony_ci // This should not crash. 2331cb0ef41Sopenharmony_ci assert.throws( 2341cb0ef41Sopenharmony_ci () => crypto.pbkdf2Sync('1', '2', 1, 1, '%'), 2351cb0ef41Sopenharmony_ci { 2361cb0ef41Sopenharmony_ci code: 'ERR_CRYPTO_INVALID_DIGEST', 2371cb0ef41Sopenharmony_ci name: 'TypeError', 2381cb0ef41Sopenharmony_ci message: 'Invalid digest: %' 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci ); 2411cb0ef41Sopenharmony_ci} 242