jose
Version:
JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes
53 lines (52 loc) • 2.09 kB
JavaScript
import { JOSENotSupported } from '../util/errors.js';
import { validateExtractableOption } from '../lib/key_options.js';
import { keyAlgorithm, unsupportedAlg, algArgument } from '../lib/key_algorithm.js';
function getModulusLengthOption(options) {
const modulusLength = options?.modulusLength ?? 2048;
if (typeof modulusLength !== 'number' ||
!Number.isInteger(modulusLength) ||
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) {
const extractable = validateExtractableOption(options?.extractable);
const entry = keyAlgorithm(alg, algArgument);
if (entry.secret) {
unsupportedAlg(algArgument);
}
let algorithm;
if (entry.resolve) {
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');
}
}
else {
if (entry.crv !== undefined && options?.crv !== undefined && options.crv !== entry.crv) {
throw new JOSENotSupported(`Invalid or unsupported crv option provided, the only supported value for ${alg} is ${entry.crv}`);
}
algorithm =
entry.kty[0] === 'RSA'
? {
...entry.subtle,
publicExponent: Uint8Array.of(0x01, 0x00, 0x01),
modulusLength: getModulusLengthOption(options),
}
: entry.subtle;
}
return crypto.subtle.generateKey(algorithm, extractable ?? false, [
...entry.usages[1],
...entry.usages[0],
]);
}