mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
Add SHA3-256, SHA3-384, and SHA3-512 to name lookup and getHashes(). BoringSSL exposes EVP_sha3_* descriptors but omits them from its digest registry. Map the names directly to those descriptors so node:crypto can use them too. When using BoringSSL, limit WebCrypto SHA-3 support to digest operations. Signed-off-by: Filip Skokan <panva.ip@gmail.com> Assisted-by: Codex PR-URL: https://github.com/nodejs/node/pull/66922 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
118 lines
4.3 KiB
JavaScript
118 lines
4.3 KiB
JavaScript
'use strict';
|
|
|
|
const common = require('../common');
|
|
if (!common.hasCrypto)
|
|
common.skip('missing crypto');
|
|
|
|
const assert = require('assert');
|
|
const {
|
|
constants,
|
|
createHash,
|
|
createHmac,
|
|
createPrivateKey,
|
|
createPublicKey,
|
|
createSign,
|
|
createVerify,
|
|
getHashes,
|
|
hash,
|
|
hkdf,
|
|
hkdfSync,
|
|
pbkdf2,
|
|
pbkdf2Sync,
|
|
sign,
|
|
verify,
|
|
} = require('crypto');
|
|
const rsaPss = require('../fixtures/crypto/rsa_pss');
|
|
|
|
const vectors = [
|
|
{
|
|
name: 'sha3-256',
|
|
digest: '3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532',
|
|
hmac: '961fcf59ed455732e405e74f5dc78beb7aa41ad315af5e2b2a0dcf8cef9887e0',
|
|
hkdf: '38c2d1e7b3933f7df51e35f3eeaa0a0138b1b812e2bf57810ad4e2300e2c4a81',
|
|
pbkdf2: 'db7d83f5e7ebc6b0ea83e9b6c57a27e254e96cfef315278e9ed96b10483a7ad0',
|
|
},
|
|
{
|
|
name: 'sha3-384',
|
|
digest: 'ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b29' +
|
|
'8d88cea927ac7f539f1edf228376d25',
|
|
hmac: 'f1d3898bb4cd7b7904fe4e7cecb84d3225b3add0265842ec7386867d662ee3364' +
|
|
'8a90e98a5c673b2266eb1077fb91ed6',
|
|
hkdf: '3ca21ccc4e742ec6a365ee5857db1ab5a0a8843196467d7a0b26c724e542f6f5',
|
|
pbkdf2: '7f049e44bfddb1b591d1ae2beaa1f3be54d683063bd25759b412a86012186c16',
|
|
},
|
|
{
|
|
name: 'sha3-512',
|
|
digest: 'b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e1' +
|
|
'0e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0',
|
|
hmac: '5576c01b021fc928ae1bc83a6ddb8db5f9a201681e940ecf1f7d5c8a6ec80ac34' +
|
|
'614d4a68c9581957f69dc8a8c0fbf413984b0f938db3e8212c0744a1a9c5915',
|
|
hkdf: 'cd54f848a5f6ffb9e730d4bfbdff30d69a4b86316afdf5ba61b4fe95bd022037',
|
|
pbkdf2: '2b5150c50e0bf48dcb5b32205ad81e8c42d97f8f8dff57dcc365a38e857a05c7',
|
|
},
|
|
];
|
|
|
|
const hashes = getHashes();
|
|
for (const vector of vectors) {
|
|
assert(hashes.includes(vector.name));
|
|
for (const name of [vector.name, vector.name.toUpperCase(),
|
|
vector.name.replace('sha', 'sHa')]) {
|
|
assert.strictEqual(hash(name, 'abc'), vector.digest);
|
|
|
|
const original = createHash(name).update('a');
|
|
const copy = original.copy();
|
|
assert.strictEqual(original.update('bc').digest('hex'), vector.digest);
|
|
assert.strictEqual(copy.update('b').copy().update('c').digest('hex'), vector.digest);
|
|
|
|
// Exceed every SHA-3 block size so HMAC also hashes the key.
|
|
assert.strictEqual(createHmac(name, Buffer.alloc(200, 0xaa))
|
|
.update('abc').digest('hex'), vector.hmac);
|
|
|
|
assert.strictEqual(Buffer.from(hkdfSync(name, 'passwordpassword', 'saltsaltsaltsalt', 'info', 32))
|
|
.toString('hex'), vector.hkdf);
|
|
hkdf(name, 'passwordpassword', 'saltsaltsaltsalt', 'info', 32, common.mustSucceed((result) => {
|
|
assert.strictEqual(Buffer.from(result).toString('hex'), vector.hkdf);
|
|
}));
|
|
|
|
assert.strictEqual(pbkdf2Sync('passwordpassword', 'saltsaltsaltsalt', 1000, 32, name)
|
|
.toString('hex'), vector.pbkdf2);
|
|
pbkdf2('passwordpassword', 'saltsaltsaltsalt', 1000, 32, name, common.mustSucceed((result) => {
|
|
assert.strictEqual(result.toString('hex'), vector.pbkdf2);
|
|
}));
|
|
}
|
|
}
|
|
|
|
// Reuse independent RSA-PSS signature vectors to check SHA-3 in both the
|
|
// one-shot and streaming APIs, including zero-length and digest-length salts.
|
|
for (const vector of rsaPss()) {
|
|
if (!vector.hash.startsWith('SHA3-')) continue;
|
|
const privateKey = createPrivateKey({
|
|
key: vector.privateKeyBuffer, format: 'der', type: 'pkcs8',
|
|
});
|
|
const publicKey = createPublicKey({
|
|
key: vector.publicKeyBuffer, format: 'der', type: 'spki',
|
|
});
|
|
const options = {
|
|
padding: constants.RSA_PKCS1_PSS_PADDING,
|
|
saltLength: vector.algorithm.saltLength,
|
|
};
|
|
const signingKey = { key: privateKey, ...options };
|
|
const verificationKey = { key: publicKey, ...options };
|
|
|
|
assert(verify(vector.hash, vector.plaintext, verificationKey,
|
|
vector.signature));
|
|
assert(createVerify(vector.hash).update(vector.plaintext)
|
|
.verify(verificationKey, vector.signature));
|
|
|
|
for (const signature of [
|
|
sign(vector.hash, vector.plaintext, signingKey),
|
|
createSign(vector.hash).update(vector.plaintext).sign(signingKey),
|
|
]) {
|
|
assert(verify(vector.hash, vector.plaintext, verificationKey, signature));
|
|
assert(createVerify(vector.hash).update(vector.plaintext)
|
|
.verify(verificationKey, signature));
|
|
if (options.saltLength === 0)
|
|
assert.deepStrictEqual(signature, vector.signature);
|
|
}
|
|
}
|