jose
Version:
JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes
98 lines (97 loc) • 3.54 kB
JavaScript
import { JOSENotSupported } from '../util/errors.js';
function getModulusLengthOption(options) {
const modulusLength = options?.modulusLength ?? 2048;
if (typeof modulusLength !== 'number' || modulusLength < 2048) {
throw new JOSENotSupported('Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used');
}
return modulusLength;
}
export async function generateKeyPair(alg, options) {
let algorithm;
let keyUsages;
switch (alg) {
case 'PS256':
case 'PS384':
case 'PS512':
algorithm = {
name: 'RSA-PSS',
hash: `SHA-${alg.slice(-3)}`,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
modulusLength: getModulusLengthOption(options),
};
keyUsages = ['sign', 'verify'];
break;
case 'RS256':
case 'RS384':
case 'RS512':
algorithm = {
name: 'RSASSA-PKCS1-v1_5',
hash: `SHA-${alg.slice(-3)}`,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
modulusLength: getModulusLengthOption(options),
};
keyUsages = ['sign', 'verify'];
break;
case 'RSA-OAEP':
case 'RSA-OAEP-256':
case 'RSA-OAEP-384':
case 'RSA-OAEP-512':
algorithm = {
name: 'RSA-OAEP',
hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
modulusLength: getModulusLengthOption(options),
};
keyUsages = ['decrypt', 'unwrapKey', 'encrypt', 'wrapKey'];
break;
case 'ES256':
algorithm = { name: 'ECDSA', namedCurve: 'P-256' };
keyUsages = ['sign', 'verify'];
break;
case 'ES384':
algorithm = { name: 'ECDSA', namedCurve: 'P-384' };
keyUsages = ['sign', 'verify'];
break;
case 'ES512':
algorithm = { name: 'ECDSA', namedCurve: 'P-521' };
keyUsages = ['sign', 'verify'];
break;
case 'Ed25519':
case 'EdDSA': {
keyUsages = ['sign', 'verify'];
algorithm = { name: 'Ed25519' };
break;
}
case 'ML-DSA-44':
case 'ML-DSA-65':
case 'ML-DSA-87': {
keyUsages = ['sign', 'verify'];
algorithm = { name: alg };
break;
}
case 'ECDH-ES':
case 'ECDH-ES+A128KW':
case 'ECDH-ES+A192KW':
case 'ECDH-ES+A256KW': {
keyUsages = ['deriveBits'];
const crv = options?.crv ?? 'P-256';
switch (crv) {
case 'P-256':
case 'P-384':
case 'P-521': {
algorithm = { name: 'ECDH', namedCurve: crv };
break;
}
case 'X25519':
algorithm = { name: 'X25519' };
break;
default:
throw new JOSENotSupported('Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, and X25519');
}
break;
}
default:
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
}
return crypto.subtle.generateKey(algorithm, options?.extractable ?? false, keyUsages);
}