Spaces:
Sleeping
Sleeping
| const unusable = (name, prop = 'algorithm.name') => new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`); | |
| const isAlgorithm = (algorithm, name) => algorithm.name === name; | |
| function getHashLength(hash) { | |
| return parseInt(hash.name.slice(4), 10); | |
| } | |
| function checkHashLength(algorithm, expected) { | |
| const actual = getHashLength(algorithm.hash); | |
| if (actual !== expected) | |
| throw unusable(`SHA-${expected}`, 'algorithm.hash'); | |
| } | |
| 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, usage) { | |
| if (usage && !key.usages.includes(usage)) { | |
| throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`); | |
| } | |
| } | |
| export function checkSigCryptoKey(key, alg, usage) { | |
| switch (alg) { | |
| case 'HS256': | |
| case 'HS384': | |
| case 'HS512': { | |
| if (!isAlgorithm(key.algorithm, 'HMAC')) | |
| throw unusable('HMAC'); | |
| checkHashLength(key.algorithm, parseInt(alg.slice(2), 10)); | |
| break; | |
| } | |
| case 'RS256': | |
| case 'RS384': | |
| case 'RS512': { | |
| if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5')) | |
| throw unusable('RSASSA-PKCS1-v1_5'); | |
| checkHashLength(key.algorithm, parseInt(alg.slice(2), 10)); | |
| break; | |
| } | |
| case 'PS256': | |
| case 'PS384': | |
| case 'PS512': { | |
| if (!isAlgorithm(key.algorithm, 'RSA-PSS')) | |
| throw unusable('RSA-PSS'); | |
| checkHashLength(key.algorithm, parseInt(alg.slice(2), 10)); | |
| break; | |
| } | |
| case 'Ed25519': | |
| case 'EdDSA': { | |
| if (!isAlgorithm(key.algorithm, 'Ed25519')) | |
| throw unusable('Ed25519'); | |
| break; | |
| } | |
| case 'ML-DSA-44': | |
| case 'ML-DSA-65': | |
| case 'ML-DSA-87': { | |
| if (!isAlgorithm(key.algorithm, alg)) | |
| throw unusable(alg); | |
| 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, usage); | |
| } | |
| export function checkEncCryptoKey(key, alg, usage) { | |
| 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': | |
| break; | |
| default: | |
| throw unusable('ECDH or X25519'); | |
| } | |
| 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'); | |
| checkHashLength(key.algorithm, parseInt(alg.slice(9), 10) || 1); | |
| break; | |
| } | |
| default: | |
| throw new TypeError('CryptoKey does not support this operation'); | |
| } | |
| checkUsage(key, usage); | |
| } | |