Skip to content
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
4 changes: 1 addition & 3 deletions lib/internal/crypto/aes.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,7 @@ function aesImportKey(
break;
}
default:
throw lazyDOMException(
`Unable to import AES key with format ${format}`,
'NotSupportedError');
return undefined;
}

if (length === undefined) {
Expand Down
2 changes: 2 additions & 0 deletions lib/internal/crypto/cfrg.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ function cfrgImportKey(
keyObject = createCFRGRawKey(name, keyData, true);
break;
}
default:
return undefined;
}

if (keyObject.asymmetricKeyType !== name.toLowerCase()) {
Expand Down
2 changes: 2 additions & 0 deletions lib/internal/crypto/ec.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ function ecImportKey(
keyObject = createECPublicKeyRaw(namedCurve, keyData);
break;
}
default:
return undefined;
}

switch (algorithm.name) {
Expand Down
10 changes: 3 additions & 7 deletions lib/internal/crypto/keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -922,15 +922,11 @@ function importGenericSecretKey(
keyObject = createSecretKey(keyData);
break;
}
default:
return undefined;
}

if (keyObject) {
return new InternalCryptoKey(keyObject, { name }, keyUsages, false);
}

throw lazyDOMException(
`Unable to import ${name} key with format ${format}`,
'NotSupportedError');
return new InternalCryptoKey(keyObject, { name }, keyUsages, false);
}

module.exports = {
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/crypto/mac.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ function hmacImportKey(
break;
}
default:
throw lazyDOMException(`Unable to import HMAC key with format ${format}`);
return undefined;
}

const { length } = keyObject[kHandle].keyDetail({});
Expand Down
4 changes: 1 addition & 3 deletions lib/internal/crypto/rsa.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,9 +305,7 @@ function rsaImportKey(
break;
}
default:
throw lazyDOMException(
`Unable to import RSA key with format ${format}`,
'NotSupportedError');
return undefined;
}

if (keyObject.asymmetricKeyType !== 'rsa') {
Expand Down
16 changes: 16 additions & 0 deletions lib/internal/crypto/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,20 @@ const kSupportedAlgorithms = {
'Ed25519': null,
'X25519': null,
},
'exportKey': {
'RSASSA-PKCS1-v1_5': null,
'RSA-PSS': null,
'RSA-OAEP': null,
'ECDSA': null,
'ECDH': null,
'HMAC': null,
'AES-CTR': null,
'AES-CBC': null,
'AES-GCM': null,
'AES-KW': null,
'Ed25519': null,
'X25519': null,
},
'sign': {
'RSASSA-PKCS1-v1_5': null,
'RSA-PSS': 'RsaPssParams',
Expand Down Expand Up @@ -259,12 +273,14 @@ const experimentalAlgorithms = ObjectEntries({
generateKey: null,
importKey: null,
deriveBits: 'EcdhKeyDeriveParams',
exportKey: null,
},
'Ed448': {
generateKey: null,
sign: 'Ed448Params',
verify: 'Ed448Params',
importKey: null,
exportKey: null,
},
});

Expand Down
182 changes: 99 additions & 83 deletions lib/internal/crypto/webcrypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,36 +322,25 @@ async function exportKeySpki(key) {
case 'RSA-PSS':
// Fall through
case 'RSA-OAEP':
if (key.type === 'public') {
return require('internal/crypto/rsa')
.rsaExportKey(key, kWebCryptoKeyFormatSPKI);
}
break;
return require('internal/crypto/rsa')
.rsaExportKey(key, kWebCryptoKeyFormatSPKI);
case 'ECDSA':
// Fall through
case 'ECDH':
if (key.type === 'public') {
return require('internal/crypto/ec')
.ecExportKey(key, kWebCryptoKeyFormatSPKI);
}
break;
return require('internal/crypto/ec')
.ecExportKey(key, kWebCryptoKeyFormatSPKI);
case 'Ed25519':
// Fall through
case 'Ed448':
// Fall through
case 'X25519':
// Fall through
case 'X448':
if (key.type === 'public') {
return require('internal/crypto/cfrg')
.cfrgExportKey(key, kWebCryptoKeyFormatSPKI);
}
break;
return require('internal/crypto/cfrg')
.cfrgExportKey(key, kWebCryptoKeyFormatSPKI);
default:
return undefined;
}

throw lazyDOMException(
`Unable to export a raw ${key.algorithm.name} ${key.type} key`,
'InvalidAccessError');
}

async function exportKeyPkcs8(key) {
Expand All @@ -361,60 +350,50 @@ async function exportKeyPkcs8(key) {
case 'RSA-PSS':
// Fall through
case 'RSA-OAEP':
if (key.type === 'private') {
return require('internal/crypto/rsa')
.rsaExportKey(key, kWebCryptoKeyFormatPKCS8);
}
break;
return require('internal/crypto/rsa')
.rsaExportKey(key, kWebCryptoKeyFormatPKCS8);
case 'ECDSA':
// Fall through
case 'ECDH':
if (key.type === 'private') {
return require('internal/crypto/ec')
.ecExportKey(key, kWebCryptoKeyFormatPKCS8);
}
break;
return require('internal/crypto/ec')
.ecExportKey(key, kWebCryptoKeyFormatPKCS8);
case 'Ed25519':
// Fall through
case 'Ed448':
// Fall through
case 'X25519':
// Fall through
case 'X448':
if (key.type === 'private') {
return require('internal/crypto/cfrg')
.cfrgExportKey(key, kWebCryptoKeyFormatPKCS8);
}
break;
return require('internal/crypto/cfrg')
.cfrgExportKey(key, kWebCryptoKeyFormatPKCS8);
default:
return undefined;
}

throw lazyDOMException(
`Unable to export a pkcs8 ${key.algorithm.name} ${key.type} key`,
'InvalidAccessError');
}

