Skip to content

Commit

Permalink
crypto: remove Node.js-specific webcrypto extensions
Browse files Browse the repository at this point in the history
PR-URL: #43310
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
panva authored and danielleadams committed Jun 13, 2022
1 parent cc3505b commit 6d00533
Show file tree
Hide file tree
Showing 25 changed files with 40 additions and 1,901 deletions.
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

0 comments on commit 6d00533

Please sign in to comment.