123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- function unusable(name, prop = 'algorithm.name') {
- return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
- }
- function isAlgorithm(algorithm, name) {
- return algorithm.name === name;
- }
- function getHashLength(hash) {
- return parseInt(hash.name.slice(4), 10);
- }
- function getNamedCurve(alg) {
- switch (alg) {
- case 'ES256':
- return 'P-256';
- case 'ES384':
- return 'P-384';
- case 'ES512':
- return 'P-521';
- default:
- throw new Error('unreachable');
- }
- }
- function checkUsage(key, usages) {
- if (usages.length && !usages.some((expected) => key.usages.includes(expected))) {
- let msg = 'CryptoKey does not support this operation, its usages must include ';
- if (usages.length > 2) {
- const last = usages.pop();
- msg += `one of ${usages.join(', ')}, or ${last}.`;
- }
- else if (usages.length === 2) {
- msg += `one of ${usages[0]} or ${usages[1]}.`;
- }
- else {
- msg += `${usages[0]}.`;
- }
- throw new TypeError(msg);
- }
- }
- export function checkSigCryptoKey(key, alg, ...usages) {
- switch (alg) {
- case 'HS256':
- case 'HS384':
- case 'HS512': {
- if (!isAlgorithm(key.algorithm, 'HMAC'))
- throw unusable('HMAC');
- const expected = parseInt(alg.slice(2), 10);
- const actual = getHashLength(key.algorithm.hash);
- if (actual !== expected)
- throw unusable(`SHA-${expected}`, 'algorithm.hash');
- break;
- }
- case 'RS256':
- case 'RS384':
- case 'RS512': {
- if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5'))
- throw unusable('RSASSA-PKCS1-v1_5');
- const expected = parseInt(alg.slice(2), 10);
- const actual = getHashLength(key.algorithm.hash);
- if (actual !== expected)
- throw unusable(`SHA-${expected}`, 'algorithm.hash');
- break;
- }
- case 'PS256':
- case 'PS384':
- case 'PS512': {
- if (!isAlgorithm(key.algorithm, 'RSA-PSS'))
- throw unusable('RSA-PSS');
- const expected = parseInt(alg.slice(2), 10);
- const actual = getHashLength(key.algorithm.hash);
- if (actual !== expected)
- throw unusable(`SHA-${expected}`, 'algorithm.hash');
- break;
- }
- case 'EdDSA': {
- if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') {
- throw unusable('Ed25519 or Ed448');
- }
- break;
- }
- case 'ES256':
- case 'ES384':
- case 'ES512': {
- if (!isAlgorithm(key.algorithm, 'ECDSA'))
- throw unusable('ECDSA');
- const expected = getNamedCurve(alg);
- const actual = key.algorithm.namedCurve;
- if (actual !== expected)
- throw unusable(expected, 'algorithm.namedCurve');
- break;
- }
- default:
- throw new TypeError('CryptoKey does not support this operation');
- }
- checkUsage(key, usages);
- }
- export function checkEncCryptoKey(key, alg, ...usages) {
- switch (alg) {
- case 'A128GCM':
- case 'A192GCM':
- case 'A256GCM': {
- if (!isAlgorithm(key.algorithm, 'AES-GCM'))
- throw unusable('AES-GCM');
- const expected = parseInt(alg.slice(1, 4), 10);
- const actual = key.algorithm.length;
- if (actual !== expected)
- throw unusable(expected, 'algorithm.length');
- break;
- }
- case 'A128KW':
- case 'A192KW':
- case 'A256KW': {
- if (!isAlgorithm(key.algorithm, 'AES-KW'))
- throw unusable('AES-KW');
- const expected = parseInt(alg.slice(1, 4), 10);
- const actual = key.algorithm.length;
- if (actual !== expected)
- throw unusable(expected, 'algorithm.length');
- break;
- }
- case 'ECDH': {
- switch (key.algorithm.name) {
- case 'ECDH':
- case 'X25519':
- case 'X448':
- break;
- default:
- throw unusable('ECDH, X25519, or X448');
- }
- break;
- }
- case 'PBES2-HS256+A128KW':
- case 'PBES2-HS384+A192KW':
- case 'PBES2-HS512+A256KW':
- if (!isAlgorithm(key.algorithm, 'PBKDF2'))
- throw unusable('PBKDF2');
- break;
- case 'RSA-OAEP':
- case 'RSA-OAEP-256':
- case 'RSA-OAEP-384':
- case 'RSA-OAEP-512': {
- if (!isAlgorithm(key.algorithm, 'RSA-OAEP'))
- throw unusable('RSA-OAEP');
- const expected = parseInt(alg.slice(9), 10) || 1;
- const actual = getHashLength(key.algorithm.hash);
- if (actual !== expected)
- throw unusable(`SHA-${expected}`, 'algorithm.hash');
- break;
- }
- default:
- throw new TypeError('CryptoKey does not support this operation');
- }
- checkUsage(key, usages);
- }
|