async function exportKeyRaw(key) {
async function exportKeyRawPublic(key) {
switch (key.algorithm.name) {
case 'ECDSA':
// Fall through
case 'ECDH':
if (key.type === 'public') {
return require('internal/crypto/ec')
.ecExportKey(key, kWebCryptoKeyFormatRaw);
}
break;
return require('internal/crypto/ec')
.ecExportKey(key, kWebCryptoKeyFormatRaw);
case 'Ed25519':
// Fall through
case 'Ed448':
// Fall through
case 'X25519':
// Fall through
case 'X448':
if (key.type === 'public') {
return require('internal/crypto/cfrg')
.cfrgExportKey(key, kWebCryptoKeyFormatRaw);
}
break;
return require('internal/crypto/cfrg')
.cfrgExportKey(key, kWebCryptoKeyFormatRaw);
default:
return undefined;
}
}

async function exportKeyRawSecret(key) {
switch (key.algorithm.name) {
case 'AES-CTR':
// Fall through
case 'AES-CBC':
Expand All @@ -424,71 +403,66 @@ async function exportKeyRaw(key) {
case 'AES-KW':
// Fall through
case 'HMAC':
return key[kKeyObject].export().buffer;
return key[kKeyObject][kHandle].export().buffer;
default:
return undefined;
}

throw lazyDOMException(
`Unable to export a raw ${key.algorithm.name} ${key.type} key`,
'InvalidAccessError');
}

async function exportKeyJWK(key) {
const jwk = key[kKeyObject][kHandle].exportJwk({
const parameters = {
key_ops: key.usages,
ext: key.extractable,
}, true);
};
switch (key.algorithm.name) {
case 'RSASSA-PKCS1-v1_5':
jwk.alg = normalizeHashName(
parameters.alg = normalizeHashName(
key.algorithm.hash.name,
normalizeHashName.kContextJwkRsa);
return jwk;
break;
case 'RSA-PSS':
jwk.alg = normalizeHashName(
parameters.alg = normalizeHashName(
key.algorithm.hash.name,
normalizeHashName.kContextJwkRsaPss);
return jwk;
break;
case 'RSA-OAEP':
jwk.alg = normalizeHashName(
parameters.alg = normalizeHashName(
key.algorithm.hash.name,
normalizeHashName.kContextJwkRsaOaep);
return jwk;
break;
case 'ECDSA':
// Fall through
case 'ECDH':
jwk.crv ||= key.algorithm.namedCurve;
return jwk;
// Fall through
case 'X25519':
// Fall through
case 'X448':
jwk.crv ||= key.algorithm.name;
return jwk;
break;
case 'Ed25519':
// Fall through
case 'Ed448':
jwk.crv ||= key.algorithm.name;
jwk.alg = key.algorithm.name;
return jwk;
parameters.alg = key.algorithm.name;
break;
case 'AES-CTR':
// Fall through
case 'AES-CBC':
// Fall through
case 'AES-GCM':
// Fall through
case 'AES-KW':
jwk.alg = require('internal/crypto/aes')
parameters.alg = require('internal/crypto/aes')
.getAlgorithmName(key.algorithm.name, key.algorithm.length);
return jwk;
break;
case 'HMAC':
jwk.alg = normalizeHashName(
parameters.alg = normalizeHashName(
key.algorithm.hash.name,
normalizeHashName.kContextJwkHmac);
return jwk;
break;
default:
// Fall through
return undefined;
}

throw lazyDOMException('Not yet supported', 'NotSupportedError');
return key[kKeyObject][kHandle].exportJwk(parameters, true);
}

async function exportKey(format, key) {
Expand All @@ -506,17 +480,55 @@ async function exportKey(format, key) {
context: '2nd argument',
});

try {
normalizeAlgorithm(key.algorithm, 'exportKey');
} catch {
throw lazyDOMException(
`${key.algorithm.name} key export is not supported`, 'NotSupportedError');
}

if (!key.extractable)
throw lazyDOMException('key is not extractable', 'InvalidAccessException');

let result;
switch (format) {
case 'spki': return exportKeySpki(key);
case 'pkcs8': return exportKeyPkcs8(key);
case 'jwk': return exportKeyJWK(key);
case 'raw': return exportKeyRaw(key);
case 'spki': {
if (key.type === 'public') {
result = await exportKeySpki(key);
}
break;
}
case 'pkcs8': {
if (key.type === 'private') {
result = await exportKeyPkcs8(key);
}
break;
}
case 'jwk': {
result = await exportKeyJWK(key);
break;
}
case 'raw': {
if (key.type === 'secret') {
result = await exportKeyRawSecret(key);
break;
}

if (key.type === 'public') {
result = await exportKeyRawPublic(key);
break;
}
break;
}
}
throw lazyDOMException(
'Export format is unsupported', 'NotSupportedError');

if (!result) {
throw lazyDOMException(
`Unable to export ${key.algorithm.name} ${key.type} key using ${format} format`,
'NotSupportedError');
}

return result;
}

async function importKey(
Expand Down Expand Up @@ -603,8 +615,12 @@ async function importKey(
extractable,
keyUsages);
break;
default:
throw lazyDOMException('Unrecognized algorithm name', 'NotSupportedError');
}

if (!result) {
throw lazyDOMException(
`Unable to import ${algorithm.name} using ${format} format`,
'NotSupportedError');
}

if ((result.type === 'secret' || result.type === 'private') && result.usages.length === 0) {
Expand Down
Loading