Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto: remove Node.js-specific Web Crypto API extensions #43310

Merged
merged 2 commits into from
Jun 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
333 changes: 38 additions & 295 deletions doc/api/webcrypto.md

Large diffs are not rendered by default.

20 changes: 0 additions & 20 deletions lib/internal/crypto/aes.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,10 @@ const {

const { PromiseReject } = primordials;

const {
codes: {
ERR_INVALID_ARG_TYPE,
}
} = require('internal/errors');

const {
InternalCryptoKey,
SecretKeyObject,
createSecretKey,
isKeyObject,
} = require('internal/crypto/keys');

const {
Expand Down Expand Up @@ -283,19 +276,6 @@ async function aesImportKey(
let keyObject;
let length;
switch (format) {
case 'node.keyObject': {
if (!isKeyObject(keyData))
throw new ERR_INVALID_ARG_TYPE('keyData', 'KeyObject', keyData);

if (keyData.type !== 'secret') {
throw lazyDOMException(
`Unable to import AES key with format ${format}`,
'NotSupportedError');
}

keyObject = keyData;
break;
}
case 'raw': {
validateKeyLength(keyData.byteLength * 8);
keyObject = createSecretKey(keyData);
Expand Down
16 changes: 0 additions & 16 deletions lib/internal/crypto/cfrg.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@ const {
kSignJobModeVerify,
} = internalBinding('crypto');

const {
codes: {
ERR_INVALID_ARG_TYPE,
},
} = require('internal/errors');

const {
getArrayBufferOrView,
getUsagesUnion,
Expand All @@ -49,7 +43,6 @@ const {
PublicKeyObject,
createPrivateKey,
createPublicKey,
isKeyObject,
} = require('internal/crypto/keys');

function verifyAcceptableCfrgKeyUse(name, type, usages) {
Expand Down Expand Up @@ -226,15 +219,6 @@ async function cfrgImportKey(
let keyObject;
const usagesSet = new SafeSet(keyUsages);
switch (format) {
case 'node.keyObject': {
if (!isKeyObject(keyData))
throw new ERR_INVALID_ARG_TYPE('keyData', 'KeyObject', keyData);
if (keyData.type === 'secret')
throw lazyDOMException('Invalid key type', 'InvalidAccessException');
verifyAcceptableCfrgKeyUse(name, keyData.type, usagesSet);
keyObject = keyData;
break;
}
case 'spki': {
verifyAcceptableCfrgKeyUse(name, 'public', usagesSet);
keyObject = createPublicKey({
Expand Down
221 changes: 0 additions & 221 deletions lib/internal/crypto/diffiehellman.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ const {
const { Buffer } = require('buffer');

const {
DHBitsJob,
DHKeyExportJob,
DiffieHellman: _DiffieHellman,
DiffieHellmanGroup: _DiffieHellmanGroup,
ECDH: _ECDH,
Expand Down Expand Up @@ -53,23 +51,12 @@ const {

const {
KeyObject,
InternalCryptoKey,
createPrivateKey,
createPublicKey,
isCryptoKey,
isKeyObject,
} = require('internal/crypto/keys');

const {
generateKeyPair,
} = require('internal/crypto/keygen');

const {
getArrayBufferOrView,
getDefaultEncoding,
getUsagesUnion,
hasAnyNotIn,
jobPromise,
toBuf,
kHandle,
kKeyObject,
Expand Down Expand Up @@ -345,89 +332,6 @@ function deriveBitsECDH(name, publicKey, privateKey, callback) {
job.run();
}

// The deriveBitsDH function is part of the Web Crypto API and serves both
// deriveKeys and deriveBits functions.
function deriveBitsDH(publicKey, privateKey, callback) {
validateObject(publicKey, 'publicKey');
validateObject(privateKey, 'privateKey');
validateFunction(callback, 'callback');
const job = new DHBitsJob(kCryptoJobAsync, publicKey, privateKey);
job.ondone = (error, bits) => {
if (error) return FunctionPrototypeCall(callback, job, error);
FunctionPrototypeCall(callback, job, null, bits);
};
job.run();
}

function verifyAcceptableDhKeyUse(name, type, usages) {
let checkSet;
switch (type) {
case 'private':
checkSet = ['deriveBits', 'deriveKey'];
break;
case 'public':
checkSet = [];
break;
}
if (hasAnyNotIn(usages, checkSet)) {
throw lazyDOMException(
`Unsupported key usage for an ${name} key`,
'SyntaxError');
}
}

async function dhGenerateKey(
algorithm,
extractable,
keyUsages) {
const usageSet = new SafeSet(keyUsages);

if (hasAnyNotIn(usageSet, ['deriveKey', 'deriveBits'])) {
throw lazyDOMException(
'Unsupported key usage for a DH key',
'SyntaxError');
}

const {
name,
primeLength,
generator,
group
} = algorithm;
let { prime } = algorithm;

if (prime !== undefined)
prime = getArrayBufferOrView(prime);

return new Promise((resolve, reject) => {
generateKeyPair('dh', {
prime,
primeLength,
generator,
group,
}, (err, pubKey, privKey) => {
if (err) {
return reject(lazyDOMException(
'The operation failed for an operation-specific reason',
'OperationError'));
}

const algorithm = { name, prime, primeLength, generator, group };

const publicKey = new InternalCryptoKey(pubKey, algorithm, [], true);

const privateKey =
new InternalCryptoKey(
privKey,
algorithm,
getUsagesUnion(usageSet, 'deriveBits', 'deriveKey'),
extractable);

resolve({ publicKey, privateKey });
});
});
}

async function asyncDeriveBitsECDH(algorithm, baseKey, length) {
const { 'public': key } = algorithm;

Expand Down Expand Up @@ -498,136 +402,11 @@ async function asyncDeriveBitsECDH(algorithm, baseKey, length) {
ArrayBufferPrototypeSlice(bits, 0, length);
}

async function asyncDeriveBitsDH(algorithm, baseKey, length) {
const { 'public': key } = algorithm;
// Null has a specific meaning for DH
if (length !== null)
validateUint32(length, 'length');
if (!isCryptoKey(key))
throw new ERR_INVALID_ARG_TYPE('algorithm.public', 'CryptoKey', key);

if (key.type !== 'public') {
throw lazyDOMException(
'algorithm.public must be a public key', 'InvalidAccessError');
}
if (baseKey.type !== 'private') {
throw lazyDOMException(
'baseKey must be a private key', 'InvalidAccessError');
}

if (key.algorithm.name !== 'NODE-DH')
throw lazyDOMException('Keys must be DH keys', 'InvalidAccessError');

if (key.algorithm.name !== baseKey.algorithm.name) {
throw lazyDOMException(
'The public and private keys must be of the same type',
'InvalidAccessError');
}

const bits = await new Promise((resolve, reject) => {
deriveBitsDH(
key[kKeyObject][kHandle],
baseKey[kKeyObject][kHandle], (err, bits) => {
if (err) return reject(err);
resolve(bits);
});
});

// If a length is not specified, return the full derived secret
if (length === null)
return bits;

// If the length is not a multiple of 8, it will be truncated
// down to the nearest multiple of 8.
length = MathFloor(length / 8);
const { byteLength } = bits;

// If the length is larger than the derived secret, throw.
// Otherwise, we either return the secret or a truncated
// slice.
if (byteLength < length)
throw lazyDOMException('derived bit length is too small', 'OperationError');

return length === byteLength ?
bits :
ArrayBufferPrototypeSlice(bits, 0, length);
}

function dhExportKey(key, format) {
return jobPromise(new DHKeyExportJob(
kCryptoJobAsync,
format,
key[kKeyObject][kHandle]));
}

async function dhImportKey(
format,
keyData,
algorithm,
extractable,
keyUsages) {
const usagesSet = new SafeSet(keyUsages);
let keyObject;
switch (format) {
case 'node.keyObject': {
if (!isKeyObject(keyData))
throw new ERR_INVALID_ARG_TYPE('keyData', 'KeyObject', keyData);
if (keyData.type === 'secret')
throw lazyDOMException('Invalid key type', 'InvalidAccessException');
verifyAcceptableDhKeyUse(algorithm.name, keyData.type, usagesSet);
keyObject = keyData;
break;
}
case 'spki': {
verifyAcceptableDhKeyUse(algorithm.name, 'public', usagesSet);
keyObject = createPublicKey({
key: keyData,
format: 'der',
type: 'spki'
});
break;
}
case 'pkcs8': {
verifyAcceptableDhKeyUse(algorithm.name, 'private', usagesSet);
keyObject = createPrivateKey({
key: keyData,
format: 'der',
type: 'pkcs8'
});
break;
}
default:
throw lazyDOMException(
`Unable to import DH key with format ${format}`,
'NotSupportedError');
}

const {
prime,
primeLength,
generator,
group,
} = keyObject[kHandle].keyDetail({});

return new InternalCryptoKey(keyObject, {
name: algorithm.name,
prime,
primeLength,
generator,
group,
}, keyUsages, extractable);
}

module.exports = {
DiffieHellman,
DiffieHellmanGroup,
ECDH,
diffieHellman,
deriveBitsECDH,
deriveBitsDH,
dhGenerateKey,
asyncDeriveBitsECDH,
asyncDeriveBitsDH,
dhExportKey,
dhImportKey,
};
Loading