init project

This commit is contained in:
root
2026-07-31 13:12:54 -04:00
parent 0da92d5e02
commit f3863f760c
7215 changed files with 1860260 additions and 1 deletions
+44
View File
@@ -0,0 +1,44 @@
import { toSPKI as exportPublic, toPKCS8 as exportPrivate } from '../lib/asn1.js';
import { invalidKeyInput } from '../lib/invalid_key_input.js';
import { encode as b64u } from '../util/base64url.js';
import { isCryptoKey, isKeyObject } from '../lib/is_key_like.js';
function omitUndefinedProperties(jwk) {
return Object.fromEntries(Object.entries(jwk).filter(([, value]) => value !== undefined));
}
async function keyToJWK(key) {
if (isKeyObject(key)) {
if (key.type === 'secret') {
key = key.export();
}
else {
return key.export({ format: 'jwk' });
}
}
if (key instanceof Uint8Array) {
return {
kty: 'oct',
k: b64u(key),
};
}
if (!isCryptoKey(key)) {
throw new TypeError(invalidKeyInput(key, 'CryptoKey', 'KeyObject', 'Uint8Array'));
}
if (!key.extractable) {
throw new TypeError('non-extractable CryptoKey cannot be exported as a JWK');
}
const { ext, key_ops, alg, use, ...jwk } = omitUndefinedProperties(await crypto.subtle.exportKey('jwk', key));
if (jwk.kty === 'AKP') {
;
jwk.alg = alg;
}
return jwk;
}
export async function exportSPKI(key) {
return exportPublic(key);
}
export async function exportPKCS8(key) {
return exportPrivate(key);
}
export async function exportJWK(key) {
return keyToJWK(key);
}
+47
View File
@@ -0,0 +1,47 @@
import { JOSENotSupported } from '../util/errors.js';
import { keyAlgorithm } from '../lib/key_algorithm.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) {
const entry = keyAlgorithm(alg);
if (entry.symmetric) {
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
}
let algorithm;
if (entry.subtleFor) {
switch (options?.crv ?? 'P-256') {
case 'P-256':
case 'P-384':
case 'P-521':
algorithm = { name: 'ECDH', namedCurve: options?.crv ?? 'P-256' };
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, options?.extractable ?? false, [
...entry.usages.private,
...entry.usages.public,
]);
}
+40
View File
@@ -0,0 +1,40 @@
import { JOSENotSupported } from '../util/errors.js';
export async function generateSecret(alg, options) {
let length;
let algorithm;
let keyUsages;
switch (alg) {
case 'HS256':
case 'HS384':
case 'HS512':
length = parseInt(alg.slice(-3), 10);
algorithm = { name: 'HMAC', hash: `SHA-${length}`, length };
keyUsages = ['sign', 'verify'];
break;
case 'A128CBC-HS256':
case 'A192CBC-HS384':
case 'A256CBC-HS512':
length = parseInt(alg.slice(-3), 10);
return crypto.getRandomValues(new Uint8Array(length >> 3));
case 'A128KW':
case 'A192KW':
case 'A256KW':
length = parseInt(alg.slice(1, 4), 10);
algorithm = { name: 'AES-KW', length };
keyUsages = ['wrapKey', 'unwrapKey'];
break;
case 'A128GCMKW':
case 'A192GCMKW':
case 'A256GCMKW':
case 'A128GCM':
case 'A192GCM':
case 'A256GCM':
length = parseInt(alg.slice(1, 4), 10);
algorithm = { name: 'AES-GCM', length };
keyUsages = ['encrypt', 'decrypt'];
break;
default:
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
}
return crypto.subtle.generateKey(algorithm, options?.extractable ?? false, keyUsages);
}
+57
View File
@@ -0,0 +1,57 @@
import { decode as decodeBase64URL } from '../util/base64url.js';
import { fromSPKI, fromPKCS8, fromX509 } from '../lib/asn1.js';
import { jwkToKey } from '../lib/jwk_to_key.js';
import { keyAlgorithm } from '../lib/key_algorithm.js';
import { JOSENotSupported } from '../util/errors.js';
import { isObject } from '../lib/type_checks.js';
export async function importSPKI(spki, alg, options) {
if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) {
throw new TypeError('"spki" must be SPKI formatted string');
}
return fromSPKI(spki, alg, options);
}
export async function importX509(x509, alg, options) {
if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) {
throw new TypeError('"x509" must be X.509 formatted string');
}
return fromX509(x509, alg, options);
}
export async function importPKCS8(pkcs8, alg, options) {
if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) {
throw new TypeError('"pkcs8" must be PKCS#8 formatted string');
}
return fromPKCS8(pkcs8, alg, options);
}
export async function importJWK(jwk, alg, options) {
if (!isObject(jwk)) {
throw new TypeError('JWK must be an object');
}
alg ??= jwk.alg;
const ext = options?.extractable ?? jwk.ext;
if (jwk.kty !== 'oct' && !alg) {
throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
}
switch (jwk.kty) {
case 'oct':
if (typeof jwk.k !== 'string' || !jwk.k) {
throw new TypeError('missing "k" (Key Value) Parameter value');
}
return decodeBase64URL(jwk.k);
case 'RSA':
return jwkToKey(keyAlgorithm(alg), { ...jwk, alg, ext });
case 'AKP': {
if (typeof jwk.alg !== 'string' || !jwk.alg) {
throw new TypeError('missing "alg" (Algorithm) Parameter value');
}
if (alg !== undefined && alg !== jwk.alg) {
throw new TypeError('JWK alg and alg option value mismatch');
}
return jwkToKey(keyAlgorithm(jwk.alg), { ...jwk, ext });
}
case 'EC':
case 'OKP':
return jwkToKey(keyAlgorithm(alg), { ...jwk, alg, ext });
default:
throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value');
}
}