node/test/parallel/test-webcrypto-export-import.js
Filip Skokan 90e3e5e173
crypto: add KeyObject.prototype.toCryptoKey
PR-URL: https://github.com/nodejs/node/pull/55262
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
2024-10-06 18:09:02 +00:00

279 lines
7.1 KiB
JavaScript

'use strict';
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');
const assert = require('assert');
const { subtle } = globalThis.crypto;
{
async function test() {
const keyData = globalThis.crypto.getRandomValues(new Uint8Array(32));
await Promise.all([1, null, undefined, {}, []].map((format) =>
assert.rejects(
subtle.importKey(format, keyData, {}, false, ['wrapKey']), {
code: 'ERR_INVALID_ARG_VALUE'
})
));
await assert.rejects(
subtle.importKey('not valid', keyData, {}, false, ['wrapKey']), {
code: 'ERR_INVALID_ARG_VALUE'
});
await assert.rejects(
subtle.importKey('KeyObject', keyData, {}, false, ['wrapKey']), {
message: /'KeyObject' is not a valid enum value of type KeyFormat/,
code: 'ERR_INVALID_ARG_VALUE'
});
await assert.rejects(
subtle.importKey('raw', 1, {}, false, ['deriveBits']), {
code: 'ERR_INVALID_ARG_TYPE'
});
await assert.rejects(
subtle.importKey('raw', keyData, {
name: 'HMAC'
}, false, ['sign', 'verify']), {
code: 'ERR_MISSING_OPTION'
});
await assert.rejects(
subtle.importKey('raw', keyData, {
name: 'HMAC',
hash: 'SHA-256'
}, false, ['deriveBits']), {
name: 'SyntaxError',
message: 'Unsupported key usage for an HMAC key'
});
await assert.rejects(
subtle.importKey('raw', keyData, {
name: 'HMAC',
hash: 'SHA-256',
length: 0
}, false, ['sign', 'verify']), {
name: 'DataError',
message: 'Zero-length key is not supported'
});
await assert.rejects(
subtle.importKey('raw', keyData, {
name: 'HMAC',
hash: 'SHA-256',
length: 1
}, false, ['sign', 'verify']), {
name: 'DataError',
message: 'Invalid key length'
});
await assert.rejects(
subtle.importKey('jwk', null, {
name: 'HMAC',
hash: 'SHA-256',
}, false, ['sign', 'verify']), {
name: 'DataError',
message: 'Invalid keyData'
});
}
test().then(common.mustCall());
}
// Import/Export HMAC Secret Key
{
async function test() {
const keyData = globalThis.crypto.getRandomValues(new Uint8Array(32));
const key = await subtle.importKey(
'raw',
keyData, {
name: 'HMAC',
hash: 'SHA-256'
}, true, ['sign', 'verify']);
const raw = await subtle.exportKey('raw', key);
assert.deepStrictEqual(
Buffer.from(keyData).toString('hex'),
Buffer.from(raw).toString('hex'));
const jwk = await subtle.exportKey('jwk', key);
assert.deepStrictEqual(jwk.key_ops, ['sign', 'verify']);
assert(jwk.ext);
assert.strictEqual(jwk.kty, 'oct');
assert.deepStrictEqual(
Buffer.from(jwk.k, 'base64').toString('hex'),
Buffer.from(raw).toString('hex'));
await assert.rejects(
subtle.importKey(
'raw',
keyData,
{
name: 'HMAC',
hash: 'SHA-256'
},
true,
[/* empty usages */]),
{ name: 'SyntaxError', message: 'Usages cannot be empty when importing a secret key.' });
}
test().then(common.mustCall());
}
// Import/Export AES Secret Key
{
async function test() {
const keyData = globalThis.crypto.getRandomValues(new Uint8Array(32));
const key = await subtle.importKey(
'raw',
keyData, {
name: 'AES-CTR',
length: 256,
}, true, ['encrypt', 'decrypt']);
const raw = await subtle.exportKey('raw', key);
assert.deepStrictEqual(
Buffer.from(keyData).toString('hex'),
Buffer.from(raw).toString('hex'));
const jwk = await subtle.exportKey('jwk', key);
assert.deepStrictEqual(jwk.key_ops, ['encrypt', 'decrypt']);
assert(jwk.ext);
assert.strictEqual(jwk.kty, 'oct');
assert.deepStrictEqual(
Buffer.from(jwk.k, 'base64').toString('hex'),
Buffer.from(raw).toString('hex'));
await assert.rejects(
subtle.importKey(
'raw',
keyData,
{
name: 'AES-CTR',
length: 256,
},
true,
[/* empty usages */]),
{ name: 'SyntaxError', message: 'Usages cannot be empty when importing a secret key.' });
}
test().then(common.mustCall());
}
// Import/Export RSA Key Pairs
{
async function test() {
const { publicKey, privateKey } = await subtle.generateKey({
name: 'RSA-PSS',
modulusLength: 1024,
publicExponent: new Uint8Array([1, 0, 1]),
hash: 'SHA-384'
}, true, ['sign', 'verify']);
const [
spki,
pkcs8,
publicJwk,
privateJwk,
] = await Promise.all([
subtle.exportKey('spki', publicKey),
subtle.exportKey('pkcs8', privateKey),
subtle.exportKey('jwk', publicKey),
subtle.exportKey('jwk', privateKey),
]);
assert(spki);
assert(pkcs8);
assert(publicJwk);
assert(privateJwk);
const [
importedSpkiPublicKey,
importedPkcs8PrivateKey,
importedJwkPublicKey,
importedJwkPrivateKey,
] = await Promise.all([
subtle.importKey('spki', spki, {
name: 'RSA-PSS',
hash: 'SHA-384',
}, true, ['verify']),
subtle.importKey('pkcs8', pkcs8, {
name: 'RSA-PSS',
hash: 'SHA-384',
}, true, ['sign']),
subtle.importKey('jwk', publicJwk, {
name: 'RSA-PSS',
hash: 'SHA-384',
}, true, ['verify']),
subtle.importKey('jwk', privateJwk, {
name: 'RSA-PSS',
hash: 'SHA-384',
}, true, ['sign']),
]);
assert(importedSpkiPublicKey);
assert(importedPkcs8PrivateKey);
assert(importedJwkPublicKey);
assert(importedJwkPrivateKey);
}
test().then(common.mustCall());
}
// Import/Export EC Key Pairs
{
async function test() {
const { publicKey, privateKey } = await subtle.generateKey({
name: 'ECDSA',
namedCurve: 'P-384'
}, true, ['sign', 'verify']);
const [
spki,
pkcs8,
publicJwk,
privateJwk,
] = await Promise.all([
subtle.exportKey('spki', publicKey),
subtle.exportKey('pkcs8', privateKey),
subtle.exportKey('jwk', publicKey),
subtle.exportKey('jwk', privateKey),
]);
assert(spki);
assert(pkcs8);
assert(publicJwk);
assert(privateJwk);
const [
importedSpkiPublicKey,
importedPkcs8PrivateKey,
importedJwkPublicKey,
importedJwkPrivateKey,
] = await Promise.all([
subtle.importKey('spki', spki, {
name: 'ECDSA',
namedCurve: 'P-384'
}, true, ['verify']),
subtle.importKey('pkcs8', pkcs8, {
name: 'ECDSA',
namedCurve: 'P-384'
}, true, ['sign']),
subtle.importKey('jwk', publicJwk, {
name: 'ECDSA',
namedCurve: 'P-384'
}, true, ['verify']),
subtle.importKey('jwk', privateJwk, {
name: 'ECDSA',
namedCurve: 'P-384'
}, true, ['sign']),
]);
assert(importedSpkiPublicKey);
assert(importedPkcs8PrivateKey);
assert(importedJwkPublicKey);
assert(importedJwkPrivateKey);
}
test().then(common.mustCall());
}