🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

jose

Package Overview
Dependencies
Maintainers
1
Versions
241
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jose - npm Package Compare versions

Comparing version
6.2.4
to
6.2.5
+143
dist/webapi/lib/jwe_algorithms.js
import { JOSENotSupported } from '../util/errors.js';
import { table } from './key_descriptor.js';
const wrap = {
public: ['encrypt', 'wrapKey'],
private: ['decrypt', 'unwrapKey'],
};
const derive = { public: [], private: ['deriveBits'] };
const none = { public: [], private: [] };
function rsaes(bits) {
return {
kty: ['RSA'],
subtle: { name: 'RSA-OAEP', hash: `SHA-${bits}` },
usages: wrap,
minModulusLength: 2048,
keyOps: { encrypt: 'wrapKey', decrypt: 'unwrapKey' },
};
}
function ecdh(kwBits) {
return {
kty: ['EC', 'OKP'],
subtle: { name: 'ECDH' },
subtleFor: ({ kty, crv, asymmetricKeyType }) => {
if (crv === 'X25519' || asymmetricKeyType === 'x25519') {
return { name: 'X25519' };
}
if (kty === 'OKP') {
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
}
return { name: 'ECDH', namedCurve: crv };
},
usages: derive,
kwBits,
keyOps: { decrypt: 'deriveBits' },
};
}
function aeskw(bits) {
return {
kty: ['oct'],
symmetric: true,
subtle: { name: 'AES-KW', length: bits },
usages: none,
keyOps: { encrypt: 'wrapKey', decrypt: 'unwrapKey' },
};
}
function aesgcmkw(bits) {
return {
kty: ['oct'],
symmetric: true,
subtle: { name: 'AES-GCM', length: bits },
usages: none,
gcmkw: `A${bits}GCM`,
keyOps: { encrypt: 'encrypt', decrypt: 'decrypt' },
};
}
function pbes2(bits, kwBits) {
return {
kty: ['oct'],
symmetric: true,
subtle: { name: 'PBKDF2' },
usages: none,
pbes2Hash: `SHA-${bits}`,
kwBits,
keyOps: { encrypt: 'deriveBits', decrypt: 'deriveBits' },
};
}
const JWE = table({
dir: {
kty: ['oct'],
symmetric: true,
subtle: { name: 'AES-GCM' },
usages: none,
keyOps: { encrypt: 'encrypt', decrypt: 'decrypt' },
},
'RSA-OAEP': rsaes(1),
'RSA-OAEP-256': rsaes(256),
'RSA-OAEP-384': rsaes(384),
'RSA-OAEP-512': rsaes(512),
'ECDH-ES': ecdh(),
'ECDH-ES+A128KW': ecdh(128),
'ECDH-ES+A192KW': ecdh(192),
'ECDH-ES+A256KW': ecdh(256),
A128KW: aeskw(128),
A192KW: aeskw(192),
A256KW: aeskw(256),
A128GCMKW: aesgcmkw(128),
A192GCMKW: aesgcmkw(192),
A256GCMKW: aesgcmkw(256),
'PBES2-HS256+A128KW': pbes2(256, 128),
'PBES2-HS384+A192KW': pbes2(384, 192),
'PBES2-HS512+A256KW': pbes2(512, 256),
});
const content = { public: [], private: [] };
const contentOps = { encrypt: 'encrypt', decrypt: 'decrypt' };
function gcm(bits) {
return {
kty: ['oct'],
symmetric: true,
subtle: { name: 'AES-GCM', length: bits },
usages: content,
keyOps: contentOps,
cekBits: bits,
ivBits: 96,
cbc: false,
};
}
function cbc(bits) {
return {
kty: ['oct'],
symmetric: true,
subtle: { name: 'AES-CBC', length: bits },
usages: content,
keyOps: contentOps,
cekBits: bits,
ivBits: 128,
cbc: true,
};
}
const ENC = table({
A128GCM: gcm(128),
A192GCM: gcm(192),
A256GCM: gcm(256),
'A128CBC-HS256': cbc(256),
'A192CBC-HS384': cbc(384),
'A256CBC-HS512': cbc(512),
});
const unsupportedAlgHeader = 'Invalid or unsupported "alg" (JWE Algorithm) header value';
export function jweAlgorithm(alg) {
const entry = JWE[alg];
if (!entry) {
throw new JOSENotSupported(unsupportedAlgHeader);
}
return entry;
}
export function maybeJWEAlgorithm(alg) {
return JWE[alg];
}
export function jweEncryption(enc) {
const entry = ENC[enc];
if (!entry) {
throw new JOSENotSupported(`Unsupported JWE Algorithm: ${enc}`);
}
return entry;
}
import { decrypt, generateCek } from './content_encryption.js';
import { decodeBase64url, encodeBase64url, parseJoseHeader } from './helpers.js';
import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../util/errors.js';
import { isDisjoint, isObject } from './type_checks.js';
import { decryptKeyManagement } from './key_management.js';
import { concat, decoder, encode } from './buffer_utils.js';
import { validateCrit, validateAlgorithms, JWE_RECOGNIZED } from './options.js';
import { prepareKey } from './key.js';
import { jweAlgorithm, jweEncryption } from './jwe_algorithms.js';
import { decompress } from './deflate.js';
export function checkShared(jwe) {
if (jwe.iv !== undefined && typeof jwe.iv !== 'string') {
throw new JWEInvalid('JWE Initialization Vector incorrect type');
}
if (typeof jwe.ciphertext !== 'string') {
throw new JWEInvalid('JWE Ciphertext missing or incorrect type');
}
if (jwe.tag !== undefined && typeof jwe.tag !== 'string') {
throw new JWEInvalid('JWE Authentication Tag incorrect type');
}
if (jwe.protected !== undefined && typeof jwe.protected !== 'string') {
throw new JWEInvalid('JWE Protected Header incorrect type');
}
if (jwe.aad !== undefined && typeof jwe.aad !== 'string') {
throw new JWEInvalid('JWE AAD incorrect type');
}
if (jwe.unprotected !== undefined && !isObject(jwe.unprotected)) {
throw new JWEInvalid('JWE Shared Unprotected Header incorrect type');
}
}
export function checkRecipient(jwe) {
if (jwe.encrypted_key !== undefined && typeof jwe.encrypted_key !== 'string') {
throw new JWEInvalid('JWE Encrypted Key incorrect type');
}
if (jwe.header !== undefined && !isObject(jwe.header)) {
throw new JWEInvalid('JWE Per-Recipient Unprotected Header incorrect type');
}
if (jwe.protected === undefined && jwe.header === undefined && jwe.unprotected === undefined) {
throw new JWEInvalid('JOSE Header missing');
}
}
export function shareJWE(jwe) {
let parsedProt;
if (jwe.protected) {
parsedProt = parseJoseHeader(jwe.protected, JWEInvalid, 'JWE Protected Header is invalid');
}
const protectedHeader = jwe.protected !== undefined ? encode(jwe.protected) : new Uint8Array();
return {
parsedProt,
ciphertext: decodeBase64url(jwe.ciphertext, 'ciphertext', JWEInvalid),
iv: jwe.iv !== undefined ? decodeBase64url(jwe.iv, 'iv', JWEInvalid) : undefined,
tag: jwe.tag !== undefined ? decodeBase64url(jwe.tag, 'tag', JWEInvalid) : undefined,
additionalData: jwe.aad !== undefined
? concat(protectedHeader, encode('.'), encodeBase64url(jwe.aad, 'aad', JWEInvalid))
: protectedHeader,
};
}
export function decryptResult(jwe, decrypted) {
const result = { plaintext: decrypted.plaintext };
if (jwe.protected !== undefined) {
result.protectedHeader = decrypted.parsedProt;
}
if (jwe.aad !== undefined) {
result.additionalAuthenticatedData = decodeBase64url(jwe.aad, 'aad', JWEInvalid);
}
if (jwe.unprotected !== undefined) {
result.sharedUnprotectedHeader = jwe.unprotected;
}
if (jwe.header !== undefined) {
result.unprotectedHeader = jwe.header;
}
if (decrypted.resolvedKey) {
return { ...result, key: decrypted.key };
}
return result;
}
export function prepareDecrypt(options) {
return {
keyManagementAlgorithms: options && validateAlgorithms('keyManagementAlgorithms', options.keyManagementAlgorithms),
contentEncryptionAlgorithms: options &&
validateAlgorithms('contentEncryptionAlgorithms', options.contentEncryptionAlgorithms),
options,
};
}
export async function decryptRecipient(jwe, token, shared, key) {
const { options } = shared;
const { parsedProt } = token;
let joseHeader;
if (jwe.header !== undefined || jwe.unprotected !== undefined) {
if (!isDisjoint(parsedProt, jwe.header, jwe.unprotected)) {
throw new JWEInvalid('JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint');
}
joseHeader = { ...parsedProt, ...jwe.header, ...jwe.unprotected };
}
else {
joseHeader = parsedProt ?? {};
}
validateCrit(JWEInvalid, JWE_RECOGNIZED, options?.crit, parsedProt, joseHeader);
if (joseHeader.zip !== undefined && joseHeader.zip !== 'DEF') {
throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value.');
}
if (joseHeader.zip !== undefined && !parsedProt?.zip) {
throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header Parameter MUST be in a protected header.');
}
const { alg, enc } = joseHeader;
if (typeof alg !== 'string' || !alg) {
throw new JWEInvalid('missing JWE Algorithm (alg) in JWE Header');
}
if (typeof enc !== 'string' || !enc) {
throw new JWEInvalid('missing JWE Encryption Algorithm (enc) in JWE Header');
}
const { keyManagementAlgorithms, contentEncryptionAlgorithms } = shared;
if ((keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) ||
(!keyManagementAlgorithms && alg.startsWith('PBES2'))) {
throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter value not allowed');
}
if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) {
throw new JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter value not allowed');
}
const encEntry = jweEncryption(enc);
let encryptedKey;
if (jwe.encrypted_key !== undefined) {
encryptedKey = decodeBase64url(jwe.encrypted_key, 'encrypted_key', JWEInvalid);
}
let resolvedKey = false;
if (typeof key === 'function') {
key = await key(parsedProt, jwe);
resolvedKey = true;
}
const algEntry = jweAlgorithm(alg);
const k = await prepareKey(alg === 'dir' ? encEntry : algEntry, key, 'decrypt');
let cek;
try {
cek = await decryptKeyManagement(alg, encEntry, k, encryptedKey, joseHeader, options);
}
catch (err) {
if (err instanceof TypeError || err instanceof JWEInvalid || err instanceof JOSENotSupported) {
throw err;
}
cek = generateCek(encEntry);
}
let plaintext = await decrypt(encEntry, cek, token.ciphertext, token.iv, token.tag, token.additionalData);
if (joseHeader.zip === 'DEF') {
const maxDecompressedLength = options?.maxDecompressedLength ?? 250_000;
if (maxDecompressedLength === 0) {
throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported.');
}
if (maxDecompressedLength !== Infinity &&
(!Number.isSafeInteger(maxDecompressedLength) || maxDecompressedLength < 1)) {
throw new TypeError('maxDecompressedLength must be 0, a positive safe integer, or Infinity');
}
plaintext = await decompress(plaintext, maxDecompressedLength).catch((cause) => {
if (cause instanceof JWEInvalid)
throw cause;
throw new JWEInvalid('Failed to decompress plaintext', { cause });
});
}
return { plaintext, parsedProt, key: k, resolvedKey };
}
export async function decryptJWE(jwe, shared, key) {
return decryptRecipient(jwe, shareJWE(jwe), shared, key);
}
export async function decryptCompact(jwe, shared, key) {
if (jwe instanceof Uint8Array) {
jwe = decoder.decode(jwe);
}
if (typeof jwe !== 'string') {
throw new JWEInvalid('Compact JWE must be a string or Uint8Array');
}
const { 0: protectedHeader, 1: encryptedKey, 2: iv, 3: ciphertext, 4: tag, length, } = jwe.split('.');
if (length !== 5) {
throw new JWEInvalid('Invalid Compact JWE');
}
return decryptJWE({
ciphertext,
iv: iv || undefined,
protected: protectedHeader,
tag: tag || undefined,
encrypted_key: encryptedKey || undefined,
}, shared, key);
}
import { encode as b64u } from '../util/base64url.js';
import { encrypt } from './content_encryption.js';
import { encryptKeyManagement } from './key_management.js';
import { JOSENotSupported, JWEInvalid } from '../util/errors.js';
import { isDisjoint } from './type_checks.js';
import { concat, encode } from './buffer_utils.js';
import { validateCrit, JWE_RECOGNIZED } from './options.js';
import { prepareKey } from './key.js';
import { jweAlgorithm, jweEncryption } from './jwe_algorithms.js';
import { compress } from './deflate.js';
export function checkEncryptHeaders(input) {
const { protectedHeader, unprotectedHeader, sharedUnprotectedHeader } = input;
if (!isDisjoint(protectedHeader, unprotectedHeader, sharedUnprotectedHeader)) {
throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint');
}
const joseHeader = {
...protectedHeader,
...unprotectedHeader,
...sharedUnprotectedHeader,
};
validateCrit(JWEInvalid, JWE_RECOGNIZED, input.crit, protectedHeader, joseHeader);
if (joseHeader.zip !== undefined && joseHeader.zip !== 'DEF') {
throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value.');
}
if (joseHeader.zip !== undefined && !protectedHeader?.zip) {
throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header Parameter MUST be in a protected header.');
}
const { alg, enc } = joseHeader;
if (typeof alg !== 'string' || !alg) {
throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid');
}
if (typeof enc !== 'string' || !enc) {
throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid');
}
return { joseHeader, alg, enc, encEntry: jweEncryption(enc) };
}
export async function encryptJWE(input, checked, key) {
const { joseHeader, alg, encEntry } = checked;
let { protectedHeader, unprotectedHeader } = input;
const { sharedUnprotectedHeader } = input;
if (input.cek && (alg === 'dir' || alg === 'ECDH-ES')) {
throw new TypeError(`setContentEncryptionKey cannot be called with JWE "alg" (Algorithm) Header ${alg}`);
}
const algEntry = jweAlgorithm(alg);
const k = await prepareKey(alg === 'dir' ? encEntry : algEntry, key, 'encrypt');
const { cek, encryptedKey, parameters } = await encryptKeyManagement(alg, encEntry, k, input.cek, input.keyManagementParameters);
if (parameters) {
if (input.unprotectedParameters) {
unprotectedHeader = unprotectedHeader ? { ...unprotectedHeader, ...parameters } : parameters;
}
else {
protectedHeader = protectedHeader ? { ...protectedHeader, ...parameters } : parameters;
}
}
let protectedHeaderS;
let protectedHeaderB;
if (protectedHeader) {
protectedHeaderS = b64u(JSON.stringify(protectedHeader));
protectedHeaderB = encode(protectedHeaderS);
}
else {
protectedHeaderS = '';
protectedHeaderB = new Uint8Array();
}
let additionalData;
let aadMember;
if (input.aad?.byteLength) {
aadMember = b64u(input.aad);
additionalData = concat(protectedHeaderB, encode('.'), encode(aadMember));
}
else {
additionalData = protectedHeaderB;
}
let plaintext = input.plaintext;
if (joseHeader.zip === 'DEF') {
plaintext = await compress(plaintext).catch((cause) => {
throw new JWEInvalid('Failed to compress plaintext', { cause });
});
}
const { ciphertext, tag, iv } = await encrypt(encEntry, plaintext, cek, input.iv, additionalData);
const jwe = {
ciphertext: b64u(ciphertext),
};
if (iv) {
jwe.iv = b64u(iv);
}
if (tag) {
jwe.tag = b64u(tag);
}
if (encryptedKey) {
jwe.encrypted_key = b64u(encryptedKey);
}
if (aadMember) {
jwe.aad = aadMember;
}
if (protectedHeader) {
jwe.protected = protectedHeaderS;
}
if (sharedUnprotectedHeader) {
jwe.unprotected = sharedUnprotectedHeader;
}
if (unprotectedHeader) {
jwe.header = unprotectedHeader;
}
return jwe;
}
export async function createJWE(input, key) {
return encryptJWE(input, checkEncryptHeaders(input), key);
}
import { JOSENotSupported } from '../util/errors.js';
import { table } from './key_descriptor.js';
const sig = { public: ['verify'], private: ['sign'] };
function hmac(bits) {
const subtle = { name: 'HMAC', hash: `SHA-${bits}` };
return { kty: ['oct'], symmetric: true, subtle, operation: subtle, usages: sig };
}
function rsa(name, bits, saltLength) {
const subtle = { name, hash: `SHA-${bits}` };
return {
kty: ['RSA'],
subtle,
operation: saltLength ? { ...subtle, saltLength } : subtle,
usages: sig,
minModulusLength: 2048,
};
}
function ecdsa(crv, bits) {
return {
kty: ['EC'],
crv,
subtle: { name: 'ECDSA', namedCurve: crv },
operation: { name: 'ECDSA', hash: `SHA-${bits}` },
usages: sig,
};
}
function eddsa() {
const subtle = { name: 'Ed25519' };
return {
kty: ['OKP'],
crv: 'Ed25519',
subtle,
operation: subtle,
usages: sig,
};
}
function mldsa(name) {
const subtle = { name };
return {
kty: ['AKP'],
subtle,
operation: subtle,
usages: sig,
};
}
const JWS = table({
HS256: hmac(256),
HS384: hmac(384),
HS512: hmac(512),
RS256: rsa('RSASSA-PKCS1-v1_5', 256),
RS384: rsa('RSASSA-PKCS1-v1_5', 384),
RS512: rsa('RSASSA-PKCS1-v1_5', 512),
PS256: rsa('RSA-PSS', 256, 32),
PS384: rsa('RSA-PSS', 384, 48),
PS512: rsa('RSA-PSS', 512, 64),
ES256: ecdsa('P-256', 256),
ES384: ecdsa('P-384', 384),
ES512: ecdsa('P-521', 512),
EdDSA: eddsa(),
Ed25519: eddsa(),
'ML-DSA-44': mldsa('ML-DSA-44'),
'ML-DSA-65': mldsa('ML-DSA-65'),
'ML-DSA-87': mldsa('ML-DSA-87'),
});
export function jwsAlgorithm(alg) {
const entry = JWS[alg];
if (!entry) {
throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
}
return entry;
}
export function maybeJWSAlgorithm(alg) {
return JWS[alg];
}
import { encode as b64u } from '../util/base64url.js';
import { sign } from './signing.js';
import { jwsAlgorithm } from './jws_algorithms.js';
import { isDisjoint } from './type_checks.js';
import { JWSInvalid } from '../util/errors.js';
import { concat, encode } from './buffer_utils.js';
import { validateCrit, validateCritDuplicates, JWS_RECOGNIZED } from './options.js';
import { prepareKey } from './key.js';
export function unencodedPayload(protectedHeader) {
return (protectedHeader?.b64 === false &&
Array.isArray(protectedHeader.crit) &&
protectedHeader.crit.includes('b64'));
}
export async function createSignature(input, key) {
const { protectedHeader, unprotectedHeader } = input;
if (!isDisjoint(protectedHeader, unprotectedHeader)) {
throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint');
}
const joseHeader = { ...protectedHeader, ...unprotectedHeader };
validateCritDuplicates(JWSInvalid, protectedHeader);
const extensions = validateCrit(JWSInvalid, JWS_RECOGNIZED, input.crit, protectedHeader, joseHeader);
let b64 = true;
if (extensions.has('b64')) {
b64 = protectedHeader.b64;
if (typeof b64 !== 'boolean') {
throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
}
}
const { alg } = joseHeader;
if (typeof alg !== 'string' || !alg) {
throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
}
const entry = jwsAlgorithm(alg);
let payloadS;
let payloadB;
if (b64) {
const encoded = (input.encoded ??= {});
encoded.b64 ??= b64u(input.payload);
encoded.raw ??= encode(encoded.b64);
payloadS = encoded.b64;
payloadB = encoded.raw;
}
else {
payloadB = input.payload;
payloadS = '';
}
let protectedHeaderString;
let protectedHeaderBytes;
if (protectedHeader) {
protectedHeaderString = b64u(JSON.stringify(protectedHeader));
protectedHeaderBytes = encode(protectedHeaderString);
}
else {
protectedHeaderString = '';
protectedHeaderBytes = new Uint8Array();
}
const data = concat(protectedHeaderBytes, encode('.'), payloadB);
const k = await prepareKey(entry, key, 'sign');
const signature = await sign(entry, k, data);
const jws = {
signature: b64u(signature),
payload: payloadS,
};
if (protectedHeader) {
jws.protected = protectedHeaderString;
}
return jws;
}
import { verify } from './signing.js';
import { jwsAlgorithm } from './jws_algorithms.js';
import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../util/errors.js';
import { concat, decoder, encoder, encode } from './buffer_utils.js';
import { decodeBase64url, encodeBase64url, parseJoseHeader } from './helpers.js';
import { isDisjoint } from './type_checks.js';
import { validateCrit, validateAlgorithms, JWS_RECOGNIZED } from './options.js';
import { prepareKey } from './key.js';
export function verifyResult(jws, verified) {
const result = { payload: verified.payload };
if (jws.protected !== undefined) {
result.protectedHeader = verified.parsedProt;
}
if (jws.header !== undefined) {
result.unprotectedHeader = jws.header;
}
if (verified.resolvedKey) {
return { ...result, key: verified.key };
}
return result;
}
export function prepareVerify(options) {
return {
algorithms: options && validateAlgorithms('algorithms', options.algorithms),
crit: options?.crit,
};
}
export async function verifySignature(jws, shared, key) {
let parsedProt = {};
if (jws.protected) {
parsedProt = parseJoseHeader(jws.protected, JWSInvalid, 'JWS Protected Header is invalid');
}
let joseHeader;
if (jws.header !== undefined) {
if (!isDisjoint(parsedProt, jws.header)) {
throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint');
}
joseHeader = { ...parsedProt, ...jws.header };
}
else {
joseHeader = parsedProt;
}
const extensions = validateCrit(JWSInvalid, JWS_RECOGNIZED, shared.crit, parsedProt, joseHeader);
let b64 = true;
if (extensions.has('b64')) {
b64 = parsedProt.b64;
if (typeof b64 !== 'boolean') {
throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
}
}
const { alg } = joseHeader;
if (typeof alg !== 'string' || !alg) {
throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
}
if (shared.algorithms && !shared.algorithms.has(alg)) {
throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter value not allowed');
}
if (b64) {
if (typeof jws.payload !== 'string') {
throw new JWSInvalid('JWS Payload must be a string');
}
}
else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) {
throw new JWSInvalid('JWS Payload must be a string or an Uint8Array instance');
}
let resolvedKey = false;
if (typeof key === 'function') {
key = await key(parsedProt, jws);
resolvedKey = true;
}
const entry = jwsAlgorithm(alg);
const data = concat(jws.protected !== undefined ? encode(jws.protected) : new Uint8Array(), encode('.'), typeof jws.payload === 'string'
? b64
?
(shared.b64p ??= encodeBase64url(jws.payload, 'payload', JWSInvalid))
: encoder.encode(jws.payload)
: jws.payload);
const signature = decodeBase64url(jws.signature, 'signature', JWSInvalid);
const k = await prepareKey(entry, key, 'verify');
const verified = await verify(entry, k, signature, data);
if (!verified) {
throw new JWSSignatureVerificationFailed();
}
let payload;
if (b64) {
payload = decodeBase64url(jws.payload, 'payload', JWSInvalid);
}
else if (typeof jws.payload === 'string') {
payload = encoder.encode(jws.payload);
}
else {
payload = jws.payload;
}
return { payload, parsedProt, b64, key: k, resolvedKey };
}
export async function verifyCompact(jws, shared, key) {
if (jws instanceof Uint8Array) {
jws = decoder.decode(jws);
}
if (typeof jws !== 'string') {
throw new JWSInvalid('Compact JWS must be a string or Uint8Array');
}
const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split('.');
if (length !== 3) {
throw new JWSInvalid('Invalid Compact JWS');
}
return verifySignature({ payload, protected: protectedHeader, signature }, shared, key);
}
import { JOSENotSupported } from '../util/errors.js';
import { maybeJWSAlgorithm } from './jws_algorithms.js';
import { maybeJWEAlgorithm } from './jwe_algorithms.js';
function unsupportedAlgorithm() {
return new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
}
export function keyAlgorithm(alg) {
if (typeof alg !== 'string') {
throw unsupportedAlgorithm();
}
const entry = maybeJWSAlgorithm(alg) ?? maybeJWEAlgorithm(alg);
if (!entry) {
throw unsupportedAlgorithm();
}
return entry;
}
export function table(entries) {
const out = { __proto__: null };
for (const alg of Object.keys(entries)) {
out[alg] = { ...entries[alg], alg };
}
return out;
}
import { withAlg as invalidKeyInput } from './invalid_key_input.js';
import { isKeyLike, isCryptoKey } from './is_key_like.js';
import * as jwk from './type_checks.js';
import { decode } from '../util/base64url.js';
import { jwkToKey } from './jwk_to_key.js';
const tag = (key) => key[Symbol.toStringTag];
const jwkMatchesOp = (entry, key, usage) => {
const { alg } = entry;
if (key.use !== undefined) {
let expected;
switch (usage) {
case 'sign':
case 'verify':
expected = 'sig';
break;
case 'encrypt':
case 'decrypt':
expected = 'enc';
break;
}
if (key.use !== expected) {
throw new TypeError(`Invalid key for this operation, its "use" must be "${expected}" when present`);
}
}
if (key.alg !== undefined && key.alg !== alg) {
throw new TypeError(`Invalid key for this operation, its "alg" must be "${alg}" when present`);
}
if (Array.isArray(key.key_ops)) {
const expectedKeyOp = usage === 'encrypt' || usage === 'decrypt' ? entry.keyOps?.[usage] : usage;
if (expectedKeyOp && key.key_ops?.includes?.(expectedKeyOp) === false) {
throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${expectedKeyOp}" when present`);
}
}
return true;
};
const symmetricTypeCheck = (entry, key, usage) => {
const { alg } = entry;
if (key instanceof Uint8Array)
return { kind: BYTES, key };
if (jwk.isJWK(key)) {
if (jwk.isSecretJWK(key) && jwkMatchesOp(entry, key, usage))
return { kind: JWK, key };
throw new TypeError(`JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present`);
}
if (!isKeyLike(key)) {
throw new TypeError(invalidKeyInput(alg, key, 'CryptoKey', 'KeyObject', 'JSON Web Key', 'Uint8Array'));
}
if (key.type !== 'secret') {
throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type "secret"`);
}
return isCryptoKey(key) ? { kind: CRYPTO, key } : { kind: KEYOBJECT, key };
};
const asymmetricTypeCheck = (entry, key, usage) => {
const { alg } = entry;
if (jwk.isJWK(key)) {
switch (usage) {
case 'decrypt':
case 'sign':
if (jwk.isPrivateJWK(key) && jwkMatchesOp(entry, key, usage))
return { kind: JWK, key };
throw new TypeError(`JSON Web Key for this operation must be a private JWK`);
case 'encrypt':
case 'verify':
if (jwk.isPublicJWK(key) && jwkMatchesOp(entry, key, usage))
return { kind: JWK, key };
throw new TypeError(`JSON Web Key for this operation must be a public JWK`);
}
}
if (!isKeyLike(key)) {
throw new TypeError(invalidKeyInput(alg, key, 'CryptoKey', 'KeyObject', 'JSON Web Key'));
}
if (key.type === 'secret') {
throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type "secret"`);
}
if (key.type === 'public') {
switch (usage) {
case 'sign':
throw new TypeError(`${tag(key)} instances for asymmetric algorithm signing must be of type "private"`);
case 'decrypt':
throw new TypeError(`${tag(key)} instances for asymmetric algorithm decryption must be of type "private"`);
}
}
if (key.type === 'private') {
switch (usage) {
case 'verify':
throw new TypeError(`${tag(key)} instances for asymmetric algorithm verifying must be of type "public"`);
case 'encrypt':
throw new TypeError(`${tag(key)} instances for asymmetric algorithm encryption must be of type "public"`);
}
}
return isCryptoKey(key) ? { kind: CRYPTO, key } : { kind: KEYOBJECT, key };
};
const BYTES = Symbol();
const CRYPTO = Symbol();
const KEYOBJECT = Symbol();
const JWK = Symbol();
export function checkKeyType(entry, key, usage) {
return entry.symmetric
? symmetricTypeCheck(entry, key, usage)
: asymmetricTypeCheck(entry, key, usage);
}
let cache;
const nist = {
__proto__: null,
prime256v1: 'P-256',
secp384r1: 'P-384',
secp521r1: 'P-521',
};
function cached(key, alg) {
cache ||= new WeakMap();
return cache.get(key)?.[alg];
}
function store(key, alg, cryptoKey) {
const entry = cache.get(key);
if (entry) {
entry[alg] = cryptoKey;
}
else {
cache.set(key, { [alg]: cryptoKey });
}
return cryptoKey;
}
const handleJWK = async (key, jwk, entry) => {
const hit = cached(key, entry.alg);
if (hit)
return hit;
const cryptoKey = await jwkToKey(entry, { ...jwk, alg: entry.alg });
return store(key, entry.alg, cryptoKey);
};
const handleKeyObject = (keyObject, entry) => {
const hit = cached(keyObject, entry.alg);
if (hit)
return hit;
const isPublic = keyObject.type === 'public';
const usages = isPublic ? entry.usages.public : entry.usages.private;
const { asymmetricKeyType } = keyObject;
const crv = nist[keyObject.asymmetricKeyDetails?.namedCurve];
const params = entry.subtleFor?.({ crv, asymmetricKeyType }) ?? entry.subtle;
return store(keyObject, entry.alg, keyObject.toCryptoKey(params, isPublic, usages));
};
export async function prepareKey(entry, key, usage) {
const tagged = checkKeyType(entry, key, usage);
switch (tagged.kind) {
case BYTES:
case CRYPTO:
return tagged.key;
case JWK: {
if (tagged.key.k) {
return decode(tagged.key.k);
}
if (!Object.isFrozen(tagged.key)) {
const { key_ops } = tagged.key;
if (Array.isArray(key_ops))
Object.freeze(key_ops);
Object.freeze(tagged.key);
}
return handleJWK(tagged.key, tagged.key, entry);
}
case KEYOBJECT: {
const keyObject = tagged.key;
if (keyObject.type === 'secret') {
return keyObject.export();
}
if ('toCryptoKey' in keyObject && typeof keyObject.toCryptoKey === 'function') {
return handleKeyObject(keyObject, entry);
}
return handleJWK(keyObject, keyObject.export({ format: 'jwk' }), entry);
}
}
}
import { JOSENotSupported, JWEInvalid, JWSInvalid } from '../util/errors.js';
export const JWS_RECOGNIZED = new Map([['b64', true]]);
export const JWE_RECOGNIZED = new Map();
export function validateAlgorithms(option, algorithms) {
if (algorithms !== undefined &&
(!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) {
throw new TypeError(`"${option}" option must be an array of strings`);
}
if (!algorithms) {
return undefined;
}
return new Set(algorithms);
}
export function validateCritDuplicates(Err, protectedHeader) {
const { crit } = protectedHeader ?? {};
if (Array.isArray(crit) && new Set(crit).size !== crit.length) {
throw new Err('"crit" (Critical) Header Parameter MUST NOT contain duplicate values');
}
}
export function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
if (joseHeader.crit !== undefined && protectedHeader?.crit === undefined) {
throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
}
if (!protectedHeader || protectedHeader.crit === undefined) {
return new Set();
}
if (!Array.isArray(protectedHeader.crit) ||
protectedHeader.crit.length === 0 ||
protectedHeader.crit.some((input) => typeof input !== 'string' || input.length === 0)) {
throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');
}
let recognized;
if (recognizedOption !== undefined) {
recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]);
}
else {
recognized = recognizedDefault;
}
for (const parameter of protectedHeader.crit) {
if (!recognized.has(parameter)) {
throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`);
}
if (joseHeader[parameter] === undefined) {
throw new Err(`Extension Header Parameter "${parameter}" is missing`);
}
if (recognized.get(parameter) && protectedHeader[parameter] === undefined) {
throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`);
}
}
return new Set(protectedHeader.crit);
}
+6
-5

@@ -30,4 +30,5 @@ export { compactDecrypt } from './jwe/compact/decrypt.js';

export { createLocalJWKSet } from './jwks/local.js';
export type { LocalJWKSet } from './jwks/local.js';
export { createRemoteJWKSet, jwksCache, customFetch } from './jwks/remote.js';
export type { RemoteJWKSetOptions, JWKSCacheInput, ExportedJWKSCache, FetchImplementation, } from './jwks/remote.js';
export type { RemoteJWKSet, RemoteJWKSetOptions, JWKSCacheInput, ExportedJWKSCache, FetchImplementation, } from './jwks/remote.js';
export { UnsecuredJWT } from './jwt/unsecured.js';

@@ -44,8 +45,8 @@ export type { UnsecuredResult } from './jwt/unsecured.js';

export { generateKeyPair } from './key/generate_key_pair.js';
export type { GenerateKeyPairResult, GenerateKeyPairOptions } from './key/generate_key_pair.js';
export type { GenerateKeyPairAlgorithm, GenerateKeyPairResult, GenerateKeyPairOptions, } from './key/generate_key_pair.js';
export { generateSecret } from './key/generate_secret.js';
export type { GenerateSecretOptions } from './key/generate_secret.js';
export type { GenerateSecretAlgorithm, GenerateSecretOptions } from './key/generate_secret.js';
import * as base64url from './util/base64url.js';
export { base64url };
export type { CompactDecryptResult, CompactJWEHeaderParameters, CompactJWSHeaderParameters, CompactVerifyResult, CritOption, CryptoKey, DecryptOptions, EncryptOptions, FlattenedDecryptResult, FlattenedJWE, FlattenedJWS, FlattenedJWSInput, FlattenedVerifyResult, GeneralDecryptResult, GeneralJWE, GeneralJWS, GeneralJWSInput, GeneralVerifyResult, GetKeyFunction, JoseHeaderParameters, JSONWebKeySet, JWEHeaderParameters, JWEKeyManagementHeaderParameters, JWK_EC_Private, JWK_EC_Public, JWK_oct, JWK_OKP_Private, JWK_OKP_Public, JWK_RSA_Private, JWK_RSA_Public, JWK, JWKParameters, JWSHeaderParameters, JWTClaimVerificationOptions, JWTDecryptResult, JWTHeaderParameters, JWTPayload, JWTVerifyResult, KeyObject, ProduceJWT, ResolvedKey, SignOptions, VerifyOptions, } from './types.d.ts';
export type { AnyJWK, CompactDecryptResult, CompactJWEHeaderParameters, CompactJWSHeaderParameters, CompactVerifyResult, CritOption, CryptoKey, DecryptOptions, EncryptOptions, FlattenedDecryptResult, FlattenedJWE, FlattenedJWS, FlattenedJWSInput, FlattenedVerifyResult, GeneralDecryptResult, GeneralJWE, GeneralJWS, GeneralJWSInput, GeneralVerifyResult, GetKeyFunction, JoseHeaderParameters, JSONWebKeySet, JWEContentEncryptionAlgorithm, JWEHeaderParameters, JWEKeyManagementAlgorithm, JWEKeyManagementHeaderParameters, JWK_AKP_Private, JWK_AKP_Public, JWK_EC_Private, JWK_EC_Public, JWK_oct, JWK_OKP_Private, JWK_OKP_Public, JWK_RSA_Private, JWK_RSA_Public, JWK, JWKKeyType, JWKParameters, JWSAlgorithm, JWSHeaderParameters, JWTClaimVerificationOptions, JWTDecryptResult, JWTHeaderParameters, JWTPayload, JWTVerifyResult, KeyInput, KeyObject, ProduceJWT, ResolvedKey, SignOptions, VerifyOptions, } from './types.d.ts';
/**

@@ -55,4 +56,4 @@ * In prior releases this indicated whether a Node.js-specific build was loaded, this is now fixed

*
* @deprecated
* @deprecated Remove any runtime branching on this value; it is always `"WebCryptoAPI"`.
*/
export declare const cryptoRuntime = "WebCryptoAPI";

@@ -1,6 +0,1 @@

/**
* Decrypting JSON Web Encryption (JWE) in Compact Serialization
*
* @module
*/
import type * as types from '../../types.d.ts';

@@ -11,3 +6,3 @@ /**

*/
export interface CompactDecryptGetKey extends types.GetKeyFunction<types.CompactJWEHeaderParameters, types.FlattenedJWE> {
export interface CompactDecryptGetKey<KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array> extends types.GetKeyFunction<types.CompactJWEHeaderParameters, types.FlattenedJWE, KeyType | types.KeyObject | types.JWK> {
}

@@ -17,5 +12,2 @@ /**

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/jwe/compact/decrypt'`.
*
* @param jwe Compact JWE.

@@ -26,4 +18,7 @@ * @param key Private Key or Secret to decrypt the JWE with. See

*/
export declare function compactDecrypt(jwe: string | Uint8Array, key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: types.DecryptOptions): Promise<types.CompactDecryptResult>;
export declare function compactDecrypt(jwe: string | Uint8Array, key: types.KeyInput, options?: types.DecryptOptions): Promise<types.CompactDecryptResult>;
/**
* Decrypts a Compact JWE, resolving the key dynamically. The result additionally carries the
* {@link types.ResolvedKey.key resolved key}.
*
* @param jwe Compact JWE.

@@ -34,2 +29,13 @@ * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. See

*/
export declare function compactDecrypt(jwe: string | Uint8Array, getKey: CompactDecryptGetKey, options?: types.DecryptOptions): Promise<types.CompactDecryptResult & types.ResolvedKey>;
export declare function compactDecrypt<KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array>(jwe: string | Uint8Array, getKey: CompactDecryptGetKey<KeyType>, options?: types.DecryptOptions): Promise<types.CompactDecryptResult & types.ResolvedKey<KeyType>>;
/**
* Accepts either form of the `key` argument. Use this overload when forwarding a value that may be
* either a key or a key resolution function; `key` is present on the result only when a resolution
* function was used.
*
* @param jwe Compact JWE.
* @param key Private Key or Secret, or a function resolving one, to decrypt the JWE with. See
* {@link https://github.com/panva/jose/issues/210#jwe-alg Algorithm Key Requirements}.
* @param options JWE Decryption options.
*/
export declare function compactDecrypt(jwe: string | Uint8Array, key: types.KeyInput | CompactDecryptGetKey, options?: types.DecryptOptions): Promise<types.CompactDecryptResult & Partial<types.ResolvedKey>>;

@@ -1,14 +0,3 @@

/**
* Encrypting JSON Web Encryption (JWE) in Compact Serialization
*
* @module
*/
import type * as types from '../../types.d.ts';
/**
* The CompactEncrypt class is used to build and encrypt Compact JWE strings.
*
* This class is exported (as a named export) from the main `'jose'` module entry point as well as
* from its subpath export `'jose/jwe/compact/encrypt'`.
*
*/
/** The CompactEncrypt class is used to build and encrypt Compact JWE strings. */
export declare class CompactEncrypt {

@@ -24,3 +13,3 @@ #private;

* Sets a content encryption key to use, by default a random suitable one is generated for the JWE
* enc" (Encryption Algorithm) Header Parameter.
* "enc" (Encryption Algorithm) Header Parameter.
*

@@ -35,3 +24,3 @@ * @deprecated You should not use this method. It is only really intended for test and vector

* Sets the JWE Initialization Vector to use for content encryption, by default a random suitable
* one is generated for the JWE enc" (Encryption Algorithm) Header Parameter.
* one is generated for the JWE "enc" (Encryption Algorithm) Header Parameter.
*

@@ -51,7 +40,6 @@ * @deprecated You should not use this method. It is only really intended for test and vector

/**
* Sets the JWE Key Management parameters to be used when encrypting.
* Sets the JWE Key Management parameters to be used when encrypting. For ECDH based algorithms,
* use this method to set the "apu" (Agreement PartyUInfo) or "apv" (Agreement PartyVInfo)
* parameters.
*
* (ECDH-ES) Use of this method is needed for ECDH based algorithms to set the "apu" (Agreement
* PartyUInfo) or "apv" (Agreement PartyVInfo) parameters.
*
* @param parameters JWE Key Management parameters.

@@ -67,3 +55,3 @@ */

*/
encrypt(key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: types.EncryptOptions): Promise<string>;
encrypt(key: types.KeyInput, options?: types.EncryptOptions): Promise<string>;
}

@@ -1,6 +0,1 @@

/**
* Decrypting JSON Web Encryption (JWE) in Flattened JSON Serialization
*
* @module
*/
import type * as types from '../../types.d.ts';

@@ -11,3 +6,3 @@ /**

*/
export interface FlattenedDecryptGetKey extends types.GetKeyFunction<types.JWEHeaderParameters | undefined, types.FlattenedJWE> {
export interface FlattenedDecryptGetKey<KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array> extends types.GetKeyFunction<types.JWEHeaderParameters | undefined, types.FlattenedJWE, KeyType | types.KeyObject | types.JWK> {
}

@@ -17,5 +12,2 @@ /**

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/jwe/flattened/decrypt'`.
*
* @param jwe Flattened JWE.

@@ -26,4 +18,7 @@ * @param key Private Key or Secret to decrypt the JWE with. See

*/
export declare function flattenedDecrypt(jwe: types.FlattenedJWE, key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: types.DecryptOptions): Promise<types.FlattenedDecryptResult>;
export declare function flattenedDecrypt(jwe: types.FlattenedJWE, key: types.KeyInput, options?: types.DecryptOptions): Promise<types.FlattenedDecryptResult>;
/**
* Decrypts a Flattened JWE, resolving the key dynamically. The result additionally carries the
* {@link types.ResolvedKey.key resolved key}.
*
* @param jwe Flattened JWE.

@@ -34,2 +29,13 @@ * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. See

*/
export declare function flattenedDecrypt(jwe: types.FlattenedJWE, getKey: FlattenedDecryptGetKey, options?: types.DecryptOptions): Promise<types.FlattenedDecryptResult & types.ResolvedKey>;
export declare function flattenedDecrypt<KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array>(jwe: types.FlattenedJWE, getKey: FlattenedDecryptGetKey<KeyType>, options?: types.DecryptOptions): Promise<types.FlattenedDecryptResult & types.ResolvedKey<KeyType>>;
/**
* Accepts either form of the `key` argument. Use this overload when forwarding a value that may be
* either a key or a key resolution function; `key` is present on the result only when a resolution
* function was used.
*
* @param jwe Flattened JWE.
* @param key Private Key or Secret, or a function resolving one, to decrypt the JWE with. See
* {@link https://github.com/panva/jose/issues/210#jwe-alg Algorithm Key Requirements}.
* @param options JWE Decryption options.
*/
export declare function flattenedDecrypt(jwe: types.FlattenedJWE, key: types.KeyInput | FlattenedDecryptGetKey, options?: types.DecryptOptions): Promise<types.FlattenedDecryptResult & Partial<types.ResolvedKey>>;

@@ -1,14 +0,3 @@

/**
* Encrypting JSON Web Encryption (JWE) in Flattened JSON Serialization
*
* @module
*/
import type * as types from '../../types.d.ts';
/**
* The FlattenedEncrypt class is used to build and encrypt Flattened JWE objects.
*
* This class is exported (as a named export) from the main `'jose'` module entry point as well as
* from its subpath export `'jose/jwe/flattened/encrypt'`.
*
*/
/** The FlattenedEncrypt class is used to build and encrypt Flattened JWE objects. */
export declare class FlattenedEncrypt {

@@ -23,7 +12,6 @@ #private;

/**
* Sets the JWE Key Management parameters to be used when encrypting.
* Sets the JWE Key Management parameters to be used when encrypting. For ECDH based algorithms,
* use this method to set the "apu" (Agreement PartyUInfo) or "apv" (Agreement PartyVInfo)
* parameters.
*
* (ECDH-ES) Use of this method is needed for ECDH based algorithms to set the "apu" (Agreement
* PartyUInfo) or "apv" (Agreement PartyVInfo) parameters.
*
* @param parameters JWE Key Management parameters.

@@ -58,3 +46,3 @@ */

* Sets a content encryption key to use, by default a random suitable one is generated for the JWE
* enc" (Encryption Algorithm) Header Parameter.
* "enc" (Encryption Algorithm) Header Parameter.
*

@@ -69,3 +57,3 @@ * @deprecated You should not use this method. It is only really intended for test and vector

* Sets the JWE Initialization Vector to use for content encryption, by default a random suitable
* one is generated for the JWE enc" (Encryption Algorithm) Header Parameter.
* one is generated for the JWE "enc" (Encryption Algorithm) Header Parameter.
*

@@ -85,3 +73,3 @@ * @deprecated You should not use this method. It is only really intended for test and vector

*/
encrypt(key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: types.EncryptOptions): Promise<types.FlattenedJWE>;
encrypt(key: types.KeyInput, options?: types.EncryptOptions): Promise<types.FlattenedJWE>;
}

@@ -1,6 +0,1 @@

/**
* Decrypting JSON Web Encryption (JWE) in General JSON Serialization
*
* @module
*/
import type * as types from '../../types.d.ts';

@@ -11,3 +6,3 @@ /**

*/
export interface GeneralDecryptGetKey extends types.GetKeyFunction<types.JWEHeaderParameters, types.FlattenedJWE> {
export interface GeneralDecryptGetKey<KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array> extends types.GetKeyFunction<types.JWEHeaderParameters | undefined, types.FlattenedJWE, KeyType | types.KeyObject | types.JWK> {
}

@@ -17,7 +12,3 @@ /**

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/jwe/general/decrypt'`.
*
* > [!NOTE]\
* > The function iterates over the `recipients` array in the General JWE and returns the decryption
* > Note: The function iterates over the `recipients` array in the General JWE and returns the decryption
* > result of the first recipient entry that can be successfully decrypted. The result only contains

@@ -33,4 +24,7 @@ * > the plaintext and headers of that successfully decrypted recipient entry. Other recipient entries

*/
export declare function generalDecrypt(jwe: types.GeneralJWE, key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: types.DecryptOptions): Promise<types.GeneralDecryptResult>;
export declare function generalDecrypt(jwe: types.GeneralJWE, key: types.KeyInput, options?: types.DecryptOptions): Promise<types.GeneralDecryptResult>;
/**
* Decrypts a General JWE, resolving the key dynamically. The result additionally carries the
* {@link types.ResolvedKey.key resolved key}.
*
* @param jwe General JWE.

@@ -41,2 +35,13 @@ * @param getKey Function resolving Private Key or Secret to decrypt the JWE with. See

*/
export declare function generalDecrypt(jwe: types.GeneralJWE, getKey: GeneralDecryptGetKey, options?: types.DecryptOptions): Promise<types.GeneralDecryptResult & types.ResolvedKey>;
export declare function generalDecrypt<KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array>(jwe: types.GeneralJWE, getKey: GeneralDecryptGetKey<KeyType>, options?: types.DecryptOptions): Promise<types.GeneralDecryptResult & types.ResolvedKey<KeyType>>;
/**
* Accepts either form of the `key` argument. Use this overload when forwarding a value that may be
* either a key or a key resolution function; `key` is present on the result only when a resolution
* function was used.
*
* @param jwe General JWE.
* @param key Private Key or Secret, or a function resolving one, to decrypt the JWE with. See
* {@link https://github.com/panva/jose/issues/210#jwe-alg Algorithm Key Requirements}.
* @param options JWE Decryption options.
*/
export declare function generalDecrypt(jwe: types.GeneralJWE, key: types.KeyInput | GeneralDecryptGetKey, options?: types.DecryptOptions): Promise<types.GeneralDecryptResult & Partial<types.ResolvedKey>>;

@@ -1,6 +0,1 @@

/**
* Encrypting JSON Web Encryption (JWE) in General JSON Serialization
*
* @module
*/
import type * as types from '../../types.d.ts';

@@ -16,24 +11,28 @@ /** Used to build General JWE object's individual recipients. */

/**
* Sets the JWE Key Management parameters to be used when encrypting.
* Sets the JWE Key Management parameters to be used when encrypting. For ECDH based algorithms,
* use this method to set the "apu" (Agreement PartyUInfo) or "apv" (Agreement PartyVInfo)
* parameters.
*
* (ECDH-ES) Use of this method is needed for ECDH based algorithms to set the "apu" (Agreement
* PartyUInfo) or "apv" (Agreement PartyVInfo) parameters.
*
* @param parameters JWE Key Management parameters.
*/
setKeyManagementParameters(parameters: types.JWEKeyManagementHeaderParameters): Recipient;
/** A shorthand for calling addRecipient() on the enclosing {@link GeneralEncrypt} instance */
addRecipient(...args: Parameters<GeneralEncrypt['addRecipient']>): Recipient;
/** A shorthand for calling encrypt() on the enclosing {@link GeneralEncrypt} instance */
encrypt(...args: Parameters<GeneralEncrypt['encrypt']>): Promise<types.GeneralJWE>;
/**
* A shorthand for calling {@link GeneralEncrypt.addRecipient addRecipient()} on the enclosing
* {@link GeneralEncrypt} instance.
*
* @param key Public Key or Secret to encrypt the Content Encryption Key for the recipient with.
* See {@link https://github.com/panva/jose/issues/210#jwe-alg Algorithm Key Requirements}.
* @param options JWE Encryption options.
*/
addRecipient(key: types.KeyInput, options?: types.CritOption): Recipient;
/**
* A shorthand for calling {@link GeneralEncrypt.encrypt encrypt()} on the enclosing
* {@link GeneralEncrypt} instance. Takes no arguments — each recipient's key is supplied to
* {@link addRecipient}.
*/
encrypt(): Promise<types.GeneralJWE>;
/** Returns the enclosing {@link GeneralEncrypt} instance */
done(): GeneralEncrypt;
}
/**
* The GeneralEncrypt class is used to build and encrypt General JWE objects.
*
* This class is exported (as a named export) from the main `'jose'` module entry point as well as
* from its subpath export `'jose/jwe/general/encrypt'`.
*
*/
/** The GeneralEncrypt class is used to build and encrypt General JWE objects. */
export declare class GeneralEncrypt {

@@ -54,3 +53,3 @@ #private;

*/
addRecipient(key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: types.CritOption): Recipient;
addRecipient(key: types.KeyInput, options?: types.CritOption): Recipient;
/**

@@ -57,0 +56,0 @@ * Sets the JWE Protected Header on the GeneralEncrypt object.

@@ -1,17 +0,13 @@

/**
* Verification using a JWK Embedded in a JWS Header
*
* @module
*/
import type * as types from '../types.d.ts';
/**
* EmbeddedJWK is an implementation of a GetKeyFunction intended to be used with the JWS/JWT verify
* operations whenever you need to opt-in to verify signatures with a public key embedded in the
* token's "jwk" (JSON Web Key) Header Parameter. It is recommended to combine this with the verify
* function's `algorithms` option to define accepted JWS "alg" (Algorithm) Header Parameter values.
* EmbeddedJWK is an implementation of a {@link types.GetKeyFunction GetKeyFunction} intended to be
* used with the JWS/JWT verify operations whenever you need to opt-in to verify signatures with a
* public key embedded in the token's "jwk" (JSON Web Key) Header Parameter. It is recommended to
* combine this with the verify function's `algorithms` option to define accepted JWS "alg"
* (Algorithm) Header Parameter values.
*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/jwk/embedded'`.
*
* @param protectedHeader JWS Protected Header.
* @param token The consumed JWS token.
* @returns The public key from the JWS "jwk" (JSON Web Key) Header Parameter.
*/
export declare function EmbeddedJWK(protectedHeader?: types.JWSHeaderParameters, token?: types.FlattenedJWSInput): Promise<types.CryptoKey>;

@@ -1,6 +0,1 @@

/**
* JSON Web Key Thumbprint and JSON Web Key Thumbprint URI
*
* @module
*/
import type * as types from '../types.d.ts';

@@ -10,10 +5,5 @@ /**

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/jwk/thumbprint'`.
*
* @param key Key to calculate the thumbprint for.
* @param digestAlgorithm Digest Algorithm to use for calculating the thumbprint. Default is
* "sha256".
*
* @see {@link https://www.rfc-editor.org/rfc/rfc7638 RFC7638}
*/

@@ -24,11 +14,6 @@ export declare function calculateJwkThumbprint(key: types.JWK | types.CryptoKey | types.KeyObject, digestAlgorithm?: 'sha256' | 'sha384' | 'sha512'): Promise<string>;

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/jwk/thumbprint'`.
*
* @param key Key to calculate the thumbprint for.
* @param digestAlgorithm Digest Algorithm to use for calculating the thumbprint. Default is
* "sha256".
*
* @see {@link https://www.rfc-editor.org/rfc/rfc9278 RFC9278}
*/
export declare function calculateJwkThumbprintUri(key: types.CryptoKey | types.KeyObject | types.JWK, digestAlgorithm?: 'sha256' | 'sha384' | 'sha512'): Promise<string>;

@@ -1,29 +0,20 @@

/**
* Verification using a JSON Web Key Set (JWKS) available locally
*
* @module
*/
import type * as types from '../types.d.ts';
/** The key resolution function returned by {@link createLocalJWKSet}. */
export interface LocalJWKSet {
(protectedHeader?: types.JWSHeaderParameters, token?: types.FlattenedJWSInput): Promise<types.CryptoKey>;
/** Returns a structured clone of the JSON Web Key Set this resolver was created with. */
jwks: () => types.JSONWebKeySet;
}
/**
* Returns a function that resolves a JWS JOSE Header to a public key object from a locally stored,
* or otherwise available, JSON Web Key Set.
* or otherwise available, JSON Web Key Set. Selection respects the header's "alg" (Algorithm) and
* "kid" (Key ID) as well as the JWK's "use" (Public Key Use) and "key_ops" (Key Operations).
* Exactly one key must match; if multiple keys match, the thrown `JWKSMultipleMatchingKeys` can be
* iterated.
*
* It uses the "alg" (JWS Algorithm) Header Parameter to determine the right JWK "kty" (Key Type),
* then proceeds to match the JWK "kid" (Key ID) with one found in the JWS Header Parameters (if
* there is one) while also respecting the JWK "use" (Public Key Use) and JWK "key_ops" (Key
* Operations) Parameters (if they are present on the JWK).
*
* Only a single public key must match the selection process. As shown in the example below when
* multiple keys get matched it is possible to opt-in to iterate over the matched keys and attempt
* verification in an iterative manner.
*
* > [!NOTE]\
* > The function's purpose is to resolve public keys used for verifying signatures and will not work
* > Note: The function's purpose is to resolve public keys used for verifying signatures and will not work
* > for public encryption keys.
*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/jwks/local'`.
*
* @param jwks JSON Web Key Set formatted object.
*/
export declare function createLocalJWKSet(jwks: types.JSONWebKeySet): (protectedHeader?: types.JWSHeaderParameters, token?: types.FlattenedJWSInput) => Promise<types.CryptoKey>;
export declare function createLocalJWKSet(jwks: types.JSONWebKeySet): LocalJWKSet;

@@ -1,6 +0,1 @@

/**
* Verification using a JSON Web Key Set (JWKS) available on an HTTP(S) URL
*
* @module
*/
import type * as types from '../types.d.ts';

@@ -11,90 +6,4 @@ /**

*
* > [!NOTE]\
* > Known caveat: Expect Type-related issues when passing the inputs through to fetch-like modules,
* > Note: Known caveat: Expect Type-related issues when passing the inputs through to fetch-like modules,
* > they hardly ever get their typings inline with actual fetch, you should `@ts-expect-error` them.
*
* import ky from 'ky'
*
* let logRequest!: (request: Request) => void
* let logResponse!: (request: Request, response: Response) => void
* let logRetry!: (request: Request, error: Error, retryCount: number) => void
*
* const JWKS = jose.createRemoteJWKSet(url, {
* [jose.customFetch]: (...args) =>
* ky(args[0], {
* ...args[1],
* hooks: {
* beforeRequest: [
* (request) => {
* logRequest(request)
* },
* ],
* beforeRetry: [
* ({ request, error, retryCount }) => {
* logRetry(request, error, retryCount)
* },
* ],
* afterResponse: [
* (request, _, response) => {
* logResponse(request, response)
* },
* ],
* },
* }),
* })
* ```
*
* import * as undici from 'undici'
*
* // see https://undici.nodejs.org/api/EnvHttpProxyAgent
* let envHttpProxyAgent = new undici.EnvHttpProxyAgent()
*
* // @ts-ignore
* const JWKS = jose.createRemoteJWKSet(url, {
* [jose.customFetch]: (...args) => {
* // @ts-ignore
* return undici.fetch(args[0], { ...args[1], dispatcher: envHttpProxyAgent }) // prettier-ignore
* },
* })
* ```
*
* import * as undici from 'undici'
*
* // see https://undici.nodejs.org/api/RetryAgent
* let retryAgent = new undici.RetryAgent(new undici.Agent(), {
* statusCodes: [],
* errorCodes: [
* 'ECONNRESET',
* 'ECONNREFUSED',
* 'ENOTFOUND',
* 'ENETDOWN',
* 'ENETUNREACH',
* 'EHOSTDOWN',
* 'UND_ERR_SOCKET',
* ],
* })
*
* // @ts-ignore
* const JWKS = jose.createRemoteJWKSet(url, {
* [jose.customFetch]: (...args) => {
* // @ts-ignore
* return undici.fetch(args[0], { ...args[1], dispatcher: retryAgent }) // prettier-ignore
* },
* })
* ```
*
* import * as undici from 'undici'
*
* // see https://undici.nodejs.org/api/MockAgent
* let mockAgent = new undici.MockAgent()
* mockAgent.disableNetConnect()
*
* // @ts-ignore
* const JWKS = jose.createRemoteJWKSet(url, {
* [jose.customFetch]: (...args) => {
* // @ts-ignore
* return undici.fetch(args[0], { ...args[1], dispatcher: mockAgent }) // prettier-ignore
* },
* })
* ```
*/

@@ -117,4 +26,3 @@ export declare const customFetch: unique symbol;

/**
* > [!WARNING]\
* > This option has security implications that must be understood, assessed for applicability, and
* > Warning: This option has security implications that must be understood, assessed for applicability, and
* > accepted before use. It is critical that the JSON Web Key Set cache only be writable by your own

@@ -124,45 +32,5 @@ * > code.

* This option is intended for cloud computing runtimes that cannot keep an in memory cache between
* their code's invocations. Use in runtimes where an in memory cache between requests is available
* is not desirable.
*
* When passed to {@link jwks/remote.createRemoteJWKSet createRemoteJWKSet} this allows the passed in
* object to:
*
* - Serve as an initial value for the JSON Web Key Set that the module would otherwise need to
* trigger an HTTP request for
* - Have the JSON Web Key Set the function optionally ended up triggering an HTTP request for
* assigned to it as properties
*
* The intended use pattern is:
*
* - Before verifying with {@link jwks/remote.createRemoteJWKSet createRemoteJWKSet} you pull the
* previously cached object from a low-latency key-value store offered by the cloud computing
* runtime it is executed on;
* - Default to an empty object `{}` instead when there's no previously cached value;
* - Pass it in as {@link RemoteJWKSetOptions[jwksCache]};
* - Afterwards, update the key-value storage if the {@link ExportedJWKSCache.uat `uat`} property of
* the object has changed.
*
* // Prerequisites
* let url!: URL
* let jwt!: string
* let getPreviouslyCachedJWKS!: () => Promise<jose.ExportedJWKSCache>
* let storeNewJWKScache!: (cache: jose.ExportedJWKSCache) => Promise<void>
*
* // Load JSON Web Key Set cache
* const jwksCache: jose.JWKSCacheInput = (await getPreviouslyCachedJWKS()) || {}
* const { uat } = jwksCache
*
* const JWKS = jose.createRemoteJWKSet(url, {
* [jose.jwksCache]: jwksCache,
* })
*
* // Use JSON Web Key Set cache
* await jose.jwtVerify(jwt, JWKS)
*
* if (uat !== jwksCache.uat) {
* // Update JSON Web Key Set cache
* await storeNewJWKScache(jwksCache)
* }
* ```
* their code's invocations. The supplied writable object seeds the resolver's cache and is updated
* with `jwks` and `uat` after a successful fetch; persist it whenever `uat` changes. Using this in
* runtimes that can keep an in-memory cache between requests is not desirable.
*/

@@ -203,2 +71,25 @@ export declare const jwksCache: unique symbol;

export type JWKSCacheInput = ExportedJWKSCache | Record<string, never>;
/** The key resolution function returned by {@link createRemoteJWKSet}. */
export interface RemoteJWKSet {
(protectedHeader?: types.JWSHeaderParameters, token?: types.FlattenedJWSInput): Promise<types.CryptoKey>;
/** Whether the cooldown window following the last successful fetch is still in effect. */
readonly coolingDown: boolean;
/**
* Whether the currently cached JSON Web Key Set is within its
* {@link RemoteJWKSetOptions.cacheMaxAge}.
*/
readonly fresh: boolean;
/** Whether a JSON Web Key Set fetch is currently in flight. */
readonly reloading: boolean;
/**
* Triggers a JSON Web Key Set fetch, bypassing
* {@link RemoteJWKSetOptions.cooldownDuration the cooldown}.
*/
reload: () => Promise<void>;
/**
* The currently cached JSON Web Key Set, or `undefined` when none has been fetched or seeded via
* {@link jwksCache} yet.
*/
jwks: () => types.JSONWebKeySet | undefined;
}
/**

@@ -208,35 +99,13 @@ * Returns a function that resolves a JWS JOSE Header to a public key object downloaded from a

* jwks_uri. The JSON Web Key Set is fetched when no key matches the selection process but only as
* frequently as the `cooldownDuration` option allows to prevent abuse.
* frequently as the `cooldownDuration` option allows to prevent abuse. Selection respects the
* header's "alg" (Algorithm) and "kid" (Key ID) as well as the JWK's "use" (Public Key Use) and
* "key_ops" (Key Operations). Exactly one key must match; if multiple keys match, the thrown
* `JWKSMultipleMatchingKeys` can be iterated.
*
* It uses the "alg" (JWS Algorithm) Header Parameter to determine the right JWK "kty" (Key Type),
* then proceeds to match the JWK "kid" (Key ID) with one found in the JWS Header Parameters (if
* there is one) while also respecting the JWK "use" (Public Key Use) and JWK "key_ops" (Key
* Operations) Parameters (if they are present on the JWK).
*
* Only a single public key must match the selection process. As shown in the example below when
* multiple keys get matched it is possible to opt-in to iterate over the matched keys and attempt
* verification in an iterative manner.
*
* > [!NOTE]\
* > The function's purpose is to resolve public keys used for verifying signatures and will not work
* > Note: The function's purpose is to resolve public keys used for verifying signatures and will not work
* > for public encryption keys.
*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/jwks/remote'`.
*
* @param url URL to fetch the JSON Web Key Set from.
* @param options Options for the remote JSON Web Key Set.
*/
export declare function createRemoteJWKSet(url: URL, options?: RemoteJWKSetOptions): {
(protectedHeader?: types.JWSHeaderParameters, token?: types.FlattenedJWSInput): Promise<types.CryptoKey>;
/** @ignore */
coolingDown: boolean;
/** @ignore */
fresh: boolean;
/** @ignore */
reloading: boolean;
/** @ignore */
reload: () => Promise<void>;
/** @ignore */
jwks: () => types.JSONWebKeySet | undefined;
};
export declare function createRemoteJWKSet(url: URL, options?: RemoteJWKSetOptions): RemoteJWKSet;

@@ -1,14 +0,3 @@

/**
* Signing JSON Web Signature (JWS) in Compact Serialization
*
* @module
*/
import type * as types from '../../types.d.ts';
/**
* The CompactSign class is used to build and sign Compact JWS strings.
*
* This class is exported (as a named export) from the main `'jose'` module entry point as well as
* from its subpath export `'jose/jws/compact/sign'`.
*
*/
/** The CompactSign class is used to build and sign Compact JWS strings. */
export declare class CompactSign {

@@ -35,3 +24,3 @@ #private;

*/
sign(key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: types.SignOptions): Promise<string>;
sign(key: types.KeyInput, options?: types.SignOptions): Promise<string>;
}

@@ -1,6 +0,1 @@

/**
* Verifying JSON Web Signature (JWS) in Compact Serialization
*
* @module
*/
import type * as types from '../../types.d.ts';

@@ -10,6 +5,4 @@ /**

* verified at the time of this function call.
*
* @see {@link jwks/remote.createRemoteJWKSet createRemoteJWKSet} to verify using a remote JSON Web Key Set.
*/
export interface CompactVerifyGetKey extends types.GenericGetKeyFunction<types.CompactJWSHeaderParameters, types.FlattenedJWSInput, types.CryptoKey | types.KeyObject | types.JWK | Uint8Array> {
export interface CompactVerifyGetKey<KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array> extends types.GetKeyFunction<types.CompactJWSHeaderParameters, types.FlattenedJWSInput, KeyType | types.KeyObject | types.JWK> {
}

@@ -19,5 +12,2 @@ /**

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/jws/compact/verify'`.
*
* @param jws Compact JWS.

@@ -28,4 +18,7 @@ * @param key Key to verify the JWS with. See

*/
export declare function compactVerify(jws: string | Uint8Array, key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: types.VerifyOptions): Promise<types.CompactVerifyResult>;
export declare function compactVerify(jws: string | Uint8Array, key: types.KeyInput, options?: types.VerifyOptions): Promise<types.CompactVerifyResult>;
/**
* Verifies the signature and format of and afterwards decodes the Compact JWS, resolving the key
* dynamically. The result additionally carries the {@link types.ResolvedKey.key resolved key}.
*
* @param jws Compact JWS.

@@ -36,2 +29,13 @@ * @param getKey Function resolving a key to verify the JWS with. See

*/
export declare function compactVerify(jws: string | Uint8Array, getKey: CompactVerifyGetKey, options?: types.VerifyOptions): Promise<types.CompactVerifyResult & types.ResolvedKey>;
export declare function compactVerify<KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array>(jws: string | Uint8Array, getKey: CompactVerifyGetKey<KeyType>, options?: types.VerifyOptions): Promise<types.CompactVerifyResult & types.ResolvedKey<KeyType>>;
/**
* Accepts either form of the `key` argument. Use this overload when forwarding a value that may be
* either a key or a key resolution function; `key` is present on the result only when a resolution
* function was used.
*
* @param jws Compact JWS.
* @param key Key, or function resolving a key, to verify the JWS with. See
* {@link https://github.com/panva/jose/issues/210#jws-alg Algorithm Key Requirements}.
* @param options JWS Verify options.
*/
export declare function compactVerify(jws: string | Uint8Array, key: types.KeyInput | CompactVerifyGetKey, options?: types.VerifyOptions): Promise<types.CompactVerifyResult & Partial<types.ResolvedKey>>;

@@ -1,14 +0,3 @@

/**
* Signing JSON Web Signature (JWS) in Flattened JSON Serialization
*
* @module
*/
import type * as types from '../../types.d.ts';
/**
* The FlattenedSign class is used to build and sign Flattened JWS objects.
*
* This class is exported (as a named export) from the main `'jose'` module entry point as well as
* from its subpath export `'jose/jws/flattened/sign'`.
*
*/
/** The FlattenedSign class is used to build and sign Flattened JWS objects. */
export declare class FlattenedSign {

@@ -41,3 +30,3 @@ #private;

*/
sign(key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: types.SignOptions): Promise<types.FlattenedJWS>;
sign(key: types.KeyInput, options?: types.SignOptions): Promise<types.FlattenedJWS>;
}

@@ -1,6 +0,1 @@

/**
* Verifying JSON Web Signature (JWS) in Flattened JSON Serialization
*
* @module
*/
import type * as types from '../../types.d.ts';

@@ -10,6 +5,4 @@ /**

* verified at the time of this function call.
*
* @see {@link jwks/remote.createRemoteJWKSet createRemoteJWKSet} to verify using a remote JSON Web Key Set.
*/
export interface FlattenedVerifyGetKey extends types.GenericGetKeyFunction<types.JWSHeaderParameters | undefined, types.FlattenedJWSInput, types.CryptoKey | types.KeyObject | types.JWK | Uint8Array> {
export interface FlattenedVerifyGetKey<KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array> extends types.GetKeyFunction<types.JWSHeaderParameters, types.FlattenedJWSInput, KeyType | types.KeyObject | types.JWK> {
}

@@ -19,5 +12,2 @@ /**

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/jws/flattened/verify'`.
*
* @param jws Flattened JWS.

@@ -28,4 +18,7 @@ * @param key Key to verify the JWS with. See

*/
export declare function flattenedVerify(jws: types.FlattenedJWSInput, key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: types.VerifyOptions): Promise<types.FlattenedVerifyResult>;
export declare function flattenedVerify(jws: types.FlattenedJWSInput, key: types.KeyInput, options?: types.VerifyOptions): Promise<types.FlattenedVerifyResult>;
/**
* Verifies the signature and format of and afterwards decodes the Flattened JWS, resolving the key
* dynamically. The result additionally carries the {@link types.ResolvedKey.key resolved key}.
*
* @param jws Flattened JWS.

@@ -36,2 +29,13 @@ * @param getKey Function resolving a key to verify the JWS with. See

*/
export declare function flattenedVerify(jws: types.FlattenedJWSInput, getKey: FlattenedVerifyGetKey, options?: types.VerifyOptions): Promise<types.FlattenedVerifyResult & types.ResolvedKey>;
export declare function flattenedVerify<KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array>(jws: types.FlattenedJWSInput, getKey: FlattenedVerifyGetKey<KeyType>, options?: types.VerifyOptions): Promise<types.FlattenedVerifyResult & types.ResolvedKey<KeyType>>;
/**
* Accepts either form of the `key` argument. Use this overload when forwarding a value that may be
* either a key or a key resolution function; `key` is present on the result only when a resolution
* function was used.
*
* @param jws Flattened JWS.
* @param key Key, or function resolving a key, to verify the JWS with. See
* {@link https://github.com/panva/jose/issues/210#jws-alg Algorithm Key Requirements}.
* @param options JWS Verify options.
*/
export declare function flattenedVerify(jws: types.FlattenedJWSInput, key: types.KeyInput | FlattenedVerifyGetKey, options?: types.VerifyOptions): Promise<types.FlattenedVerifyResult & Partial<types.ResolvedKey>>;

@@ -1,6 +0,1 @@

/**
* Signing JSON Web Signature (JWS) in General JSON Serialization
*
* @module
*/
import type * as types from '../../types.d.ts';

@@ -21,16 +16,20 @@ /** Used to build General JWS object's individual signatures. */

setUnprotectedHeader(unprotectedHeader: types.JWSHeaderParameters): Signature;
/** A shorthand for calling addSignature() on the enclosing {@link GeneralSign} instance */
addSignature(...args: Parameters<GeneralSign['addSignature']>): Signature;
/** A shorthand for calling encrypt() on the enclosing {@link GeneralSign} instance */
sign(...args: Parameters<GeneralSign['sign']>): Promise<types.GeneralJWS>;
/**
* A shorthand for calling {@link GeneralSign.addSignature addSignature()} on the enclosing
* {@link GeneralSign} instance.
*
* @param key Private Key or Secret to sign the individual JWS signature with. See
* {@link https://github.com/panva/jose/issues/210#jws-alg Algorithm Key Requirements}.
* @param options JWS Sign options.
*/
addSignature(key: types.KeyInput, options?: types.SignOptions): Signature;
/**
* A shorthand for calling {@link GeneralSign.sign sign()} on the enclosing {@link GeneralSign}
* instance. Takes no arguments — each signature's key is supplied to {@link addSignature}.
*/
sign(): Promise<types.GeneralJWS>;
/** Returns the enclosing {@link GeneralSign} instance */
done(): GeneralSign;
}
/**
* The GeneralSign class is used to build and sign General JWS objects.
*
* This class is exported (as a named export) from the main `'jose'` module entry point as well as
* from its subpath export `'jose/jws/general/sign'`.
*
*/
/** The GeneralSign class is used to build and sign General JWS objects. */
export declare class GeneralSign {

@@ -51,5 +50,5 @@ #private;

*/
addSignature(key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: types.SignOptions): Signature;
addSignature(key: types.KeyInput, options?: types.SignOptions): Signature;
/** Signs and resolves the value of the General JWS object. */
sign(): Promise<types.GeneralJWS>;
}

@@ -1,6 +0,1 @@

/**
* Verifying JSON Web Signature (JWS) in General JSON Serialization
*
* @module
*/
import type * as types from '../../types.d.ts';

@@ -10,6 +5,4 @@ /**

* verified at the time of this function call.
*
* @see {@link jwks/remote.createRemoteJWKSet createRemoteJWKSet} to verify using a remote JSON Web Key Set.
*/
export interface GeneralVerifyGetKey extends types.GenericGetKeyFunction<types.JWSHeaderParameters, types.FlattenedJWSInput, types.CryptoKey | types.KeyObject | types.JWK | Uint8Array> {
export interface GeneralVerifyGetKey<KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array> extends types.GetKeyFunction<types.JWSHeaderParameters, types.FlattenedJWSInput, KeyType | types.KeyObject | types.JWK> {
}

@@ -19,7 +12,3 @@ /**

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/jws/general/verify'`.
*
* > [!NOTE]\
* > The function iterates over the `signatures` array in the General JWS and returns the verification
* > Note: The function iterates over the `signatures` array in the General JWS and returns the verification
* > result of the first signature entry that can be successfully verified. The result only contains

@@ -36,4 +25,7 @@ * > the payload, protected header, and unprotected header of that successfully verified signature

*/
export declare function generalVerify(jws: types.GeneralJWSInput, key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: types.VerifyOptions): Promise<types.GeneralVerifyResult>;
export declare function generalVerify(jws: types.GeneralJWSInput, key: types.KeyInput, options?: types.VerifyOptions): Promise<types.GeneralVerifyResult>;
/**
* Verifies the signature and format of and afterwards decodes the General JWS, resolving the key
* dynamically. The result additionally carries the {@link types.ResolvedKey.key resolved key}.
*
* @param jws General JWS.

@@ -44,2 +36,13 @@ * @param getKey Function resolving a key to verify the JWS with. See

*/
export declare function generalVerify(jws: types.GeneralJWSInput, getKey: GeneralVerifyGetKey, options?: types.VerifyOptions): Promise<types.GeneralVerifyResult & types.ResolvedKey>;
export declare function generalVerify<KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array>(jws: types.GeneralJWSInput, getKey: GeneralVerifyGetKey<KeyType>, options?: types.VerifyOptions): Promise<types.GeneralVerifyResult & types.ResolvedKey<KeyType>>;
/**
* Accepts either form of the `key` argument. Use this overload when forwarding a value that may be
* either a key or a key resolution function; `key` is present on the result only when a resolution
* function was used.
*
* @param jws General JWS.
* @param key Key, or function resolving a key, to verify the JWS with. See
* {@link https://github.com/panva/jose/issues/210#jws-alg Algorithm Key Requirements}.
* @param options JWS Verify options.
*/
export declare function generalVerify(jws: types.GeneralJWSInput, key: types.KeyInput | GeneralVerifyGetKey, options?: types.VerifyOptions): Promise<types.GeneralVerifyResult & Partial<types.ResolvedKey>>;

@@ -1,6 +0,1 @@

/**
* JSON Web Token (JWT) Decryption (JWT is in JWE format)
*
* @module
*/
import type * as types from '../types.d.ts';

@@ -14,3 +9,3 @@ /** Combination of JWE Decryption options and JWT Claims Set verification options. */

*/
export interface JWTDecryptGetKey extends types.GetKeyFunction<types.CompactJWEHeaderParameters, types.FlattenedJWE> {
export interface JWTDecryptGetKey<KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array> extends types.GetKeyFunction<types.CompactJWEHeaderParameters, types.FlattenedJWE, KeyType | types.KeyObject | types.JWK> {
}

@@ -21,5 +16,2 @@ /**

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/jwt/decrypt'`.
*
* @param jwt JSON Web Token value (encoded as JWE).

@@ -30,4 +22,7 @@ * @param key Private Key or Secret to decrypt and verify the JWT with. See

*/
export declare function jwtDecrypt<PayloadType = types.JWTPayload>(jwt: string | Uint8Array, key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: JWTDecryptOptions): Promise<types.JWTDecryptResult<PayloadType>>;
export declare function jwtDecrypt<PayloadType = types.JWTPayload>(jwt: string | Uint8Array, key: types.KeyInput, options?: JWTDecryptOptions): Promise<types.JWTDecryptResult<PayloadType>>;
/**
* Decrypts a JWT and validates its JWT Claims Set, resolving the key dynamically. The result
* additionally carries the {@link types.ResolvedKey.key resolved key}.
*
* @param jwt JSON Web Token value (encoded as JWE).

@@ -38,2 +33,13 @@ * @param getKey Function resolving Private Key or Secret to decrypt and verify the JWT with. See

*/
export declare function jwtDecrypt<PayloadType = types.JWTPayload>(jwt: string | Uint8Array, getKey: JWTDecryptGetKey, options?: JWTDecryptOptions): Promise<types.JWTDecryptResult<PayloadType> & types.ResolvedKey>;
export declare function jwtDecrypt<PayloadType = types.JWTPayload, KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array>(jwt: string | Uint8Array, getKey: JWTDecryptGetKey<KeyType>, options?: JWTDecryptOptions): Promise<types.JWTDecryptResult<PayloadType> & types.ResolvedKey<KeyType>>;
/**
* Accepts either form of the `key` argument. Use this overload when forwarding a value that may be
* either a key or a key resolution function; `key` is present on the result only when a resolution
* function was used.
*
* @param jwt JSON Web Token value (encoded as JWE).
* @param key Private Key or Secret, or a function resolving one, to decrypt and verify the JWT
* with. See {@link https://github.com/panva/jose/issues/210#jwe-alg Algorithm Key Requirements}.
* @param options JWT Decryption and JWT Claims Set validation options.
*/
export declare function jwtDecrypt<PayloadType = types.JWTPayload>(jwt: string | Uint8Array, key: types.KeyInput | JWTDecryptGetKey, options?: JWTDecryptOptions): Promise<types.JWTDecryptResult<PayloadType> & Partial<types.ResolvedKey>>;

@@ -1,14 +0,3 @@

/**
* JSON Web Token (JWT) Encryption (JWT is in JWE format)
*
* @module
*/
import type * as types from '../types.d.ts';
/**
* The EncryptJWT class is used to build and encrypt Compact JWE formatted JSON Web Tokens.
*
* This class is exported (as a named export) from the main `'jose'` module entry point as well as
* from its subpath export `'jose/jwt/encrypt'`.
*
*/
/** The EncryptJWT class is used to build and encrypt Compact JWE formatted JSON Web Tokens. */
export declare class EncryptJWT implements types.ProduceJWT {

@@ -37,7 +26,6 @@ #private;

/**
* Sets the JWE Key Management parameters to be used when encrypting.
* Sets the JWE Key Management parameters to be used when encrypting. For ECDH based algorithms,
* use this method to set the "apu" (Agreement PartyUInfo) or "apv" (Agreement PartyVInfo)
* parameters.
*
* (ECDH-ES) Use of this method is needed for ECDH based algorithms to set the "apu" (Agreement
* PartyUInfo) or "apv" (Agreement PartyVInfo) parameters.
*
* @param parameters JWE Key Management parameters.

@@ -48,3 +36,3 @@ */

* Sets a content encryption key to use, by default a random suitable one is generated for the JWE
* enc" (Encryption Algorithm) Header Parameter.
* "enc" (Encryption Algorithm) Header Parameter.
*

@@ -59,3 +47,3 @@ * @deprecated You should not use this method. It is only really intended for test and vector

* Sets the JWE Initialization Vector to use for content encryption, by default a random suitable
* one is generated for the JWE enc" (Encryption Algorithm) Header Parameter.
* one is generated for the JWE "enc" (Encryption Algorithm) Header Parameter.
*

@@ -68,19 +56,7 @@ * @deprecated You should not use this method. It is only really intended for test and vector

setInitializationVector(iv: Uint8Array): this;
/**
* Replicates the "iss" (Issuer) Claim as a JWE Protected Header Parameter.
*
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-5.3 RFC7519#section-5.3}
*/
/** Replicates the "iss" (Issuer) Claim as a JWE Protected Header Parameter. */
replicateIssuerAsHeader(): this;
/**
* Replicates the "sub" (Subject) Claim as a JWE Protected Header Parameter.
*
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-5.3 RFC7519#section-5.3}
*/
/** Replicates the "sub" (Subject) Claim as a JWE Protected Header Parameter. */
replicateSubjectAsHeader(): this;
/**
* Replicates the "aud" (Audience) Claim as a JWE Protected Header Parameter.
*
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-5.3 RFC7519#section-5.3}
*/
/** Replicates the "aud" (Audience) Claim as a JWE Protected Header Parameter. */
replicateAudienceAsHeader(): this;

@@ -94,3 +70,3 @@ /**

*/
encrypt(key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: types.EncryptOptions): Promise<string>;
encrypt(key: types.KeyInput, options?: types.EncryptOptions): Promise<string>;
}

@@ -1,14 +0,3 @@

/**
* JSON Web Token (JWT) Signing (JWT is in JWS format)
*
* @module
*/
import type * as types from '../types.d.ts';
/**
* The SignJWT class is used to build and sign Compact JWS formatted JSON Web Tokens.
*
* This class is exported (as a named export) from the main `'jose'` module entry point as well as
* from its subpath export `'jose/jwt/sign'`.
*
*/
/** The SignJWT class is used to build and sign Compact JWS formatted JSON Web Tokens. */
export declare class SignJWT implements types.ProduceJWT {

@@ -42,3 +31,3 @@ #private;

*/
sign(key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: types.SignOptions): Promise<string>;
sign(key: types.KeyInput, options?: types.SignOptions): Promise<string>;
}

@@ -1,19 +0,10 @@

/**
* Unsecured (unsigned & unencrypted) JSON Web Tokens (JWT)
*
* @module
*/
import type * as types from '../types.d.ts';
/** Result of decoding an Unsecured JWT. */
export interface UnsecuredResult<PayloadType = types.JWTPayload> {
payload: PayloadType & types.JWTPayload;
/** JWT Claims Set. */
payload: PayloadType & types.JWTPayload & ([PayloadType] extends [object] ? unknown : unknown extends PayloadType ? unknown : never);
/** The decoded JOSE Header; always `{ "alg": "none" }` for an Unsecured JWT. */
header: types.JWSHeaderParameters;
}
/**
* The UnsecuredJWT class is a utility for dealing with `{ "alg": "none" }` Unsecured JWTs.
*
* This class is exported (as a named export) from the main `'jose'` module entry point as well as
* from its subpath export `'jose/jwt/unsecured'`.
*
*/
/** The UnsecuredJWT class is a utility for dealing with `{ "alg": "none" }` Unsecured JWTs. */
export declare class UnsecuredJWT implements types.ProduceJWT {

@@ -20,0 +11,0 @@ #private;

@@ -1,6 +0,1 @@

/**
* JSON Web Token (JWT) Verification (JWT is in JWS format)
*
* @module
*/
import type * as types from '../types.d.ts';

@@ -13,6 +8,4 @@ /** Combination of JWS Verification options and JWT Claims Set verification options. */

* the time of this function call.
*
* @see {@link jwks/remote.createRemoteJWKSet createRemoteJWKSet} to verify using a remote JSON Web Key Set.
*/
export interface JWTVerifyGetKey extends types.GenericGetKeyFunction<types.JWTHeaderParameters, types.FlattenedJWSInput, types.CryptoKey | types.KeyObject | types.JWK | Uint8Array> {
export interface JWTVerifyGetKey<KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array> extends types.GetKeyFunction<types.CompactJWSHeaderParameters, types.FlattenedJWSInput, KeyType | types.KeyObject | types.JWK> {
}

@@ -23,5 +16,2 @@ /**

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/jwt/verify'`.
*
* @param jwt JSON Web Token value (encoded as JWS).

@@ -32,3 +22,3 @@ * @param key Key to verify the JWT with. See

*/
export declare function jwtVerify<PayloadType = types.JWTPayload>(jwt: string | Uint8Array, key: types.CryptoKey | types.KeyObject | types.JWK | Uint8Array, options?: JWTVerifyOptions): Promise<types.JWTVerifyResult<PayloadType>>;
export declare function jwtVerify<PayloadType = types.JWTPayload>(jwt: string | Uint8Array, key: types.KeyInput, options?: JWTVerifyOptions): Promise<types.JWTVerifyResult<PayloadType>>;
/**

@@ -40,2 +30,13 @@ * @param jwt JSON Web Token value (encoded as JWS).

*/
export declare function jwtVerify<PayloadType = types.JWTPayload>(jwt: string | Uint8Array, getKey: JWTVerifyGetKey, options?: JWTVerifyOptions): Promise<types.JWTVerifyResult<PayloadType> & types.ResolvedKey>;
export declare function jwtVerify<PayloadType = types.JWTPayload, KeyType extends types.CryptoKey | Uint8Array = types.CryptoKey | Uint8Array>(jwt: string | Uint8Array, getKey: JWTVerifyGetKey<KeyType>, options?: JWTVerifyOptions): Promise<types.JWTVerifyResult<PayloadType> & types.ResolvedKey<KeyType>>;
/**
* Accepts either form of the `key` argument. Use this overload when forwarding a value that may be
* either a key or a key resolution function; `key` is present on the result only when a resolution
* function was used.
*
* @param jwt JSON Web Token value (encoded as JWS).
* @param key Key, or function resolving a key, to verify the JWT with. See
* {@link https://github.com/panva/jose/issues/210#jws-alg Algorithm Key Requirements}.
* @param options JWT Decryption and JWT Claims Set validation options.
*/
export declare function jwtVerify<PayloadType = types.JWTPayload>(jwt: string | Uint8Array, key: types.KeyInput | JWTVerifyGetKey, options?: JWTVerifyOptions): Promise<types.JWTVerifyResult<PayloadType> & Partial<types.ResolvedKey>>;

@@ -1,6 +0,1 @@

/**
* Cryptographic key export functions
*
* @module
*/
import type * as types from '../types.d.ts';

@@ -10,5 +5,2 @@ /**

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/key/export'`.
*
* @param key Key to export to a PEM-encoded SPKI string format.

@@ -20,5 +12,2 @@ */

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/key/export'`.
*
* @param key Key to export to a PEM-encoded PKCS8 string format.

@@ -30,7 +19,4 @@ */

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/key/export'`.
*
* @param key Key to export as JWK.
*/
export declare function exportJWK(key: types.CryptoKey | types.KeyObject | Uint8Array): Promise<types.JWK>;

@@ -0,7 +1,7 @@

import type * as types from '../types.d.ts';
/**
* Asymmetric key generation
*
* @module
* JWA Algorithm Identifiers that {@link generateKeyPair} is able to generate a key pair for, subject
* to runtime support.
*/
import type * as types from '../types.d.ts';
export type GenerateKeyPairAlgorithm = 'PS256' | 'PS384' | 'PS512' | 'RS256' | 'RS384' | 'RS512' | 'RSA-OAEP' | 'RSA-OAEP-256' | 'RSA-OAEP-384' | 'RSA-OAEP-512' | 'ES256' | 'ES384' | 'ES512' | 'Ed25519' | 'EdDSA' | 'ML-DSA-44' | 'ML-DSA-65' | 'ML-DSA-87' | 'ECDH-ES' | 'ECDH-ES+A128KW' | 'ECDH-ES+A192KW' | 'ECDH-ES+A256KW' | (string & {});
/** Asymmetric key pair generation function result. */

@@ -26,6 +26,3 @@ export interface GenerateKeyPairResult {

modulusLength?: number;
/**
* The value to use as {@link !SubtleCrypto.generateKey} `extractable` argument. Default is false.
*
*/
/** The value to use as {@link !SubtleCrypto.generateKey} `extractable` argument. Default is false. */
extractable?: boolean;

@@ -37,9 +34,5 @@ }

*
* > [!NOTE]\
* > The `privateKey` is generated with `extractable` set to `false` by default. See
* > Note: The `privateKey` is generated with `extractable` set to `false` by default. See
* > {@link GenerateKeyPairOptions.extractable} to generate an extractable `privateKey`.
*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/generate/keypair'`.
*
* @param alg JWA Algorithm Identifier to be used with the generated key pair. See

@@ -49,2 +42,2 @@ * {@link https://github.com/panva/jose/issues/210 Algorithm Key Requirements}.

*/
export declare function generateKeyPair(alg: string, options?: GenerateKeyPairOptions): Promise<GenerateKeyPairResult>;
export declare function generateKeyPair(alg: GenerateKeyPairAlgorithm, options?: GenerateKeyPairOptions): Promise<GenerateKeyPairResult>;

@@ -0,7 +1,15 @@

import type * as types from '../types.d.ts';
/**
* Symmetric key generation
*
* @module
* JWA Algorithm Identifiers that {@link generateSecret} is able to generate a secret for, subject to
* runtime support.
*/
import type * as types from '../types.d.ts';
export type GenerateSecretAlgorithm = 'HS256' | 'HS384' | 'HS512' | 'A128CBC-HS256' | 'A192CBC-HS384' | 'A256CBC-HS512' | 'A128KW' | 'A192KW' | 'A256KW' | 'A128GCMKW' | 'A192GCMKW' | 'A256GCMKW' | 'A128GCM' | 'A192GCM' | 'A256GCM' | (string & {});
/**
* Resolves what {@link generateSecret} returns for a given JWA Algorithm Identifier. The
* AES_CBC_HMAC_SHA2 content encryption algorithms have no {@link !CryptoKey} representation, so they
* yield a {@link !Uint8Array}; every other supported identifier yields a
* {@link types.CryptoKey CryptoKey}. When the identifier is not statically known this resolves to
* their union.
*/
export type GeneratedSecret<Alg extends string> = Alg extends 'A128CBC-HS256' | 'A192CBC-HS384' | 'A256CBC-HS512' ? Uint8Array : string extends Alg ? types.CryptoKey | Uint8Array : types.CryptoKey;
/** Secret generation function options. */

@@ -12,4 +20,3 @@ export interface GenerateSecretOptions {

*
* > [!NOTE]\
* > Because A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 secrets cannot be represented as
* > Note: Because A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 secrets cannot be represented as
* > {@link !CryptoKey} this option has no effect for them.

@@ -22,12 +29,7 @@ */

*
* > [!NOTE]\
* > The secret key is generated with `extractable` set to `false` by default.
* > Note: The secret key is generated with `extractable` set to `false` by default.
*
* > [!NOTE]\
* > Because A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 secrets cannot be represented as
* > Note: Because A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 secrets cannot be represented as
* > {@link !CryptoKey} this method yields a {@link !Uint8Array} for them instead.
*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/generate/secret'`.
*
* @param alg JWA Algorithm Identifier to be used with the generated secret. See

@@ -37,2 +39,2 @@ * {@link https://github.com/panva/jose/issues/210 Algorithm Key Requirements}.

*/
export declare function generateSecret(alg: string, options?: GenerateSecretOptions): Promise<types.CryptoKey | Uint8Array>;
export declare function generateSecret<Alg extends GenerateSecretAlgorithm>(alg: Alg, options?: GenerateSecretOptions): Promise<GeneratedSecret<Alg>>;

@@ -0,7 +1,14 @@

import type * as types from '../types.d.ts';
/**
* Cryptographic key import functions
*
* @module
* Resolves what {@link importJWK} returns for a given JWK type. The "kty" (Key Type) Parameter fully
* determines the outcome at runtime: `"oct"` yields a {@link !Uint8Array} secret, every other
* supported key type yields a {@link types.CryptoKey CryptoKey}. When "kty" is not statically known
* — the usual case for a JWK parsed from JSON, or for a value typed as {@link types.JWK JWK} — this
* resolves to their union.
*/
import type * as types from '../types.d.ts';
export type ImportedJWK<JWKType extends types.JWK> = JWKType extends {
kty: 'oct';
} ? Uint8Array : JWKType extends {
kty: 'AKP' | 'EC' | 'OKP' | 'RSA';
} ? types.CryptoKey : types.CryptoKey | Uint8Array;
/** Key Import Function options. */

@@ -18,10 +25,6 @@ export interface KeyImportOptions {

*
* > [!NOTE]\
* > The OID id-RSASSA-PSS (1.2.840.113549.1.1.10) is not supported in
* > Note: The OID id-RSASSA-PSS (1.2.840.113549.1.1.10) is not supported in
* > {@link https://w3c.github.io/webcrypto/ Web Cryptography API}, use the OID rsaEncryption
* > (1.2.840.113549.1.1.1) instead for all RSA algorithms.
*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/key/import'`.
*
* @param spki PEM-encoded SPKI string

@@ -35,10 +38,6 @@ * @param alg JSON Web Algorithm identifier to be used with the imported key. See

*
* > [!NOTE]\
* > The OID id-RSASSA-PSS (1.2.840.113549.1.1.10) is not supported in
* > Note: The OID id-RSASSA-PSS (1.2.840.113549.1.1.10) is not supported in
* > {@link https://w3c.github.io/webcrypto/ Web Cryptography API}, use the OID rsaEncryption
* > (1.2.840.113549.1.1.1) instead for all RSA algorithms.
*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/key/import'`.
*
* @param x509 X.509 certificate string

@@ -52,10 +51,6 @@ * @param alg JSON Web Algorithm identifier to be used with the imported key. See

*
* > [!NOTE]\
* > The OID id-RSASSA-PSS (1.2.840.113549.1.1.10) is not supported in
* > Note: The OID id-RSASSA-PSS (1.2.840.113549.1.1.10) is not supported in
* > {@link https://w3c.github.io/webcrypto/ Web Cryptography API}, use the OID rsaEncryption
* > (1.2.840.113549.1.1.1) instead for all RSA algorithms.
*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/key/import'`.
*
* @param pkcs8 PEM-encoded PKCS#8 string

@@ -70,13 +65,8 @@ * @param alg JSON Web Algorithm identifier to be used with the imported key. See

*
* > [!NOTE]\
* > The JSON Web Key parameters "use", "key_ops", and "ext" are also used in the {@link !CryptoKey}
* > import process.
* > Note: The JSON Web Key parameters "key_ops" and "ext" are also used in the {@link !CryptoKey} import
* > process.
*
* > [!NOTE]\
* > Symmetric JSON Web Keys (i.e. `kty: "oct"`) yield back an {@link !Uint8Array} instead of a
* > Note: Symmetric JSON Web Keys (i.e. `kty: "oct"`) yield back an {@link !Uint8Array} instead of a
* > {@link !CryptoKey}.
*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/key/import'`.
*
* @param jwk JSON Web Key.

@@ -87,2 +77,2 @@ * @param alg JSON Web Algorithm identifier to be used with the imported key. Default is the "alg"

*/
export declare function importJWK(jwk: types.JWK, alg?: string, options?: KeyImportOptions): Promise<types.CryptoKey | Uint8Array>;
export declare function importJWK<JWKType extends types.JWK>(jwk: JWKType, alg?: string, options?: KeyImportOptions): Promise<ImportedJWK<JWKType>>;

@@ -1,11 +0,77 @@

/** Generic JSON Web Key Parameters. */
export interface JWKParameters {
/**
* JWS "alg" (Algorithm) Header Parameter values supported by this module. Availability of a given
* identifier additionally depends on the runtime.
*/
export type JWSAlgorithm =
| 'HS256'
| 'HS384'
| 'HS512'
| 'RS256'
| 'RS384'
| 'RS512'
| 'PS256'
| 'PS384'
| 'PS512'
| 'ES256'
| 'ES384'
| 'ES512'
| 'EdDSA'
| 'Ed25519'
| 'ML-DSA-44'
| 'ML-DSA-65'
| 'ML-DSA-87'
| (string & {})
/**
* JWE "alg" (Algorithm) Header Parameter values supported by this module. Availability of a given
* identifier additionally depends on the runtime.
*/
export type JWEKeyManagementAlgorithm =
| 'dir'
| 'A128KW'
| 'A192KW'
| 'A256KW'
| 'A128GCMKW'
| 'A192GCMKW'
| 'A256GCMKW'
| 'ECDH-ES'
| 'ECDH-ES+A128KW'
| 'ECDH-ES+A192KW'
| 'ECDH-ES+A256KW'
| 'RSA-OAEP'
| 'RSA-OAEP-256'
| 'RSA-OAEP-384'
| 'RSA-OAEP-512'
| 'PBES2-HS256+A128KW'
| 'PBES2-HS384+A192KW'
| 'PBES2-HS512+A256KW'
| (string & {})
/**
* JWE "enc" (Encryption Algorithm) Header Parameter values supported by this module. Availability
* of a given identifier additionally depends on the runtime.
*/
export type JWEContentEncryptionAlgorithm =
| 'A128CBC-HS256'
| 'A192CBC-HS384'
| 'A256CBC-HS512'
| 'A128GCM'
| 'A192GCM'
| 'A256GCM'
| (string & {})
/** JWK "kty" (Key Type) Parameter values supported by this module. */
export type JWKKeyType = 'EC' | 'RSA' | 'OKP' | 'AKP' | 'oct' | (string & {})
/**
* Generic JSON Web Key Parameters.
*
* > Note: This is declared as a type alias rather than an interface so that it satisfies the implicit index
* > signature of the `JsonWebKey` types shipped by `@types/node` and `lib.dom`.
*/
export type JWKParameters = {
/** JWK "kty" (Key Type) Parameter */
kty?: string
/**
* JWK "alg" (Algorithm) Parameter
*
* @see {@link https://github.com/panva/jose/issues/210 Algorithm Key Requirements}
*/
alg?: string
kty?: JWKKeyType
/** JWK "alg" (Algorithm) Parameter */
alg?: JWSAlgorithm | JWEKeyManagementAlgorithm | JWEContentEncryptionAlgorithm
/** JWK "key_ops" (Key Operations) Parameter */

@@ -16,3 +82,3 @@ key_ops?: string[]

/** JWK "use" (Public Key Use) Parameter */
use?: string
use?: 'sig' | 'enc' | (string & {})
/** JWK "x5c" (X.509 Certificate Chain) Parameter */

@@ -105,16 +171,31 @@ x5c?: string[]

/**
* JSON Web Key ({@link https://www.rfc-editor.org/rfc/rfc7517 JWK}). "RSA", "EC", "OKP", "AKP", and
* "oct" key types are supported.
* JSON Web Key ({@link https://www.rfc-editor.org/info/rfc7517/ JWK}). "RSA", "EC", "OKP", "AKP",
* and "oct" key types are supported.
*
* @see {@link JWK_AKP_Public}
* @see {@link JWK_AKP_Private}
* @see {@link JWK_OKP_Public}
* @see {@link JWK_OKP_Private}
* @see {@link JWK_EC_Public}
* @see {@link JWK_EC_Private}
* @see {@link JWK_RSA_Public}
* @see {@link JWK_RSA_Private}
* @see {@link JWK_oct}
* > Note: This is declared as a type alias rather than an interface so that it satisfies the implicit index
* > signature of the `JsonWebKey` types shipped by `@types/node` and `lib.dom`. It spells out the
* > {@link JWKParameters} members rather than intersecting them so that every JWK member is documented
* > in one place.
*/
export interface JWK extends JWKParameters {
export type JWK = {
/** JWK "kty" (Key Type) Parameter */
kty?: JWKKeyType
/** JWK "alg" (Algorithm) Parameter */
alg?: JWSAlgorithm | JWEKeyManagementAlgorithm | JWEContentEncryptionAlgorithm
/** JWK "key_ops" (Key Operations) Parameter */
key_ops?: string[]
/** JWK "ext" (Extractable) Parameter */
ext?: boolean
/** JWK "use" (Public Key Use) Parameter */
use?: 'sig' | 'enc' | (string & {})
/** JWK "x5c" (X.509 Certificate Chain) Parameter */
x5c?: string[]
/** JWK "x5t" (X.509 Certificate SHA-1 Thumbprint) Parameter */
x5t?: string
/** JWK "x5t#S256" (X.509 Certificate SHA-256 Thumbprint) Parameter */
'x5t#S256'?: string
/** JWK "x5u" (X.509 URL) Parameter */
x5u?: string
/** JWK "kid" (Key ID) Parameter */
kid?: string
/**

@@ -158,16 +239,44 @@ * - EC JWK "crv" (Curve) Parameter

priv?: string
/**
* RSA JWK "oth" (Other Primes Info) Parameter
*
* > Note: Multi-prime RSA keys are not supported; importing a JWK with this parameter present throws.
*/
oth?: Array<{
/** The Factor CRT Exponent */
d?: string
/** The Prime Factor */
r?: string
/** The Factor CRT Coefficient */
t?: string
}>
}
/**
* @private
*
* @internal
* Discriminated union of the JSON Web Key shapes supported by this module. Unlike {@link JWK}, each
* member requires and fixes the "kty" (Key Type) Parameter to its key type so that the union can be
* narrowed on it.
*/
// The "kty" is intersected into each arm one at a time rather than distributed over a parenthesised
// union - `X & (A | B)` means the same thing, but typedoc renders it without the parentheses, which
// reads as though the second arm carried no "kty" at all.
export type AnyJWK =
| (JWK_EC_Private & { kty: 'EC' })
| (JWK_EC_Public & { kty: 'EC' })
| (JWK_RSA_Private & { kty: 'RSA' })
| (JWK_RSA_Public & { kty: 'RSA' })
| (JWK_OKP_Private & { kty: 'OKP' })
| (JWK_OKP_Public & { kty: 'OKP' })
| (JWK_AKP_Private & { kty: 'AKP' })
| (JWK_AKP_Public & { kty: 'AKP' })
| (JWK_oct & { kty: 'oct' })
/** Key or secret input accepted by all sign, verify, encrypt, and decrypt operations. */
export type KeyInput = CryptoKey | KeyObject | JWK | Uint8Array
export interface GenericGetKeyFunction<IProtectedHeader, IToken, ReturnKeyTypes> {
/**
* Dynamic key resolution function. No token components have been verified at the time of this
* function call.
* function call. If a suitable key for the token cannot be matched, throw an error instead.
*
* If a suitable key for the token cannot be matched, throw an error instead.
*
* @param protectedHeader JWE or JWS Protected Header.

@@ -179,13 +288,8 @@ * @param token The consumed JWE or JWS token.

/**
* Generic Interface for consuming operations dynamic key resolution.
*
* @param IProtectedHeader Type definition of the JWE or JWS Protected Header.
* @param IToken Type definition of the consumed JWE or JWS token.
*/
export interface GetKeyFunction<IProtectedHeader, IToken> extends GenericGetKeyFunction<
/** Interface for consuming operations dynamic key resolution. */
export interface GetKeyFunction<
IProtectedHeader,
IToken,
CryptoKey | KeyObject | JWK | Uint8Array
> {}
KeyTypes extends KeyInput = KeyInput,
> extends GenericGetKeyFunction<IProtectedHeader, IToken, KeyTypes> {}

@@ -229,3 +333,3 @@ /**

* The "payload" member MUST be present and contain the value BASE64URL(JWS Payload). When when
* JWS Unencoded Payload ({@link https://www.rfc-editor.org/rfc/rfc7797 RFC7797}) "b64": false is
* JWS Unencoded Payload ({@link https://www.rfc-editor.org/info/rfc7797/ RFC7797}) "b64": false is
* used the value passed may also be a {@link !Uint8Array}.

@@ -244,3 +348,3 @@ */

* Flattened JWS JSON Serialization Syntax token. Payload is returned as an empty string when JWS
* Unencoded Payload ({@link https://www.rfc-editor.org/rfc/rfc7797 RFC7797}) is used.
* Unencoded Payload ({@link https://www.rfc-editor.org/info/rfc7797/ RFC7797}) is used.
*/

@@ -254,3 +358,3 @@ export interface FlattenedJWS extends Partial<FlattenedJWSInput> {

* General JWS JSON Serialization Syntax token. Payload is returned as an empty string when JWS
* Unencoded Payload ({@link https://www.rfc-editor.org/rfc/rfc7797 RFC7797}) is used.
* Unencoded Payload ({@link https://www.rfc-editor.org/info/rfc7797/ RFC7797}) is used.
*/

@@ -279,4 +383,7 @@ export interface GeneralJWS {

/** "jwk" (JSON Web Key) Header Parameter */
jwk?: Pick<JWK, 'kty' | 'crv' | 'x' | 'y' | 'e' | 'n' | 'alg' | 'pub'>
/**
* "jwk" (JSON Web Key) Header Parameter. This must be a public JSON Web Key; private and
* symmetric key parameters are not permitted.
*/
jwk?: Omit<JWK, 'd' | 'dp' | 'dq' | 'k' | 'p' | 'q' | 'qi' | 'priv' | 'oth'>

@@ -292,12 +399,8 @@ /** "typ" (Type) Header Parameter */

export interface JWSHeaderParameters extends JoseHeaderParameters {
/**
* JWS "alg" (Algorithm) Header Parameter
*
* @see {@link https://github.com/panva/jose/issues/210#jws-alg Algorithm Key Requirements}
*/
alg?: string
/** JWS "alg" (Algorithm) Header Parameter */
alg?: JWSAlgorithm
/**
* This JWS Extension Header Parameter modifies the JWS Payload representation and the JWS Signing
* Input computation as per {@link https://www.rfc-editor.org/rfc/rfc7797 RFC7797}.
* Input computation as per {@link https://www.rfc-editor.org/info/rfc7797/ RFC7797}.
*/

@@ -409,15 +512,7 @@ b64?: boolean

export interface JWEHeaderParameters extends JoseHeaderParameters {
/**
* JWE "alg" (Algorithm) Header Parameter
*
* @see {@link https://github.com/panva/jose/issues/210#jwe-alg Algorithm Key Requirements}
*/
alg?: string
/** JWE "alg" (Algorithm) Header Parameter */
alg?: JWEKeyManagementAlgorithm
/**
* JWE "enc" (Encryption Algorithm) Header Parameter
*
* @see {@link https://github.com/panva/jose/issues/210#jwe-alg Algorithm Key Requirements}
*/
enc?: string
/** JWE "enc" (Encryption Algorithm) Header Parameter */
enc?: JWEContentEncryptionAlgorithm

@@ -428,10 +523,7 @@ /** JWE "crit" (Critical) Header Parameter */

/**
* JWE "zip" (Compression Algorithm) Header Parameter.
*
* The only supported value is `"DEF"` (DEFLATE). Requires the `CompressionStream` /
* `DecompressionStream` APIs to be available in the runtime.
*
* @see {@link https://www.rfc-editor.org/rfc/rfc7516#section-4.1.3 JWE "zip" Header Parameter}
* JWE "zip" (Compression Algorithm) Header Parameter. The only supported value is `"DEF"`
* (DEFLATE), and it requires the `CompressionStream` / `DecompressionStream` APIs to be available
* in the runtime.
*/
zip?: string
zip?: 'DEF' | (string & {})

@@ -447,16 +539,10 @@ /** Any other JWE Header member. */

* for those is either `true` or `false`. `true` when the Header Parameter MUST be integrity
* protected, `false` when it's irrelevant.
* protected, `false` when it's irrelevant. The JWS extension Header Parameter `b64` is always
* recognized and processed properly; no other registered Header Parameters currently receive this
* built-in treatment.
*
* This makes the "Extension Header Parameter "..." is not recognized" error go away.
*
* Use this when a given JWS/JWT/JWE profile requires the use of proprietary non-registered "crit"
* (Critical) Header Parameters. This will only make sure the Header Parameter is syntactically
* correct when provided and that it is optionally integrity protected. It will not process the
* Header Parameter in any way or reject the operation if it is missing. You MUST still verify the
* Header Parameter was present and process it according to the profile's validation steps after
* the operation succeeds.
*
* The JWS extension Header Parameter `b64` is always recognized and processed properly. No other
* registered Header Parameters that need this kind of default built-in treatment are currently
* available.
* > Warning: This only checks that the Header Parameter is syntactically correct when provided and,
* > optionally, integrity protected. It does not process the Header Parameter or reject the
* > operation when it is missing. You MUST still verify its presence and process it according to
* > the profile's validation steps after the operation succeeds.
*/

@@ -475,3 +561,3 @@ crit?: {

*/
keyManagementAlgorithms?: string[]
keyManagementAlgorithms?: JWEKeyManagementAlgorithm[]

@@ -482,3 +568,3 @@ /**

*/
contentEncryptionAlgorithms?: string[]
contentEncryptionAlgorithms?: JWEContentEncryptionAlgorithm[]

@@ -495,7 +581,4 @@ /**

* Algorithm) Header Parameter is present. By default this value is set to 250000 (250 KB). The
* value must be `0`, a positive safe integer, or `Infinity`.
*
* Set to `0` to reject all compressed JWEs during decryption.
*
* Set to `Infinity` to disable the decompressed size limit.
* value must be `0`, a positive safe integer, or `Infinity`. Set it to `0` to reject all
* compressed JWEs during decryption or to `Infinity` to disable the decompressed size limit.
*/

@@ -511,5 +594,4 @@ maxDecompressedLength?: number

/**
* Expected JWT "aud" (Audience) Claim value(s).
*
* This option makes the JWT "aud" (Audience) Claim presence required.
* Expected JWT "aud" (Audience) Claim value(s). This option makes the JWT "aud" (Audience) Claim
* presence required.
*/

@@ -519,9 +601,6 @@ audience?: string | string[]

/**
* Clock skew tolerance
*
* - In seconds when number (e.g. 5)
* - Resolved into a number of seconds when a string (e.g. "5 seconds", "10 minutes", "2 hours").
*
* Used when validating the JWT "nbf" (Not Before) and "exp" (Expiration Time) claims, and when
* validating the "iat" (Issued At) claim if the {@link maxTokenAge `maxTokenAge` option} is set.
* Clock skew tolerance in seconds when a number (e.g. 5), or resolved into seconds when a string
* (e.g. "5 seconds", "10 minutes", "2 hours"). Used when validating the JWT "nbf" (Not Before)
* and "exp" (Expiration Time) claims, and when validating the "iat" (Issued At) claim if the
* {@link maxTokenAge `maxTokenAge` option} is set.
*/

@@ -531,5 +610,4 @@ clockTolerance?: string | number

/**
* Expected JWT "iss" (Issuer) Claim value(s).
*
* This option makes the JWT "iss" (Issuer) Claim presence required.
* Expected JWT "iss" (Issuer) Claim value(s). This option makes the JWT "iss" (Issuer) Claim
* presence required.
*/

@@ -539,8 +617,5 @@ issuer?: string | string[]

/**
* Maximum time elapsed (in seconds) from the JWT "iat" (Issued At) Claim value.
*
* - In seconds when number (e.g. 5)
* - Resolved into a number of seconds when a string (e.g. "5 seconds", "10 minutes", "2 hours").
*
* This option makes the JWT "iat" (Issued At) Claim presence required.
* Maximum time elapsed from the JWT "iat" (Issued At) Claim value, in seconds when a number (e.g.
* 5), or resolved into seconds when a string (e.g. "5 seconds", "10 minutes", "2 hours"). This
* option makes the JWT "iat" (Issued At) Claim presence required.
*/

@@ -550,5 +625,4 @@ maxTokenAge?: string | number

/**
* Expected JWT "sub" (Subject) Claim value.
*
* This option makes the JWT "sub" (Subject) Claim presence required.
* Expected JWT "sub" (Subject) Claim value. This option makes the JWT "sub" (Subject) Claim
* presence required.
*/

@@ -558,5 +632,4 @@ subject?: string

/**
* Expected JWT "typ" (Type) Header Parameter value.
*
* This option makes the JWT "typ" (Type) Header Parameter presence required.
* Expected JWT "typ" (Type) Header Parameter value. This option makes the JWT "typ" (Type) Header
* Parameter presence required.
*/

@@ -585,6 +658,5 @@ typ?: string

*
* > [!NOTE]\
* > Unsecured JWTs (`{ "alg": "none" }`) are never accepted by this API.
* > Note: Unsecured JWTs (`{ "alg": "none" }`) are never accepted by this API.
*/
algorithms?: string[]
algorithms?: JWSAlgorithm[]
}

@@ -597,49 +669,21 @@

export interface JWTPayload {
/**
* JWT Issuer
*
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.1 RFC7519#section-4.1.1}
*/
/** JWT Issuer */
iss?: string
/**
* JWT Subject
*
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.2 RFC7519#section-4.1.2}
*/
/** JWT Subject */
sub?: string
/**
* JWT Audience
*
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.3 RFC7519#section-4.1.3}
*/
/** JWT Audience */
aud?: string | string[]
/**
* JWT ID
*
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.7 RFC7519#section-4.1.7}
*/
/** JWT ID */
jti?: string
/**
* JWT Not Before
*
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.5 RFC7519#section-4.1.5}
*/
/** JWT Not Before */
nbf?: number
/**
* JWT Expiration Time
*
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4 RFC7519#section-4.1.4}
*/
/** JWT Expiration Time */
exp?: number
/**
* JWT Issued At
*
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.6 RFC7519#section-4.1.6}
*/
/** JWT Issued At */
iat?: number

@@ -708,3 +752,5 @@

/** JWT Claims Set. */
payload: PayloadType & JWTPayload
payload: PayloadType &
JWTPayload &
([PayloadType] extends [object] ? unknown : unknown extends PayloadType ? unknown : never)

@@ -718,3 +764,5 @@ /** JWS Protected Header. */

/** JWT Claims Set. */
payload: PayloadType & JWTPayload
payload: PayloadType &
JWTPayload &
([PayloadType] extends [object] ? unknown : unknown extends PayloadType ? unknown : never)

@@ -726,5 +774,5 @@ /** JWE Protected Header. */

/** When key resolver functions are used this becomes part of successful resolves */
export interface ResolvedKey {
export interface ResolvedKey<KeyType extends CryptoKey | Uint8Array = CryptoKey | Uint8Array> {
/** Key resolved from the key resolver function. */
key: CryptoKey | Uint8Array
key: KeyType
}

@@ -734,3 +782,3 @@

export interface CompactJWSHeaderParameters extends JWSHeaderParameters {
alg: string
alg: JWSAlgorithm
}

@@ -740,3 +788,3 @@

export interface JWTHeaderParameters extends CompactJWSHeaderParameters {
b64?: true
b64?: boolean
}

@@ -746,4 +794,4 @@

export interface CompactJWEHeaderParameters extends JWEHeaderParameters {
alg: string
enc: string
alg: JWEKeyManagementAlgorithm
enc: JWEContentEncryptionAlgorithm
}

@@ -762,3 +810,3 @@

export interface KeyObject {
type: string
type: 'private' | 'public' | 'secret'
}

@@ -772,7 +820,23 @@

*/
export type CryptoKey = Extract<
Awaited<ReturnType<typeof crypto.subtle.generateKey>>,
{ type: string }
>
export type CryptoKey = typeof globalThis extends {
crypto: { subtle: { generateKey(...args: any[]): Promise<infer R> } }
}
? Extract<R, { type: string }>
: CryptoKeyStructuralFallback
/**
* Used as {@link CryptoKey} only when the host runtime's `crypto` global is not typed at all, e.g. a
* consumer compiling with neither the DOM lib nor `@types/node`. Whenever a `CryptoKey` type is
* available it is aliased instead, deliberately, so that this module never introduces a competing
* nominal `CryptoKey` and values flow freely to and from {@link !SubtleCrypto} APIs.
*/
export interface CryptoKeyStructuralFallback {
readonly algorithm: { name: string }
readonly extractable: boolean
readonly type: 'private' | 'public' | 'secret'
readonly usages: (
'decrypt' | 'deriveBits' | 'deriveKey' | 'encrypt' | 'sign' | 'unwrapKey' | 'verify' | 'wrapKey'
)[]
}
/** Generic interface for JWT producing classes. */

@@ -809,22 +873,7 @@ export interface ProduceJWT {

/**
* Set the "nbf" (Not Before) Claim.
* Set the "nbf" (Not Before) Claim. A `number` is used directly, a `Date` is converted to a Unix
* timestamp, and a `string` is parsed as a time span relative to the current Unix timestamp.
* String units may be seconds, minutes, hours, days, weeks, or years; months are unsupported and
* a year is 365.25 days. A leading `-` or trailing `"ago"` subtracts the time span.
*
* - If a `number` is passed as an argument it is used as the claim directly.
* - If a `Date` instance is passed as an argument it is converted to unix timestamp and used as the
* claim.
* - If a `string` is passed as an argument it is resolved to a time span, and then added to the
* current unix timestamp and used as the claim.
*
* Format used for time span should be a number followed by a unit, such as "5 minutes" or "1
* day".
*
* Valid units are: "sec", "secs", "second", "seconds", "s", "minute", "minutes", "min", "mins",
* "m", "hour", "hours", "hr", "hrs", "h", "day", "days", "d", "week", "weeks", "w", "year",
* "years", "yr", "yrs", and "y". It is not possible to specify months. 365.25 days is used as an
* alias for a year.
*
* If the string is suffixed with "ago", or prefixed with a "-", the resulting time span gets
* subtracted from the current unix timestamp. A "from now" suffix can also be used for
* readability when adding to the current unix timestamp.
*
* @param input "nbf" (Not Before) Claim value to set on the JWT Claims Set.

@@ -835,22 +884,7 @@ */

/**
* Set the "exp" (Expiration Time) Claim.
* Set the "exp" (Expiration Time) Claim. A `number` is used directly, a `Date` is converted to a
* Unix timestamp, and a `string` is parsed as a time span relative to the current Unix timestamp.
* String units may be seconds, minutes, hours, days, weeks, or years; months are unsupported and
* a year is 365.25 days. A leading `-` or trailing `"ago"` subtracts the time span.
*
* - If a `number` is passed as an argument it is used as the claim directly.
* - If a `Date` instance is passed as an argument it is converted to unix timestamp and used as the
* claim.
* - If a `string` is passed as an argument it is resolved to a time span, and then added to the
* current unix timestamp and used as the claim.
*
* Format used for time span should be a number followed by a unit, such as "5 minutes" or "1
* day".
*
* Valid units are: "sec", "secs", "second", "seconds", "s", "minute", "minutes", "min", "mins",
* "m", "hour", "hours", "hr", "hrs", "h", "day", "days", "d", "week", "weeks", "w", "year",
* "years", "yr", "yrs", and "y". It is not possible to specify months. 365.25 days is used as an
* alias for a year.
*
* If the string is suffixed with "ago", or prefixed with a "-", the resulting time span gets
* subtracted from the current unix timestamp. A "from now" suffix can also be used for
* readability when adding to the current unix timestamp.
*
* @param input "exp" (Expiration Time) Claim value to set on the JWT Claims Set.

@@ -861,26 +895,11 @@ */

/**
* Set the "iat" (Issued At) Claim.
* Set the "iat" (Issued At) Claim. With no argument the current Unix timestamp is used. A
* `number` is used directly, a `Date` is converted to a Unix timestamp, and a `string` is parsed
* as a time span relative to the current Unix timestamp. String units may be seconds, minutes,
* hours, days, weeks, or years; months are unsupported and a year is 365.25 days. A leading `-`
* or trailing `"ago"` subtracts the time span.
*
* - If no argument is used the current unix timestamp is used as the claim.
* - If a `number` is passed as an argument it is used as the claim directly.
* - If a `Date` instance is passed as an argument it is converted to unix timestamp and used as the
* claim.
* - If a `string` is passed as an argument it is resolved to a time span, and then added to the
* current unix timestamp and used as the claim.
*
* Format used for time span should be a number followed by a unit, such as "5 minutes" or "1
* day".
*
* Valid units are: "sec", "secs", "second", "seconds", "s", "minute", "minutes", "min", "mins",
* "m", "hour", "hours", "hr", "hrs", "h", "day", "days", "d", "week", "weeks", "w", "year",
* "years", "yr", "yrs", and "y". It is not possible to specify months. 365.25 days is used as an
* alias for a year.
*
* If the string is suffixed with "ago", or prefixed with a "-", the resulting time span gets
* subtracted from the current unix timestamp. A "from now" suffix can also be used for
* readability when adding to the current unix timestamp.
*
* @param input "iat" (Expiration Time) Claim value to set on the JWT Claims Set.
* @param input "iat" (Issued At) Claim value to set on the JWT Claims Set.
*/
setIssuedAt(input?: number | string | Date): this
}
/**
* Base64URL encoding and decoding utilities
* Decodes a Base64URL encoded input.
*
* @module
* @param input Base64URL encoded input, as a string or its UTF-8 bytes.
* @returns The decoded bytes.
* @throws {!TypeError} When the input is not correctly Base64URL encoded. Standard Base64 input
* (i.e. containing `+` or `/`) is rejected.
*/
/** Decodes a Base64URL encoded input. */
export declare function decode(input: Uint8Array | string): Uint8Array;
/** Encodes an input using Base64URL with no padding. */
/**
* Encodes an input using Base64URL with no padding.
*
* @param input Input to encode, as a string or as bytes. Strings are encoded as UTF-8 first.
* @returns The Base64URL encoded, unpadded, representation of the input.
*/
export declare function encode(input: Uint8Array | string): string;

@@ -1,6 +0,1 @@

/**
* JSON Web Token (JWT) Claims Set Decoding (no validation, no signature checking)
*
* @module
*/
import type * as types from '../types.d.ts';

@@ -13,7 +8,4 @@ /**

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/jwt/decode'`.
*
* @param jwt JWT token in compact JWS serialization.
*/
export declare function decodeJwt<PayloadType = types.JWTPayload>(jwt: string): PayloadType & types.JWTPayload;
export declare function decodeJwt<PayloadType = types.JWTPayload>(jwt: string): PayloadType & types.JWTPayload & ([PayloadType] extends [object] ? unknown : unknown extends PayloadType ? unknown : never);

@@ -1,6 +0,1 @@

/**
* JOSE Protected Header Decoding (JWE, JWS, all serialization syntaxes)
*
* @module
*/
import type * as types from '../types.d.ts';

@@ -12,7 +7,4 @@ /** JWE and JWS Header Parameters */

*
* This function is exported (as a named export) from the main `'jose'` module entry point as well
* as from its subpath export `'jose/decode/protected_header'`.
*
* @param token JWE/JWS/JWT token in any JOSE serialization.
*/
export declare function decodeProtectedHeader(token: string | object): ProtectedHeaderParameters;

@@ -0,21 +1,33 @@

import type * as types from '../types.d.ts';
/**
* JOSE module errors and error codes
*
* @module
* Every stable error code used by this module. {@link AnyJOSEError} pairs each subclass with the one
* it is thrown with, making that union a discriminated one.
*/
import type * as types from '../types.d.ts';
export type JOSEErrorCode = 'ERR_JOSE_ALG_NOT_ALLOWED' | 'ERR_JOSE_GENERIC' | 'ERR_JOSE_NOT_SUPPORTED' | 'ERR_JWE_DECRYPTION_FAILED' | 'ERR_JWE_INVALID' | 'ERR_JWK_INVALID' | 'ERR_JWKS_INVALID' | 'ERR_JWKS_MULTIPLE_MATCHING_KEYS' | 'ERR_JWKS_NO_MATCHING_KEY' | 'ERR_JWKS_TIMEOUT' | 'ERR_JWS_INVALID' | 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED' | 'ERR_JWT_CLAIM_VALIDATION_FAILED' | 'ERR_JWT_EXPIRED' | 'ERR_JWT_INVALID';
/**
* A generic Error that all other JOSE specific Error subclasses extend.
* The shape shared by the two errors thrown during JWT Claims Set validation.
*
* > Note: {@link JWTExpired} does not extend {@link JWTClaimValidationFailed}, so `instanceof
* > JWTClaimValidationFailed` is `false` for an expired JWT. Use {@link JWTClaimValidationError} or
* > the {@link JOSEError.code code} discriminant to handle both.
*/
export interface JWTClaimValidationFailure {
/** The Claim for which the validation failed. */
claim: string;
/** Reason code for the validation failure. */
reason: JWTClaimValidationReason;
/** The parsed JWT Claims Set (aka payload). */
payload: types.JWTPayload;
}
/** Reason codes produced by JWT Claims Set validation. */
export type JWTClaimValidationReason = 'check_failed' | 'invalid' | 'mismatch' | 'missing' | 'unspecified' | (string & {});
/** A generic Error that all other JOSE specific Error subclasses extend. */
export declare class JOSEError extends Error {
/** A unique error code for the particular error subclass. */
static code: JOSEErrorCode | (string & {});
/**
* A unique error code for the particular error subclass.
*
* @ignore
* A unique error code for {@link JOSEError}. Each subclass sets its own; see {@link AnyJOSEError}
* to switch over them as a discriminated union.
*/
static code: string;
/** A unique error code for {@link JOSEError}. */
code: string;
/** @ignore */
code: JOSEErrorCode | (string & {});
constructor(message?: string, options?: {

@@ -25,15 +37,13 @@ cause?: unknown;

}
/**
* An error subclass thrown when a JWT Claim Set member validation fails.
*
*/
export declare class JWTClaimValidationFailed extends JOSEError {
/** @ignore */
static code: string;
/** An error subclass thrown when a JWT Claim Set member validation fails. */
export declare class JWTClaimValidationFailed extends JOSEError implements JWTClaimValidationFailure {
static code: JOSEErrorCode | (string & {});
/** A unique error code for {@link JWTClaimValidationFailed}. */
code: string;
code: JOSEErrorCode | (string & {});
/** The {@link JWTClaimValidationFailure} carried by every instance of this error. */
cause: JWTClaimValidationFailure;
/** The Claim for which the validation failed. */
claim: string;
/** Reason code for the validation failure. */
reason: string;
reason: JWTClaimValidationReason;
/**

@@ -46,18 +56,15 @@ * The parsed JWT Claims Set (aka payload). Other JWT claims may or may not have been verified at

payload: types.JWTPayload;
/** @ignore */
constructor(message: string, payload: types.JWTPayload, claim?: string, reason?: string);
constructor(message: string, payload: types.JWTPayload, claim?: string, reason?: JWTClaimValidationReason);
}
/**
* An error subclass thrown when a JWT is expired.
*
*/
export declare class JWTExpired extends JOSEError implements JWTClaimValidationFailed {
/** @ignore */
static code: string;
/** An error subclass thrown when a JWT is expired. */
export declare class JWTExpired extends JOSEError implements JWTClaimValidationFailure {
static code: JOSEErrorCode | (string & {});
/** A unique error code for {@link JWTExpired}. */
code: string;
code: JOSEErrorCode | (string & {});
/** The {@link JWTClaimValidationFailure} carried by every instance of this error. */
cause: JWTClaimValidationFailure;
/** The Claim for which the validation failed. */
claim: string;
/** Reason code for the validation failure. */
reason: string;
reason: JWTClaimValidationReason;
/**

@@ -70,14 +77,9 @@ * The parsed JWT Claims Set (aka payload). Other JWT claims may or may not have been verified at

payload: types.JWTPayload;
/** @ignore */
constructor(message: string, payload: types.JWTPayload, claim?: string, reason?: string);
constructor(message: string, payload: types.JWTPayload, claim?: string, reason?: JWTClaimValidationReason);
}
/**
* An error subclass thrown when a JOSE Algorithm is not allowed per developer preference.
*
*/
/** An error subclass thrown when a JOSE Algorithm is not allowed per developer preference. */
export declare class JOSEAlgNotAllowed extends JOSEError {
/** @ignore */
static code: string;
static code: JOSEErrorCode | (string & {});
/** A unique error code for {@link JOSEAlgNotAllowed}. */
code: string;
code: JOSEErrorCode | (string & {});
}

@@ -87,20 +89,13 @@ /**

* implementation or JOSE in general.
*
*/
export declare class JOSENotSupported extends JOSEError {
/** @ignore */
static code: string;
static code: JOSEErrorCode | (string & {});
/** A unique error code for {@link JOSENotSupported}. */
code: string;
code: JOSEErrorCode | (string & {});
}
/**
* An error subclass thrown when a JWE ciphertext decryption fails.
*
*/
/** An error subclass thrown when a JWE ciphertext decryption fails. */
export declare class JWEDecryptionFailed extends JOSEError {
/** @ignore */
static code: string;
static code: JOSEErrorCode | (string & {});
/** A unique error code for {@link JWEDecryptionFailed}. */
code: string;
/** @ignore */
code: JOSEErrorCode | (string & {});
constructor(message?: string, options?: {

@@ -110,62 +105,37 @@ cause?: unknown;

}
/**
* An error subclass thrown when a JWE is invalid.
*
*/
/** An error subclass thrown when a JWE is invalid. */
export declare class JWEInvalid extends JOSEError {
/** @ignore */
static code: string;
static code: JOSEErrorCode | (string & {});
/** A unique error code for {@link JWEInvalid}. */
code: string;
code: JOSEErrorCode | (string & {});
}
/**
* An error subclass thrown when a JWS is invalid.
*
*/
/** An error subclass thrown when a JWS is invalid. */
export declare class JWSInvalid extends JOSEError {
/** @ignore */
static code: string;
static code: JOSEErrorCode | (string & {});
/** A unique error code for {@link JWSInvalid}. */
code: string;
code: JOSEErrorCode | (string & {});
}
/**
* An error subclass thrown when a JWT is invalid.
*
*/
/** An error subclass thrown when a JWT is invalid. */
export declare class JWTInvalid extends JOSEError {
/** @ignore */
static code: string;
static code: JOSEErrorCode | (string & {});
/** A unique error code for {@link JWTInvalid}. */
code: string;
code: JOSEErrorCode | (string & {});
}
/**
* An error subclass thrown when a JWK is invalid.
*
*/
/** An error subclass thrown when a JWK is invalid. */
export declare class JWKInvalid extends JOSEError {
/** @ignore */
static code: string;
static code: JOSEErrorCode | (string & {});
/** A unique error code for {@link JWKInvalid}. */
code: string;
code: JOSEErrorCode | (string & {});
}
/**
* An error subclass thrown when a JWKS is invalid.
*
*/
/** An error subclass thrown when a JWKS is invalid. */
export declare class JWKSInvalid extends JOSEError {
/** @ignore */
static code: string;
static code: JOSEErrorCode | (string & {});
/** A unique error code for {@link JWKSInvalid}. */
code: string;
code: JOSEErrorCode | (string & {});
}
/**
* An error subclass thrown when no keys match from a JWKS.
*
*/
/** An error subclass thrown when no keys match from a JWKS. */
export declare class JWKSNoMatchingKey extends JOSEError {
/** @ignore */
static code: string;
static code: JOSEErrorCode | (string & {});
/** A unique error code for {@link JWKSNoMatchingKey}. */
code: string;
/** @ignore */
code: JOSEErrorCode | (string & {});
constructor(message?: string, options?: {

@@ -175,14 +145,15 @@ cause?: unknown;

}
/**
* An error subclass thrown when multiple keys match from a JWKS.
*
*/
/** An error subclass thrown when multiple keys match from a JWKS. */
export declare class JWKSMultipleMatchingKeys extends JOSEError {
/** @ignore */
/**
* Iterates the public keys that matched the JWS JOSE Header, so that verification can be
* attempted with each in turn. See the {@link jwks/remote.createRemoteJWKSet createRemoteJWKSet}
* and {@link jwks/local.createLocalJWKSet createLocalJWKSet} examples. Instances thrown by this
* module always iterate the matched keys; an instance constructed by other code iterates
* nothing.
*/
[Symbol.asyncIterator]: () => AsyncIterableIterator<types.CryptoKey>;
/** @ignore */
static code: string;
static code: JOSEErrorCode | (string & {});
/** A unique error code for {@link JWKSMultipleMatchingKeys}. */
code: string;
/** @ignore */
code: JOSEErrorCode | (string & {});
constructor(message?: string, options?: {

@@ -192,12 +163,7 @@ cause?: unknown;

}
/**
* Timeout was reached when retrieving the JWKS response.
*
*/
/** Timeout was reached when retrieving the JWKS response. */
export declare class JWKSTimeout extends JOSEError {
/** @ignore */
static code: string;
static code: JOSEErrorCode | (string & {});
/** A unique error code for {@link JWKSTimeout}. */
code: string;
/** @ignore */
code: JOSEErrorCode | (string & {});
constructor(message?: string, options?: {

@@ -207,12 +173,7 @@ cause?: unknown;

}
/**
* An error subclass thrown when JWS signature verification fails.
*
*/
/** An error subclass thrown when JWS signature verification fails. */
export declare class JWSSignatureVerificationFailed extends JOSEError {
/** @ignore */
static code: string;
static code: JOSEErrorCode | (string & {});
/** A unique error code for {@link JWSSignatureVerificationFailed}. */
code: string;
/** @ignore */
code: JOSEErrorCode | (string & {});
constructor(message?: string, options?: {

@@ -222,1 +183,47 @@ cause?: unknown;

}
/**
* Union of the errors thrown during JWT Claims Set validation. {@link JWTExpired} does not extend
* {@link JWTClaimValidationFailed}, so a single `instanceof` check cannot cover both. Use this type
* — together with the {@link JOSEError.code code} discriminant — when handling either.
*/
export type JWTClaimValidationError = JWTClaimValidationFailed | JWTExpired;
/**
* Union of every {@link JOSEError} subclass this module throws, each paired with the single
* {@link JOSEErrorCode} it is thrown with. That pairing lives here rather than on the classes, so
* that `code` stays assignable, writable, and overridable on them exactly as before, while a value
* of this type can still be switched over as a discriminated union.
*
* > Note: The base {@link JOSEError} is deliberately not a member — its `code` spans every value, which
* > would defeat the discriminant. A small number of JSON Web Key Set HTTP failures are thrown as the
* > base class itself, so `instanceof JOSEError` remains the catch-all; this union is for handling a
* > value already known to be one of the specific errors.
*/
export type AnyJOSEError = (JOSEAlgNotAllowed & {
code: 'ERR_JOSE_ALG_NOT_ALLOWED';
}) | (JOSENotSupported & {
code: 'ERR_JOSE_NOT_SUPPORTED';
}) | (JWEDecryptionFailed & {
code: 'ERR_JWE_DECRYPTION_FAILED';
}) | (JWEInvalid & {
code: 'ERR_JWE_INVALID';
}) | (JWKInvalid & {
code: 'ERR_JWK_INVALID';
}) | (JWKSInvalid & {
code: 'ERR_JWKS_INVALID';
}) | (JWKSMultipleMatchingKeys & {
code: 'ERR_JWKS_MULTIPLE_MATCHING_KEYS';
}) | (JWKSNoMatchingKey & {
code: 'ERR_JWKS_NO_MATCHING_KEY';
}) | (JWKSTimeout & {
code: 'ERR_JWKS_TIMEOUT';
}) | (JWSInvalid & {
code: 'ERR_JWS_INVALID';
}) | (JWSSignatureVerificationFailed & {
code: 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED';
}) | (JWTClaimValidationFailed & {
code: 'ERR_JWT_CLAIM_VALIDATION_FAILED';
}) | (JWTExpired & {
code: 'ERR_JWT_EXPIRED';
}) | (JWTInvalid & {
code: 'ERR_JWT_INVALID';
});

@@ -1,23 +0,5 @@

import { flattenedDecrypt } from '../flattened/decrypt.js';
import { JWEInvalid } from '../../util/errors.js';
import { decoder } from '../../lib/buffer_utils.js';
import { prepareDecrypt, decryptCompact } from '../../lib/jwe_decrypt.js';
export async function compactDecrypt(jwe, key, options) {
if (jwe instanceof Uint8Array) {
jwe = decoder.decode(jwe);
}
if (typeof jwe !== 'string') {
throw new JWEInvalid('Compact JWE must be a string or Uint8Array');
}
const { 0: protectedHeader, 1: encryptedKey, 2: iv, 3: ciphertext, 4: tag, length, } = jwe.split('.');
if (length !== 5) {
throw new JWEInvalid('Invalid Compact JWE');
}
const decrypted = await flattenedDecrypt({
ciphertext,
iv: iv || undefined,
protected: protectedHeader,
tag: tag || undefined,
encrypted_key: encryptedKey || undefined,
}, key, options);
const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader };
const decrypted = await decryptCompact(jwe, prepareDecrypt(options), key);
const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.parsedProt };
if (typeof key === 'function') {

@@ -24,0 +6,0 @@ return { ...result, key: decrypted.key };

@@ -1,15 +0,4 @@

import { decode as b64u } from '../../util/base64url.js';
import { decrypt } from '../../lib/content_encryption.js';
import { decodeBase64url } from '../../lib/helpers.js';
import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.js';
import { isDisjoint } from '../../lib/type_checks.js';
import { JWEInvalid } from '../../util/errors.js';
import { isObject } from '../../lib/type_checks.js';
import { decryptKeyManagement } from '../../lib/key_management.js';
import { decoder, concat, encode } from '../../lib/buffer_utils.js';
import { generateCek } from '../../lib/content_encryption.js';
import { validateCrit } from '../../lib/validate_crit.js';
import { validateAlgorithms } from '../../lib/validate_algorithms.js';
import { normalizeKey } from '../../lib/normalize_key.js';
import { checkKeyType } from '../../lib/check_key_type.js';
import { decompress } from '../../lib/deflate.js';
import { prepareDecrypt, decryptJWE, decryptResult, checkShared, checkRecipient, } from '../../lib/jwe_decrypt.js';
export async function flattenedDecrypt(jwe, key, options) {

@@ -19,142 +8,5 @@ if (!isObject(jwe)) {

}
if (jwe.protected === undefined && jwe.header === undefined && jwe.unprotected === undefined) {
throw new JWEInvalid('JOSE Header missing');
}
if (jwe.iv !== undefined && typeof jwe.iv !== 'string') {
throw new JWEInvalid('JWE Initialization Vector incorrect type');
}
if (typeof jwe.ciphertext !== 'string') {
throw new JWEInvalid('JWE Ciphertext missing or incorrect type');
}
if (jwe.tag !== undefined && typeof jwe.tag !== 'string') {
throw new JWEInvalid('JWE Authentication Tag incorrect type');
}
if (jwe.protected !== undefined && typeof jwe.protected !== 'string') {
throw new JWEInvalid('JWE Protected Header incorrect type');
}
if (jwe.encrypted_key !== undefined && typeof jwe.encrypted_key !== 'string') {
throw new JWEInvalid('JWE Encrypted Key incorrect type');
}
if (jwe.aad !== undefined && typeof jwe.aad !== 'string') {
throw new JWEInvalid('JWE AAD incorrect type');
}
if (jwe.header !== undefined && !isObject(jwe.header)) {
throw new JWEInvalid('JWE Shared Unprotected Header incorrect type');
}
if (jwe.unprotected !== undefined && !isObject(jwe.unprotected)) {
throw new JWEInvalid('JWE Per-Recipient Unprotected Header incorrect type');
}
let parsedProt;
if (jwe.protected) {
try {
const protectedHeader = b64u(jwe.protected);
parsedProt = JSON.parse(decoder.decode(protectedHeader));
}
catch {
throw new JWEInvalid('JWE Protected Header is invalid');
}
}
if (!isDisjoint(parsedProt, jwe.header, jwe.unprotected)) {
throw new JWEInvalid('JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint');
}
const joseHeader = {
...parsedProt,
...jwe.header,
...jwe.unprotected,
};
validateCrit(JWEInvalid, new Map(), options?.crit, parsedProt, joseHeader);
if (joseHeader.zip !== undefined && joseHeader.zip !== 'DEF') {
throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value.');
}
if (joseHeader.zip !== undefined && !parsedProt?.zip) {
throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header Parameter MUST be in a protected header.');
}
const { alg, enc } = joseHeader;
if (typeof alg !== 'string' || !alg) {
throw new JWEInvalid('missing JWE Algorithm (alg) in JWE Header');
}
if (typeof enc !== 'string' || !enc) {
throw new JWEInvalid('missing JWE Encryption Algorithm (enc) in JWE Header');
}
const keyManagementAlgorithms = options && validateAlgorithms('keyManagementAlgorithms', options.keyManagementAlgorithms);
const contentEncryptionAlgorithms = options &&
validateAlgorithms('contentEncryptionAlgorithms', options.contentEncryptionAlgorithms);
if ((keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) ||
(!keyManagementAlgorithms && alg.startsWith('PBES2'))) {
throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter value not allowed');
}
if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) {
throw new JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter value not allowed');
}
let encryptedKey;
if (jwe.encrypted_key !== undefined) {
encryptedKey = decodeBase64url(jwe.encrypted_key, 'encrypted_key', JWEInvalid);
}
let resolvedKey = false;
if (typeof key === 'function') {
key = await key(parsedProt, jwe);
resolvedKey = true;
}
checkKeyType(alg === 'dir' ? enc : alg, key, 'decrypt');
const k = await normalizeKey(key, alg);
let cek;
try {
cek = await decryptKeyManagement(alg, k, encryptedKey, joseHeader, options);
}
catch (err) {
if (err instanceof TypeError || err instanceof JWEInvalid || err instanceof JOSENotSupported) {
throw err;
}
cek = generateCek(enc);
}
let iv;
let tag;
if (jwe.iv !== undefined) {
iv = decodeBase64url(jwe.iv, 'iv', JWEInvalid);
}
if (jwe.tag !== undefined) {
tag = decodeBase64url(jwe.tag, 'tag', JWEInvalid);
}
const protectedHeader = jwe.protected !== undefined ? encode(jwe.protected) : new Uint8Array();
let additionalData;
if (jwe.aad !== undefined) {
additionalData = concat(protectedHeader, encode('.'), encode(jwe.aad));
}
else {
additionalData = protectedHeader;
}
const ciphertext = decodeBase64url(jwe.ciphertext, 'ciphertext', JWEInvalid);
const plaintext = await decrypt(enc, cek, ciphertext, iv, tag, additionalData);
const result = { plaintext };
if (joseHeader.zip === 'DEF') {
const maxDecompressedLength = options?.maxDecompressedLength ?? 250_000;
if (maxDecompressedLength === 0) {
throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported.');
}
if (maxDecompressedLength !== Infinity &&
(!Number.isSafeInteger(maxDecompressedLength) || maxDecompressedLength < 1)) {
throw new TypeError('maxDecompressedLength must be 0, a positive safe integer, or Infinity');
}
result.plaintext = await decompress(plaintext, maxDecompressedLength).catch((cause) => {
if (cause instanceof JWEInvalid)
throw cause;
throw new JWEInvalid('Failed to decompress plaintext', { cause });
});
}
if (jwe.protected !== undefined) {
result.protectedHeader = parsedProt;
}
if (jwe.aad !== undefined) {
result.additionalAuthenticatedData = decodeBase64url(jwe.aad, 'aad', JWEInvalid);
}
if (jwe.unprotected !== undefined) {
result.sharedUnprotectedHeader = jwe.unprotected;
}
if (jwe.header !== undefined) {
result.unprotectedHeader = jwe.header;
}
if (resolvedKey) {
return { ...result, key: k };
}
return result;
checkShared(jwe);
checkRecipient(jwe);
return decryptResult(jwe, await decryptJWE(jwe, prepareDecrypt(options), key));
}

@@ -1,12 +0,5 @@

import { encode as b64u } from '../../util/base64url.js';
import { unprotected, assertNotSet } from '../../lib/helpers.js';
import { encrypt } from '../../lib/content_encryption.js';
import { encryptKeyManagement } from '../../lib/key_management.js';
import { JOSENotSupported, JWEInvalid } from '../../util/errors.js';
import { isDisjoint } from '../../lib/type_checks.js';
import { concat, encode } from '../../lib/buffer_utils.js';
import { validateCrit } from '../../lib/validate_crit.js';
import { normalizeKey } from '../../lib/normalize_key.js';
import { checkKeyType } from '../../lib/check_key_type.js';
import { compress } from '../../lib/deflate.js';
import { JWEInvalid } from '../../util/errors.js';
import { createJWE } from '../../lib/jwe_encrypt.js';
import { validateCritDuplicates } from '../../lib/options.js';
export class FlattenedEncrypt {

@@ -65,104 +58,16 @@ #plaintext;

}
if (!isDisjoint(this.#protectedHeader, this.#unprotectedHeader, this.#sharedUnprotectedHeader)) {
throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint');
}
const joseHeader = {
...this.#protectedHeader,
...this.#unprotectedHeader,
...this.#sharedUnprotectedHeader,
};
validateCrit(JWEInvalid, new Map(), options?.crit, this.#protectedHeader, joseHeader);
if (joseHeader.zip !== undefined && joseHeader.zip !== 'DEF') {
throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value.');
}
if (joseHeader.zip !== undefined && !this.#protectedHeader?.zip) {
throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header Parameter MUST be in a protected header.');
}
const { alg, enc } = joseHeader;
if (typeof alg !== 'string' || !alg) {
throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid');
}
if (typeof enc !== 'string' || !enc) {
throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid');
}
let encryptedKey;
if (this.#cek && (alg === 'dir' || alg === 'ECDH-ES')) {
throw new TypeError(`setContentEncryptionKey cannot be called with JWE "alg" (Algorithm) Header ${alg}`);
}
checkKeyType(alg === 'dir' ? enc : alg, key, 'encrypt');
let cek;
{
let parameters;
const k = await normalizeKey(key, alg);
({ cek, encryptedKey, parameters } = await encryptKeyManagement(alg, enc, k, this.#cek, this.#keyManagementParameters));
if (parameters) {
if (options && unprotected in options) {
if (!this.#unprotectedHeader) {
this.setUnprotectedHeader(parameters);
}
else {
this.#unprotectedHeader = { ...this.#unprotectedHeader, ...parameters };
}
}
else if (!this.#protectedHeader) {
this.setProtectedHeader(parameters);
}
else {
this.#protectedHeader = { ...this.#protectedHeader, ...parameters };
}
}
}
let additionalData;
let protectedHeaderS;
let protectedHeaderB;
let aadMember;
if (this.#protectedHeader) {
protectedHeaderS = b64u(JSON.stringify(this.#protectedHeader));
protectedHeaderB = encode(protectedHeaderS);
}
else {
protectedHeaderS = '';
protectedHeaderB = new Uint8Array();
}
if (this.#aad) {
aadMember = b64u(this.#aad);
const aadMemberBytes = encode(aadMember);
additionalData = concat(protectedHeaderB, encode('.'), aadMemberBytes);
}
else {
additionalData = protectedHeaderB;
}
let plaintext = this.#plaintext;
if (joseHeader.zip === 'DEF') {
plaintext = await compress(plaintext).catch((cause) => {
throw new JWEInvalid('Failed to compress plaintext', { cause });
});
}
const { ciphertext, tag, iv } = await encrypt(enc, plaintext, cek, this.#iv, additionalData);
const jwe = {
ciphertext: b64u(ciphertext),
};
if (iv) {
jwe.iv = b64u(iv);
}
if (tag) {
jwe.tag = b64u(tag);
}
if (encryptedKey) {
jwe.encrypted_key = b64u(encryptedKey);
}
if (aadMember) {
jwe.aad = aadMember;
}
if (this.#protectedHeader) {
jwe.protected = protectedHeaderS;
}
if (this.#sharedUnprotectedHeader) {
jwe.unprotected = this.#sharedUnprotectedHeader;
}
if (this.#unprotectedHeader) {
jwe.header = this.#unprotectedHeader;
}
return jwe;
validateCritDuplicates(JWEInvalid, this.#protectedHeader);
return createJWE({
plaintext: this.#plaintext,
protectedHeader: this.#protectedHeader,
unprotectedHeader: this.#unprotectedHeader,
sharedUnprotectedHeader: this.#sharedUnprotectedHeader,
aad: this.#aad,
cek: this.#cek,
iv: this.#iv,
keyManagementParameters: this.#keyManagementParameters,
crit: options?.crit,
unprotectedParameters: options ? unprotected in options : false,
}, key);
}
}

@@ -1,2 +0,2 @@

import { flattenedDecrypt } from '../flattened/decrypt.js';
import { prepareDecrypt, shareJWE, decryptRecipient, decryptResult, checkShared, checkRecipient, } from '../../lib/jwe_decrypt.js';
import { JWEDecryptionFailed, JWEInvalid } from '../../util/errors.js';

@@ -14,5 +14,15 @@ import { isObject } from '../../lib/type_checks.js';

}
let shared;
let token;
try {
checkShared(jwe);
shared = prepareDecrypt(options);
token = shareJWE(jwe);
}
catch {
throw new JWEDecryptionFailed();
}
for (const recipient of jwe.recipients) {
try {
return await flattenedDecrypt({
const flattened = {
aad: jwe.aad,

@@ -26,3 +36,5 @@ ciphertext: jwe.ciphertext,

unprotected: jwe.unprotected,
}, key, options);
};
checkRecipient(flattened);
return decryptResult(flattened, await decryptRecipient(flattened, token, shared, key));
}

@@ -29,0 +41,0 @@ catch {

import { FlattenedEncrypt } from '../flattened/encrypt.js';
import { unprotected, assertNotSet } from '../../lib/helpers.js';
import { JOSENotSupported, JWEInvalid } from '../../util/errors.js';
import { assertNotSet } from '../../lib/helpers.js';
import { JWEInvalid } from '../../util/errors.js';
import { generateCek } from '../../lib/content_encryption.js';
import { isDisjoint } from '../../lib/type_checks.js';
import { encryptKeyManagement } from '../../lib/key_management.js';
import { encode as b64u } from '../../util/base64url.js';
import { validateCrit } from '../../lib/validate_crit.js';
import { normalizeKey } from '../../lib/normalize_key.js';
import { checkKeyType } from '../../lib/check_key_type.js';
import { validateCritDuplicates } from '../../lib/options.js';
import { checkEncryptHeaders, encryptJWE } from '../../lib/jwe_encrypt.js';
import { prepareKey } from '../../lib/key.js';
import { jweAlgorithm } from '../../lib/jwe_algorithms.js';
class IndividualRecipient {

@@ -74,2 +74,5 @@ #parent;

}
if (!(this.#plaintext instanceof Uint8Array)) {
throw new TypeError('plaintext must be an instance of Uint8Array');
}
if (this.#recipients.length === 1) {

@@ -82,2 +85,3 @@ const [recipient] = this.#recipients;

.setUnprotectedHeader(recipient.unprotectedHeader)
.setKeyManagementParameters(recipient.keyManagementParameters)
.encrypt(recipient.key, { ...recipient.options });

@@ -102,38 +106,32 @@ const jwe = {

}
validateCritDuplicates(JWEInvalid, this.#protectedHeader);
let enc;
const inputs = [];
const checked = [];
for (let i = 0; i < this.#recipients.length; i++) {
const recipient = this.#recipients[i];
if (!isDisjoint(this.#protectedHeader, this.#unprotectedHeader, recipient.unprotectedHeader)) {
throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint');
}
const joseHeader = {
...this.#protectedHeader,
...this.#unprotectedHeader,
...recipient.unprotectedHeader,
const input = {
plaintext: this.#plaintext,
protectedHeader: this.#protectedHeader,
unprotectedHeader: recipient.unprotectedHeader,
sharedUnprotectedHeader: this.#unprotectedHeader,
aad: this.#aad,
keyManagementParameters: recipient.keyManagementParameters,
crit: recipient.options.crit,
unprotectedParameters: true,
};
const { alg } = joseHeader;
if (typeof alg !== 'string' || !alg) {
throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid');
}
if (alg === 'dir' || alg === 'ECDH-ES') {
const headers = checkEncryptHeaders(input);
inputs.push(input);
checked.push(headers);
if (headers.alg === 'dir' || headers.alg === 'ECDH-ES') {
throw new JWEInvalid('"dir" and "ECDH-ES" alg may only be used with a single recipient');
}
if (typeof joseHeader.enc !== 'string' || !joseHeader.enc) {
throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid');
}
if (!enc) {
enc = joseHeader.enc;
enc = headers.enc;
}
else if (enc !== joseHeader.enc) {
else if (enc !== headers.enc) {
throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients');
}
validateCrit(JWEInvalid, new Map(), recipient.options.crit, this.#protectedHeader, joseHeader);
if (joseHeader.zip !== undefined && joseHeader.zip !== 'DEF') {
throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value.');
}
if (joseHeader.zip !== undefined && !this.#protectedHeader?.zip) {
throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header Parameter MUST be in a protected header.');
}
}
const cek = generateCek(enc);
const cek = generateCek(checked[0].encEntry);
const jwe = {

@@ -148,13 +146,3 @@ ciphertext: '',

if (i === 0) {
const flattened = await new FlattenedEncrypt(this.#plaintext)
.setAdditionalAuthenticatedData(this.#aad)
.setContentEncryptionKey(cek)
.setProtectedHeader(this.#protectedHeader)
.setSharedUnprotectedHeader(this.#unprotectedHeader)
.setUnprotectedHeader(recipient.unprotectedHeader)
.setKeyManagementParameters(recipient.keyManagementParameters)
.encrypt(recipient.key, {
...recipient.options,
[unprotected]: true,
});
const flattened = await encryptJWE({ ...inputs[0], cek }, checked[0], recipient.key);
jwe.ciphertext = flattened.ciphertext;

@@ -174,8 +162,5 @@ jwe.iv = flattened.iv;

}
const alg = recipient.unprotectedHeader?.alg ||
this.#protectedHeader?.alg ||
this.#unprotectedHeader?.alg;
checkKeyType(alg === 'dir' ? enc : alg, recipient.key, 'encrypt');
const k = await normalizeKey(recipient.key, alg);
const { encryptedKey, parameters } = await encryptKeyManagement(alg, enc, k, cek, recipient.keyManagementParameters);
const { alg } = checked[i];
const k = await prepareKey(jweAlgorithm(alg), recipient.key, 'encrypt');
const { encryptedKey, parameters } = await encryptKeyManagement(alg, checked[i].encEntry, k, cek, recipient.keyManagementParameters);
target.encrypted_key = b64u(encryptedKey);

@@ -182,0 +167,0 @@ if (recipient.unprotectedHeader || parameters)

@@ -1,2 +0,3 @@

import { importJWK } from '../key/import.js';
import { jwkToKey } from '../lib/jwk_to_key.js';
import { jwsAlgorithm } from '../lib/jws_algorithms.js';
import { isObject } from '../lib/type_checks.js';

@@ -12,4 +13,5 @@ import { JWSInvalid } from '../util/errors.js';

}
const key = await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg);
if (key instanceof Uint8Array || key.type !== 'public') {
const entry = jwsAlgorithm(joseHeader.alg);
const key = await jwkToKey(entry, { ...joseHeader.jwk, ext: true });
if (key.type !== 'public') {
throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key');

@@ -16,0 +18,0 @@ }

@@ -1,24 +0,18 @@

import { importJWK } from '../key/import.js';
import { jwkToKey } from '../lib/jwk_to_key.js';
import { maybeJWSAlgorithm } from '../lib/jws_algorithms.js';
import { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys, } from '../util/errors.js';
import { isObject } from '../lib/type_checks.js';
function getKtyFromAlg(alg) {
switch (typeof alg === 'string' && alg.slice(0, 2)) {
case 'RS':
case 'PS':
return 'RSA';
case 'ES':
return 'EC';
case 'Ed':
return 'OKP';
case 'ML':
return 'AKP';
default:
throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set');
function signatureAlgorithm(alg) {
const entry = typeof alg === 'string' ? maybeJWSAlgorithm(alg) : undefined;
if (!entry || entry.symmetric) {
throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set');
}
return entry;
}
function isJWKSLike(jwks) {
return (jwks &&
typeof jwks === 'object' &&
Array.isArray(jwks.keys) &&
jwks.keys.every(isJWKLike));
if (!jwks || typeof jwks !== 'object') {
return false;
}
const { keys } = jwks;
return Array.isArray(keys) && keys.every(isJWKLike);
}

@@ -28,3 +22,3 @@ function isJWKLike(key) {

}
class LocalJWKSet {
class LocalJWKSetImpl {
#jwks;

@@ -43,9 +37,9 @@ #cached = new WeakMap();

const { alg, kid } = { ...protectedHeader, ...token?.header };
const kty = getKtyFromAlg(alg);
const entry = signatureAlgorithm(alg);
const candidates = this.#jwks.keys.filter((jwk) => {
let candidate = kty === jwk.kty;
let candidate = entry.kty.includes(jwk.kty);
if (candidate && typeof kid === 'string') {
candidate = kid === jwk.kid;
}
if (candidate && (typeof jwk.alg === 'string' || kty === 'AKP')) {
if (candidate && (typeof jwk.alg === 'string' || jwk.kty === 'AKP')) {
candidate = alg === jwk.alg;

@@ -59,18 +53,4 @@ }

}
if (candidate) {
switch (alg) {
case 'ES256':
candidate = jwk.crv === 'P-256';
break;
case 'ES384':
candidate = jwk.crv === 'P-384';
break;
case 'ES512':
candidate = jwk.crv === 'P-521';
break;
case 'Ed25519':
case 'EdDSA':
candidate = jwk.crv === 'Ed25519';
break;
}
if (candidate && entry.crv) {
candidate = jwk.crv === entry.crv;
}

@@ -89,3 +69,3 @@ return candidate;

try {
yield await importWithAlgCache(_cached, jwk, alg);
yield await importWithAlgCache(_cached, jwk, entry);
}

@@ -97,18 +77,18 @@ catch { }

}
return importWithAlgCache(this.#cached, jwk, alg);
return importWithAlgCache(this.#cached, jwk, entry);
}
}
async function importWithAlgCache(cache, jwk, alg) {
async function importWithAlgCache(cache, jwk, entry) {
const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk);
if (cached[alg] === undefined) {
const key = await importJWK({ ...jwk, ext: true }, alg);
if (key instanceof Uint8Array || key.type !== 'public') {
if (cached[entry.alg] === undefined) {
const key = await jwkToKey(entry, { ...jwk, alg: entry.alg, ext: true });
if (key.type !== 'public') {
throw new JWKSInvalid('JSON Web Key Set members must be public keys');
}
cached[alg] = key;
cached[entry.alg] = key;
}
return cached[alg];
return cached[entry.alg];
}
export function createLocalJWKSet(jwks) {
const set = new LocalJWKSet(jwks);
const set = new LocalJWKSetImpl(jwks);
const localJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);

@@ -115,0 +95,0 @@ Object.defineProperties(localJWKSet, {

@@ -12,3 +12,3 @@ import { JOSEError, JWKSNoMatchingKey, JWKSTimeout } from '../util/errors.js';

const NAME = 'jose';
const VERSION = 'v6.2.4';
const VERSION = 'v6.2.5';
USER_AGENT = `${NAME}/${VERSION}`;

@@ -55,3 +55,3 @@ }

}
class RemoteJWKSet {
class RemoteJWKSetImpl {
#url;

@@ -149,3 +149,3 @@ #timeoutDuration;

export function createRemoteJWKSet(url, options) {
const set = new RemoteJWKSet(url, options);
const set = new RemoteJWKSetImpl(url, options);
const remoteJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);

@@ -152,0 +152,0 @@ Object.defineProperties(remoteJWKSet, {

import { FlattenedSign } from '../flattened/sign.js';
import { unencodedPayload } from '../../lib/jws_sign.js';
export class CompactSign {
#flattened;
#protectedHeader;
constructor(payload) {

@@ -9,11 +11,12 @@ this.#flattened = new FlattenedSign(payload);

this.#flattened.setProtectedHeader(protectedHeader);
this.#protectedHeader = protectedHeader;
return this;
}
async sign(key, options) {
const jws = await this.#flattened.sign(key, options);
if (jws.payload === undefined) {
if (unencodedPayload(this.#protectedHeader)) {
throw new TypeError('use the flattened module for creating JWS with b64: false');
}
const jws = await this.#flattened.sign(key, options);
return `${jws.protected}.${jws.payload}.${jws.signature}`;
}
}

@@ -1,17 +0,5 @@

import { flattenedVerify } from '../flattened/verify.js';
import { JWSInvalid } from '../../util/errors.js';
import { decoder } from '../../lib/buffer_utils.js';
import { prepareVerify, verifyCompact } from '../../lib/jws_verify.js';
export async function compactVerify(jws, key, options) {
if (jws instanceof Uint8Array) {
jws = decoder.decode(jws);
}
if (typeof jws !== 'string') {
throw new JWSInvalid('Compact JWS must be a string or Uint8Array');
}
const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split('.');
if (length !== 3) {
throw new JWSInvalid('Invalid Compact JWS');
}
const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options);
const result = { payload: verified.payload, protectedHeader: verified.protectedHeader };
const verified = await verifyCompact(jws, prepareVerify(options), key);
const result = { payload: verified.payload, protectedHeader: verified.parsedProt };
if (typeof key === 'function') {

@@ -18,0 +6,0 @@ return { ...result, key: verified.key };

@@ -1,9 +0,3 @@

import { encode as b64u } from '../../util/base64url.js';
import { sign } from '../../lib/signing.js';
import { isDisjoint } from '../../lib/type_checks.js';
import { JWSInvalid } from '../../util/errors.js';
import { concat, encode } from '../../lib/buffer_utils.js';
import { checkKeyType } from '../../lib/check_key_type.js';
import { validateCrit } from '../../lib/validate_crit.js';
import { normalizeKey } from '../../lib/normalize_key.js';
import { createSignature } from '../../lib/jws_sign.js';
import { assertNotSet } from '../../lib/helpers.js';

@@ -34,57 +28,13 @@ export class FlattenedSign {

}
if (!isDisjoint(this.#protectedHeader, this.#unprotectedHeader)) {
throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint');
}
const joseHeader = {
...this.#protectedHeader,
...this.#unprotectedHeader,
};
const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options?.crit, this.#protectedHeader, joseHeader);
let b64 = true;
if (extensions.has('b64')) {
b64 = this.#protectedHeader.b64;
if (typeof b64 !== 'boolean') {
throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
}
}
const { alg } = joseHeader;
if (typeof alg !== 'string' || !alg) {
throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
}
checkKeyType(alg, key, 'sign');
let payloadS;
let payloadB;
if (b64) {
payloadS = b64u(this.#payload);
payloadB = encode(payloadS);
}
else {
payloadB = this.#payload;
payloadS = '';
}
let protectedHeaderString;
let protectedHeaderBytes;
if (this.#protectedHeader) {
protectedHeaderString = b64u(JSON.stringify(this.#protectedHeader));
protectedHeaderBytes = encode(protectedHeaderString);
}
else {
protectedHeaderString = '';
protectedHeaderBytes = new Uint8Array();
}
const data = concat(protectedHeaderBytes, encode('.'), payloadB);
const k = await normalizeKey(key, alg);
const signature = await sign(alg, k, data);
const jws = {
signature: b64u(signature),
payload: payloadS,
};
const jws = await createSignature({
payload: this.#payload,
protectedHeader: this.#protectedHeader,
unprotectedHeader: this.#unprotectedHeader,
crit: options?.crit,
}, key);
if (this.#unprotectedHeader) {
jws.header = this.#unprotectedHeader;
}
if (this.#protectedHeader) {
jws.protected = protectedHeaderString;
}
return jws;
}
}

@@ -1,12 +0,4 @@

import { decode as b64u } from '../../util/base64url.js';
import { verify } from '../../lib/signing.js';
import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js';
import { concat, encoder, decoder, encode } from '../../lib/buffer_utils.js';
import { decodeBase64url } from '../../lib/helpers.js';
import { isDisjoint } from '../../lib/type_checks.js';
import { JWSInvalid } from '../../util/errors.js';
import { isObject } from '../../lib/type_checks.js';
import { checkKeyType } from '../../lib/check_key_type.js';
import { validateCrit } from '../../lib/validate_crit.js';
import { validateAlgorithms } from '../../lib/validate_algorithms.js';
import { normalizeKey } from '../../lib/normalize_key.js';
import { prepareVerify, verifySignature, verifyResult } from '../../lib/jws_verify.js';
export async function flattenedVerify(jws, key, options) {

@@ -31,81 +23,3 @@ if (!isObject(jws)) {

}
let parsedProt = {};
if (jws.protected) {
try {
const protectedHeader = b64u(jws.protected);
parsedProt = JSON.parse(decoder.decode(protectedHeader));
}
catch {
throw new JWSInvalid('JWS Protected Header is invalid');
}
}
if (!isDisjoint(parsedProt, jws.header)) {
throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint');
}
const joseHeader = {
...parsedProt,
...jws.header,
};
const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options?.crit, parsedProt, joseHeader);
let b64 = true;
if (extensions.has('b64')) {
b64 = parsedProt.b64;
if (typeof b64 !== 'boolean') {
throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
}
}
const { alg } = joseHeader;
if (typeof alg !== 'string' || !alg) {
throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
}
const algorithms = options && validateAlgorithms('algorithms', options.algorithms);
if (algorithms && !algorithms.has(alg)) {
throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter value not allowed');
}
if (b64) {
if (typeof jws.payload !== 'string') {
throw new JWSInvalid('JWS Payload must be a string');
}
}
else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) {
throw new JWSInvalid('JWS Payload must be a string or an Uint8Array instance');
}
let resolvedKey = false;
if (typeof key === 'function') {
key = await key(parsedProt, jws);
resolvedKey = true;
}
checkKeyType(alg, key, 'verify');
const data = concat(jws.protected !== undefined ? encode(jws.protected) : new Uint8Array(), encode('.'), typeof jws.payload === 'string'
? b64
? encode(jws.payload)
: encoder.encode(jws.payload)
: jws.payload);
const signature = decodeBase64url(jws.signature, 'signature', JWSInvalid);
const k = await normalizeKey(key, alg);
const verified = await verify(alg, k, signature, data);
if (!verified) {
throw new JWSSignatureVerificationFailed();
}
let payload;
if (b64) {
payload = decodeBase64url(jws.payload, 'payload', JWSInvalid);
}
else if (typeof jws.payload === 'string') {
payload = encoder.encode(jws.payload);
}
else {
payload = jws.payload;
}
const result = { payload };
if (jws.protected !== undefined) {
result.protectedHeader = parsedProt;
}
if (jws.header !== undefined) {
result.unprotectedHeader = jws.header;
}
if (resolvedKey) {
return { ...result, key: k };
}
return result;
return verifyResult(jws, await verifySignature(jws, prepareVerify(options), key));
}

@@ -1,2 +0,2 @@

import { FlattenedSign } from '../flattened/sign.js';
import { createSignature } from '../../lib/jws_sign.js';
import { JWSInvalid } from '../../util/errors.js';

@@ -50,2 +50,5 @@ import { assertNotSet } from '../../lib/helpers.js';

}
if (!(this.#payload instanceof Uint8Array)) {
throw new TypeError('payload must be an instance of Uint8Array');
}
const jws = {

@@ -55,8 +58,18 @@ signatures: [],

};
const encoded = {};
for (let i = 0; i < this.#signatures.length; i++) {
const signature = this.#signatures[i];
const flattened = new FlattenedSign(this.#payload);
flattened.setProtectedHeader(signature.protectedHeader);
flattened.setUnprotectedHeader(signature.unprotectedHeader);
const { payload, ...rest } = await flattened.sign(signature.key, signature.options);
if (!signature.protectedHeader && !signature.unprotectedHeader) {
throw new JWSInvalid('either setProtectedHeader or setUnprotectedHeader must be called before #sign()');
}
const { payload, ...rest } = await createSignature({
payload: this.#payload,
protectedHeader: signature.protectedHeader,
unprotectedHeader: signature.unprotectedHeader,
crit: signature.options?.crit,
encoded,
}, signature.key);
if (signature.unprotectedHeader) {
rest.header = signature.unprotectedHeader;
}
if (i === 0) {

@@ -63,0 +76,0 @@ jws.payload = payload;

@@ -1,2 +0,2 @@

import { flattenedVerify } from '../flattened/verify.js';
import { prepareVerify, verifySignature, verifyResult } from '../../lib/jws_verify.js';
import { JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js';

@@ -11,5 +11,23 @@ import { isObject } from '../../lib/type_checks.js';

}
let shared;
try {
if (jws.payload === undefined)
throw new Error();
shared = prepareVerify(options);
}
catch {
throw new JWSSignatureVerificationFailed();
}
for (const signature of jws.signatures) {
try {
return await flattenedVerify({
if (signature.protected === undefined && signature.header === undefined)
throw new Error();
if (signature.protected !== undefined && typeof signature.protected !== 'string') {
throw new Error();
}
if (typeof signature.signature !== 'string')
throw new Error();
if (signature.header !== undefined && !isObject(signature.header))
throw new Error();
return verifyResult(signature, await verifySignature({
header: signature.header,

@@ -19,3 +37,3 @@ payload: jws.payload,

signature: signature.signature,
}, key, options);
}, shared, key));
}

@@ -22,0 +40,0 @@ catch {

@@ -1,8 +0,8 @@

import { compactDecrypt } from '../jwe/compact/decrypt.js';
import { prepareDecrypt, decryptCompact } from '../lib/jwe_decrypt.js';
import { validateClaimsSet } from '../lib/jwt_claims_set.js';
import { JWTClaimValidationFailed } from '../util/errors.js';
export async function jwtDecrypt(jwt, key, options) {
const decrypted = await compactDecrypt(jwt, key, options);
const payload = validateClaimsSet(decrypted.protectedHeader, decrypted.plaintext, options);
const { protectedHeader } = decrypted;
const decrypted = await decryptCompact(jwt, prepareDecrypt(options), key);
const protectedHeader = decrypted.parsedProt;
const payload = validateClaimsSet(protectedHeader, decrypted.plaintext, options);
if (protectedHeader.iss !== undefined && protectedHeader.iss !== payload.iss) {

@@ -9,0 +9,0 @@ throw new JWTClaimValidationFailed('replicated "iss" claim header parameter mismatch', payload, 'iss', 'mismatch');

import { CompactSign } from '../jws/compact/sign.js';
import { unencodedPayload } from '../lib/jws_sign.js';
import { JWTInvalid } from '../util/errors.js';

@@ -45,5 +46,3 @@ import { JWTClaimsBuilder } from '../lib/jwt_claims_set.js';

sig.setProtectedHeader(this.#protectedHeader);
if (Array.isArray(this.#protectedHeader?.crit) &&
this.#protectedHeader.crit.includes('b64') &&
this.#protectedHeader.b64 === false) {
if (unencodedPayload(this.#protectedHeader)) {
throw new JWTInvalid('JWTs MUST NOT use unencoded payload');

@@ -50,0 +49,0 @@ }

import * as b64u from '../util/base64url.js';
import { decoder } from '../lib/buffer_utils.js';
import { strictDecoder } from '../lib/buffer_utils.js';
import { decodeBase64url } from '../lib/helpers.js';
import { JWTInvalid } from '../util/errors.js';

@@ -53,3 +54,3 @@ import { validateClaimsSet, JWTClaimsBuilder } from '../lib/jwt_claims_set.js';

try {
header = JSON.parse(decoder.decode(b64u.decode(encodedHeader)));
header = JSON.parse(strictDecoder.decode(b64u.decode(encodedHeader)));
if (header.alg !== 'none')

@@ -61,5 +62,5 @@ throw new Error();

}
const payload = validateClaimsSet(header, b64u.decode(encodedPayload), options);
const payload = validateClaimsSet(header, decodeBase64url(encodedPayload, 'payload', JWTInvalid), options);
return { payload, header };
}
}

@@ -1,11 +0,11 @@

import { compactVerify } from '../jws/compact/verify.js';
import { prepareVerify, verifyCompact } from '../lib/jws_verify.js';
import { validateClaimsSet } from '../lib/jwt_claims_set.js';
import { JWTInvalid } from '../util/errors.js';
export async function jwtVerify(jwt, key, options) {
const verified = await compactVerify(jwt, key, options);
if (verified.protectedHeader.crit?.includes('b64') && verified.protectedHeader.b64 === false) {
const verified = await verifyCompact(jwt, prepareVerify(options), key);
if (!verified.b64) {
throw new JWTInvalid('JWTs MUST NOT use unencoded payload');
}
const payload = validateClaimsSet(verified.protectedHeader, verified.payload, options);
const result = { payload, protectedHeader: verified.protectedHeader };
const payload = validateClaimsSet(verified.parsedProt, verified.payload, options);
const result = { payload, protectedHeader: verified.parsedProt };
if (typeof key === 'function') {

@@ -12,0 +12,0 @@ return { ...result, key: verified.key };

import { toSPKI as exportPublic, toPKCS8 as exportPrivate } from '../lib/asn1.js';
import { keyToJWK } from '../lib/key_to_jwk.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) {

@@ -4,0 +37,0 @@ return exportPublic(key);

import { JOSENotSupported } from '../util/errors.js';
import { keyAlgorithm } from '../lib/key_algorithm.js';
function getModulusLengthOption(options) {

@@ -10,89 +11,38 @@ const modulusLength = options?.modulusLength ?? 2048;

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;
let keyUsages;
switch (alg) {
case 'PS256':
case 'PS384':
case 'PS512':
algorithm = {
name: 'RSA-PSS',
hash: `SHA-${alg.slice(-3)}`,
publicExponent: Uint8Array.of(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: Uint8Array.of(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: Uint8Array.of(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;
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');
}
case 'ML-DSA-44':
case 'ML-DSA-65':
case 'ML-DSA-87': {
keyUsages = ['sign', 'verify'];
algorithm = { name: alg };
break;
}
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}`);
}
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;
algorithm =
entry.kty[0] === 'RSA'
? {
...entry.subtle,
publicExponent: Uint8Array.of(0x01, 0x00, 0x01),
modulusLength: getModulusLengthOption(options),
}
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');
: entry.subtle;
}
return crypto.subtle.generateKey(algorithm, options?.extractable ?? false, keyUsages);
return crypto.subtle.generateKey(algorithm, options?.extractable ?? false, [
...entry.usages.private,
...entry.usages.public,
]);
}
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';

@@ -28,5 +29,7 @@ import { isObject } from '../lib/type_checks.js';

}
let ext;
alg ??= jwk.alg;
ext ??= options?.extractable ?? jwk.ext;
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) {

@@ -39,6 +42,3 @@ case 'oct':

case 'RSA':
if ('oth' in jwk && jwk.oth !== undefined) {
throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');
}
return jwkToKey({ ...jwk, alg, ext });
return jwkToKey(keyAlgorithm(alg), { ...jwk, alg, ext });
case 'AKP': {

@@ -51,7 +51,7 @@ if (typeof jwk.alg !== 'string' || !jwk.alg) {

}
return jwkToKey({ ...jwk, ext });
return jwkToKey(keyAlgorithm(jwk.alg), { ...jwk, ext });
}
case 'EC':
case 'OKP':
return jwkToKey({ ...jwk, alg, ext });
return jwkToKey(keyAlgorithm(alg), { ...jwk, alg, ext });
default:

@@ -58,0 +58,0 @@ throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value');

import { invalidKeyInput } from './invalid_key_input.js';
import { encodeBase64, decodeBase64 } from '../lib/base64.js';
import { JOSENotSupported } from '../util/errors.js';
import { keyAlgorithm } from './key_algorithm.js';
import { isCryptoKey, isKeyObject } from './is_key_like.js';

@@ -39,4 +40,11 @@ const formatPEM = (b64, descriptor) => {

const createASN1State = (data) => ({ data, pos: 0 });
const readByte = (state) => {
const byte = state.data[state.pos++];
if (byte === undefined) {
throw new Error('Unexpected end of ASN.1 input');
}
return byte;
};
const parseLength = (state) => {
const first = state.data[state.pos++];
const first = readByte(state);
if (first & 0x80) {

@@ -46,3 +54,3 @@ const lengthOfLen = first & 0x7f;

for (let i = 0; i < lengthOfLen; i++) {
length = (length << 8) | state.data[state.pos++];
length = (length << 8) | readByte(state);
}

@@ -64,3 +72,3 @@ return length;

const expectTag = (state, expectedTag, errorMessage) => {
if (state.data[state.pos++] !== expectedTag) {
if (readByte(state) !== expectedTag) {
throw new Error(errorMessage);

@@ -70,2 +78,5 @@ }

const getSubarray = (state, length) => {
if (length < 0 || state.pos + length > state.data.length) {
throw new Error('Unexpected end of ASN.1 input');
}
const result = state.data.subarray(state.pos, state.pos + length);

@@ -122,67 +133,20 @@ state.pos += length;

const genericImport = async (keyFormat, keyData, alg, options) => {
const entry = keyAlgorithm(alg);
if (entry.symmetric) {
throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value');
}
const isPublic = keyFormat === 'spki';
let algorithm;
let keyUsages;
const isPublic = keyFormat === 'spki';
const getSigUsages = () => (isPublic ? ['verify'] : ['sign']);
const getEncUsages = () => isPublic ? ['encrypt', 'wrapKey'] : ['decrypt', 'unwrapKey'];
switch (alg) {
case 'PS256':
case 'PS384':
case 'PS512':
algorithm = { name: 'RSA-PSS', hash: `SHA-${alg.slice(-3)}` };
keyUsages = getSigUsages();
break;
case 'RS256':
case 'RS384':
case 'RS512':
algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.slice(-3)}` };
keyUsages = getSigUsages();
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}`,
};
keyUsages = getEncUsages();
break;
case 'ES256':
case 'ES384':
case 'ES512': {
const curveMap = { ES256: 'P-256', ES384: 'P-384', ES512: 'P-521' };
algorithm = { name: 'ECDSA', namedCurve: curveMap[alg] };
keyUsages = getSigUsages();
break;
if (entry.subtleFor) {
try {
algorithm = entry.subtleFor({ crv: options.getNamedCurve(keyData) });
}
case 'ECDH-ES':
case 'ECDH-ES+A128KW':
case 'ECDH-ES+A192KW':
case 'ECDH-ES+A256KW': {
try {
const namedCurve = options.getNamedCurve(keyData);
algorithm = namedCurve === 'X25519' ? { name: 'X25519' } : { name: 'ECDH', namedCurve };
}
catch (cause) {
throw new JOSENotSupported('Invalid or unsupported key format');
}
keyUsages = isPublic ? [] : ['deriveBits'];
break;
catch (cause) {
throw new JOSENotSupported('Invalid or unsupported key format');
}
case 'Ed25519':
case 'EdDSA':
algorithm = { name: 'Ed25519' };
keyUsages = getSigUsages();
break;
case 'ML-DSA-44':
case 'ML-DSA-65':
case 'ML-DSA-87':
algorithm = { name: alg };
keyUsages = getSigUsages();
break;
default:
throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value');
}
return crypto.subtle.importKey(keyFormat, keyData, algorithm, options?.extractable ?? (isPublic ? true : false), keyUsages);
else {
algorithm = entry.subtle;
}
return crypto.subtle.importKey(keyFormat, keyData, algorithm, options?.extractable ?? (isPublic ? true : false), isPublic ? entry.usages.public : entry.usages.private);
};

@@ -189,0 +153,0 @@ const processPEMData = (pem, pattern) => {

export const encoder = new TextEncoder();
export const decoder = new TextDecoder();
export const strictDecoder = new TextDecoder('utf-8', { fatal: true });
const MAX_INT32 = 2 ** 32;

@@ -4,0 +5,0 @@ export function concat(...buffers) {

import { concat, uint64be } from './buffer_utils.js';
import { checkEncCryptoKey } from './crypto_key.js';
import { checkCryptoKey } from './crypto_key.js';
import { invalidKeyInput } from './invalid_key_input.js';
import { JOSENotSupported, JWEDecryptionFailed, JWEInvalid } from '../util/errors.js';
import { JWEDecryptionFailed, JWEInvalid } from '../util/errors.js';
import { isCryptoKey } from './is_key_like.js';
export function cekLength(alg) {
switch (alg) {
case 'A128GCM':
return 128;
case 'A192GCM':
return 192;
case 'A256GCM':
case 'A128CBC-HS256':
return 256;
case 'A192CBC-HS384':
return 384;
case 'A256CBC-HS512':
return 512;
default:
throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
}
}
export const generateCek = (alg) => crypto.getRandomValues(new Uint8Array(cekLength(alg) >> 3));
export const generateCek = (enc) => crypto.getRandomValues(new Uint8Array(enc.cekBits >> 3));
function checkCekLength(cek, expected) {

@@ -30,22 +13,5 @@ const actual = cek.byteLength << 3;

}
function ivBitLength(alg) {
switch (alg) {
case 'A128GCM':
case 'A128GCMKW':
case 'A192GCM':
case 'A192GCMKW':
case 'A256GCM':
case 'A256GCMKW':
return 96;
case 'A128CBC-HS256':
case 'A192CBC-HS384':
case 'A256CBC-HS512':
return 128;
default:
throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
}
}
export const generateIv = (alg) => crypto.getRandomValues(new Uint8Array(ivBitLength(alg) >> 3));
export const generateIv = (enc) => crypto.getRandomValues(new Uint8Array(enc.ivBits >> 3));
export function checkIvLength(enc, iv) {
if (iv.length << 3 !== ivBitLength(enc)) {
if (iv.length << 3 !== enc.ivBits) {
throw new JWEInvalid('Invalid Initialization Vector length');

@@ -58,3 +24,3 @@ }

}
const keySize = parseInt(enc.slice(1, 4), 10);
const keySize = enc.cekBits >> 1;
const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, [usage]);

@@ -76,3 +42,3 @@ const macKey = await crypto.subtle.importKey('raw', cek.subarray(0, keySize >> 3), {

}, encKey, plaintext));
const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3));
const macData = concat(aad, iv, ciphertext, uint64be(aad.length * 8));
const tag = await cbcHmacTag(macKey, macData, keySize);

@@ -101,3 +67,3 @@ return { ciphertext, tag, iv };

const { encKey, macKey, keySize } = await cbcKeySetup(enc, cek, 'decrypt');
const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3));
const macData = concat(aad, iv, ciphertext, uint64be(aad.length * 8));
const expectedTag = await cbcHmacTag(macKey, macData, keySize);

@@ -130,3 +96,3 @@ let macCheckPassed;

else {
checkEncCryptoKey(cek, enc, 'encrypt');
checkCryptoKey(cek, enc.subtle, 'encrypt');
encKey = cek;

@@ -150,3 +116,3 @@ }

else {
checkEncCryptoKey(cek, enc, 'decrypt');
checkCryptoKey(cek, enc.subtle, 'decrypt');
encKey = cek;

@@ -166,3 +132,2 @@ }

}
const unsupportedEnc = 'Unsupported JWE Content Encryption Algorithm';
export async function encrypt(enc, plaintext, cek, iv, aad) {

@@ -178,20 +143,8 @@ if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) {

}
switch (enc) {
case 'A128CBC-HS256':
case 'A192CBC-HS384':
case 'A256CBC-HS512':
if (cek instanceof Uint8Array) {
checkCekLength(cek, parseInt(enc.slice(-3), 10));
}
return cbcEncrypt(enc, plaintext, cek, iv, aad);
case 'A128GCM':
case 'A192GCM':
case 'A256GCM':
if (cek instanceof Uint8Array) {
checkCekLength(cek, parseInt(enc.slice(1, 4), 10));
}
return gcmEncrypt(enc, plaintext, cek, iv, aad);
default:
throw new JOSENotSupported(unsupportedEnc);
if (cek instanceof Uint8Array) {
checkCekLength(cek, enc.cekBits);
}
return enc.cbc
? cbcEncrypt(enc, plaintext, cek, iv, aad)
: gcmEncrypt(enc, plaintext, cek, iv, aad);
}

@@ -209,18 +162,8 @@ export async function decrypt(enc, cek, ciphertext, iv, tag, aad) {

checkIvLength(enc, iv);
switch (enc) {
case 'A128CBC-HS256':
case 'A192CBC-HS384':
case 'A256CBC-HS512':
if (cek instanceof Uint8Array)
checkCekLength(cek, parseInt(enc.slice(-3), 10));
return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad);
case 'A128GCM':
case 'A192GCM':
case 'A256GCM':
if (cek instanceof Uint8Array)
checkCekLength(cek, parseInt(enc.slice(1, 4), 10));
return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad);
default:
throw new JOSENotSupported(unsupportedEnc);
if (cek instanceof Uint8Array) {
checkCekLength(cek, enc.cekBits);
}
return enc.cbc
? cbcDecrypt(enc, cek, ciphertext, iv, tag, aad)
: gcmDecrypt(enc, cek, ciphertext, iv, tag, aad);
}
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) {
export function checkUsage(key, usage) {
if (usage && !key.usages.includes(usage)) {

@@ -28,110 +7,17 @@ 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');
export function checkCryptoKey(key, expected, usage) {
const algorithm = key.algorithm;
if (algorithm.name !== expected.name) {
throw unusable(expected.name);
}
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');
if (expected.hash && algorithm.hash?.name !== expected.hash) {
throw unusable(expected.hash, 'algorithm.hash');
}
if (expected.namedCurve && algorithm.namedCurve !== expected.namedCurve) {
throw unusable(expected.namedCurve, 'algorithm.namedCurve');
}
if (expected.length !== undefined && algorithm.length !== expected.length) {
throw unusable(expected.length, 'algorithm.length');
}
checkUsage(key, usage);
}
import { decode } from '../util/base64url.js';
import { encode, strictDecoder } from './buffer_utils.js';
import { isObject } from './type_checks.js';
export const unprotected = Symbol();

@@ -16,2 +18,10 @@ export function assertNotSet(value, name) {

}
export function encodeBase64url(value, label, ErrorClass) {
try {
return encode(value);
}
catch {
throw new ErrorClass(`The ${label} is not a valid base64url string`);
}
}
export async function digest(algorithm, data) {

@@ -21,1 +31,14 @@ const subtleDigest = `SHA-${algorithm.slice(-3)}`;

}
export function parseJoseHeader(b64, ErrorClass, message) {
let parsed;
try {
parsed = JSON.parse(strictDecoder.decode(decode(b64)));
}
catch {
throw new ErrorClass(message);
}
if (!isObject(parsed)) {
throw new ErrorClass(message);
}
return parsed;
}
import { JOSENotSupported } from '../util/errors.js';
const unsupportedAlg = 'Invalid or unsupported JWK "alg" (Algorithm) Parameter value';
function subtleMapping(jwk) {
let algorithm;
let keyUsages;
switch (jwk.kty) {
case 'AKP': {
switch (jwk.alg) {
case 'ML-DSA-44':
case 'ML-DSA-65':
case 'ML-DSA-87':
algorithm = { name: jwk.alg };
keyUsages = jwk.priv ? ['sign'] : ['verify'];
break;
default:
throw new JOSENotSupported(unsupportedAlg);
}
break;
}
case 'RSA': {
switch (jwk.alg) {
case 'PS256':
case 'PS384':
case 'PS512':
algorithm = { name: 'RSA-PSS', hash: `SHA-${jwk.alg.slice(-3)}` };
keyUsages = jwk.d ? ['sign'] : ['verify'];
break;
case 'RS256':
case 'RS384':
case 'RS512':
algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${jwk.alg.slice(-3)}` };
keyUsages = jwk.d ? ['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(jwk.alg.slice(-3), 10) || 1}`,
};
keyUsages = jwk.d ? ['decrypt', 'unwrapKey'] : ['encrypt', 'wrapKey'];
break;
default:
throw new JOSENotSupported(unsupportedAlg);
}
break;
}
case 'EC': {
switch (jwk.alg) {
case 'ES256':
case 'ES384':
case 'ES512':
algorithm = {
name: 'ECDSA',
namedCurve: { ES256: 'P-256', ES384: 'P-384', ES512: 'P-521' }[jwk.alg],
};
keyUsages = jwk.d ? ['sign'] : ['verify'];
break;
case 'ECDH-ES':
case 'ECDH-ES+A128KW':
case 'ECDH-ES+A192KW':
case 'ECDH-ES+A256KW':
algorithm = { name: 'ECDH', namedCurve: jwk.crv };
keyUsages = jwk.d ? ['deriveBits'] : [];
break;
default:
throw new JOSENotSupported(unsupportedAlg);
}
break;
}
case 'OKP': {
switch (jwk.alg) {
case 'Ed25519':
case 'EdDSA':
algorithm = { name: 'Ed25519' };
keyUsages = jwk.d ? ['sign'] : ['verify'];
break;
case 'ECDH-ES':
case 'ECDH-ES+A128KW':
case 'ECDH-ES+A192KW':
case 'ECDH-ES+A256KW':
algorithm = { name: jwk.crv };
keyUsages = jwk.d ? ['deriveBits'] : [];
break;
default:
throw new JOSENotSupported(unsupportedAlg);
}
break;
}
default:
throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value');
function subtleParams(entry, jwk) {
if (!entry.kty.includes(jwk.kty)) {
throw new JOSENotSupported(unsupportedAlg);
}
return { algorithm, keyUsages };
return entry.subtleFor?.({ kty: jwk.kty, crv: jwk.crv }) ?? entry.subtle;
}
export async function jwkToKey(jwk) {
if (!jwk.alg) {
throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
export async function jwkToKey(entry, jwk) {
if (jwk.kty === 'RSA' && 'oth' in jwk && jwk.oth !== undefined) {
throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');
}
const { algorithm, keyUsages } = subtleMapping(jwk);
const algorithm = subtleParams(entry, jwk);
const isPrivate = !!(jwk.d || jwk.priv);
const keyUsages = isPrivate ? entry.usages.private : entry.usages.public;
const keyData = { ...jwk };

@@ -106,3 +21,3 @@ if (keyData.kty !== 'AKP') {

delete keyData.use;
return crypto.subtle.importKey('jwk', keyData, algorithm, jwk.ext ?? (jwk.d || jwk.priv ? false : true), jwk.key_ops ?? keyUsages);
return crypto.subtle.importKey('jwk', keyData, algorithm, jwk.ext ?? (isPrivate ? false : true), jwk.key_ops ?? keyUsages);
}
import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.js';
import { encoder, decoder } from './buffer_utils.js';
import { encoder, strictDecoder } from './buffer_utils.js';
import { isObject } from './type_checks.js';

@@ -84,3 +84,3 @@ const epoch = (date) => Math.floor(date.getTime() / 1000);

try {
payload = JSON.parse(decoder.decode(encodedPayload));
payload = JSON.parse(strictDecoder.decode(encodedPayload));
}

@@ -113,10 +113,10 @@ catch {

}
if (issuer &&
if (issuer !== undefined &&
!(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) {
throw new JWTClaimValidationFailed('unexpected "iss" claim value', payload, 'iss', 'check_failed');
}
if (subject && payload.sub !== subject) {
if (subject !== undefined && payload.sub !== subject) {
throw new JWTClaimValidationFailed('unexpected "sub" claim value', payload, 'sub', 'check_failed');
}
if (audience &&
if (audience !== undefined &&
!checkAudiencePresence(payload.aud, typeof audience === 'string' ? [audience] : audience)) {

@@ -139,5 +139,6 @@ throw new JWTClaimValidationFailed('unexpected "aud" claim value', payload, 'aud', 'check_failed');

}
validateInput('clockTolerance option', tolerance);
const { currentDate } = options;
const now = epoch(currentDate || new Date());
if ((payload.iat !== undefined || maxTokenAge) && typeof payload.iat !== 'number') {
const now = validateInput('currentDate option', epoch(currentDate || new Date()));
if ((payload.iat !== undefined || maxTokenAge !== undefined) && typeof payload.iat !== 'number') {
throw new JWTClaimValidationFailed('"iat" claim must be a number', payload, 'iat', 'invalid');

@@ -161,3 +162,3 @@ }

}
if (maxTokenAge) {
if (maxTokenAge !== undefined) {
const age = now - payload.iat;

@@ -164,0 +165,0 @@ const max = typeof maxTokenAge === 'number' ? maxTokenAge : secs(maxTokenAge);

@@ -1,15 +0,165 @@

import * as aeskw from './aeskw.js';
import * as ecdhes from './ecdhes.js';
import * as pbes2kw from './pbes2kw.js';
import * as rsaes from './rsaes.js';
import { encode as b64u } from '../util/base64url.js';
import { normalizeKey } from './normalize_key.js';
import { prepareKey } from './key.js';
import { jwkToKey } from './jwk_to_key.js';
import { jweAlgorithm, jweEncryption } from './jwe_algorithms.js';
import { JOSENotSupported, JWEInvalid } from '../util/errors.js';
import { decodeBase64url } from './helpers.js';
import { generateCek, cekLength } from './content_encryption.js';
import { importJWK } from '../key/import.js';
import { exportJWK } from '../key/export.js';
import { decodeBase64url, digest } from './helpers.js';
import { generateCek, encrypt, decrypt } from './content_encryption.js';
import { isObject } from './type_checks.js';
import { wrap as aesGcmKwWrap, unwrap as aesGcmKwUnwrap } from './aesgcmkw.js';
import { checkCryptoKey, checkUsage } from './crypto_key.js';
import { checkModulusLength } from './signing.js';
import { concat, encode, uint32be } from './buffer_utils.js';
import { assertCryptoKey } from './is_key_like.js';
function checkEcdhCryptoKey(key, usage) {
switch (key.algorithm.name) {
case 'ECDH':
case 'X25519':
break;
default:
throw new TypeError('CryptoKey does not support this operation, its algorithm.name must be ECDH or X25519');
}
checkUsage(key, usage);
}
function checkKeySize(key, alg) {
if (key.algorithm.length !== parseInt(alg.slice(1, 4), 10)) {
throw new TypeError(`Invalid key size for alg: ${alg}`);
}
}
function aeskwCryptoKey(key, alg, usage) {
if (key instanceof Uint8Array) {
return crypto.subtle.importKey('raw', key, 'AES-KW', true, [usage]);
}
checkCryptoKey(key, jweAlgorithm(alg).subtle, usage);
return key;
}
async function aeskwWrap(alg, key, cek) {
const cryptoKey = await aeskwCryptoKey(key, alg, 'wrapKey');
checkKeySize(cryptoKey, alg);
const cryptoKeyCek = await crypto.subtle.importKey('raw', cek, { hash: 'SHA-256', name: 'HMAC' }, true, ['sign']);
return new Uint8Array(await crypto.subtle.wrapKey('raw', cryptoKeyCek, cryptoKey, 'AES-KW'));
}
async function aeskwUnwrap(alg, key, encryptedKey) {
const cryptoKey = await aeskwCryptoKey(key, alg, 'unwrapKey');
checkKeySize(cryptoKey, alg);
const cryptoKeyCek = await crypto.subtle.unwrapKey('raw', encryptedKey, cryptoKey, 'AES-KW', { hash: 'SHA-256', name: 'HMAC' }, true, ['sign']);
return new Uint8Array(await crypto.subtle.exportKey('raw', cryptoKeyCek));
}
async function aesGcmKwWrap(gcm, key, cek, iv) {
const wrapped = await encrypt(gcm, cek, key, iv, new Uint8Array());
return {
encryptedKey: wrapped.ciphertext,
iv: b64u(wrapped.iv),
tag: b64u(wrapped.tag),
};
}
async function aesGcmKwUnwrap(gcm, key, encryptedKey, iv, tag) {
return decrypt(gcm, key, encryptedKey, iv, tag, new Uint8Array());
}
const subtleAlgorithm = (alg) => {
switch (alg) {
case 'RSA-OAEP':
case 'RSA-OAEP-256':
case 'RSA-OAEP-384':
case 'RSA-OAEP-512':
return 'RSA-OAEP';
default:
throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
}
};
async function rsaesEncrypt(alg, key, cek) {
checkCryptoKey(key, jweAlgorithm(alg).subtle, 'encrypt');
checkModulusLength(alg, key);
return new Uint8Array(await crypto.subtle.encrypt(subtleAlgorithm(alg), key, cek));
}
async function rsaesDecrypt(alg, key, encryptedKey) {
checkCryptoKey(key, jweAlgorithm(alg).subtle, 'decrypt');
checkModulusLength(alg, key);
return new Uint8Array(await crypto.subtle.decrypt(subtleAlgorithm(alg), key, encryptedKey));
}
function pbes2CryptoKey(key, alg) {
if (key instanceof Uint8Array) {
return crypto.subtle.importKey('raw', key, 'PBKDF2', false, [
'deriveBits',
]);
}
checkCryptoKey(key, jweAlgorithm(alg).subtle, 'deriveBits');
return key;
}
const concatSalt = (alg, p2sInput) => concat(encode(alg), Uint8Array.of(0x00), p2sInput);
async function deriveKey(p2s, alg, p2c, key) {
if (!(p2s instanceof Uint8Array) || p2s.length < 8) {
throw new JWEInvalid('PBES2 Salt Input must be 8 or more octets');
}
if (!Number.isSafeInteger(p2c) || Math.sign(p2c) !== 1) {
throw new JWEInvalid('PBES2 Count Input must be a positive integer');
}
const salt = concatSalt(alg, p2s);
const keylen = parseInt(alg.slice(13, 16), 10);
const subtleAlg = {
hash: `SHA-${alg.slice(8, 11)}`,
iterations: p2c,
name: 'PBKDF2',
salt,
};
const cryptoKey = await pbes2CryptoKey(key, alg);
return new Uint8Array(await crypto.subtle.deriveBits(subtleAlg, cryptoKey, keylen));
}
async function pbes2kwWrap(alg, key, cek, p2c = 2048, p2s = crypto.getRandomValues(new Uint8Array(16))) {
const derived = await deriveKey(p2s, alg, p2c, key);
const encryptedKey = await aeskwWrap(alg.slice(-6), derived, cek);
return { encryptedKey, p2c, p2s: b64u(p2s) };
}
async function pbes2kwUnwrap(alg, key, encryptedKey, p2c, p2s) {
const derived = await deriveKey(p2s, alg, p2c, key);
return aeskwUnwrap(alg.slice(-6), derived, encryptedKey);
}
function lengthAndInput(input) {
return concat(uint32be(input.length), input);
}
async function concatKdf(Z, L, OtherInfo) {
const dkLen = L >> 3;
const hashLen = 32;
const reps = Math.ceil(dkLen / hashLen);
const dk = new Uint8Array(reps * hashLen);
for (let i = 1; i <= reps; i++) {
const hashInput = new Uint8Array(4 + Z.length + OtherInfo.length);
hashInput.set(uint32be(i), 0);
hashInput.set(Z, 4);
hashInput.set(OtherInfo, 4 + Z.length);
const hashResult = await digest('sha256', hashInput);
dk.set(hashResult, (i - 1) * hashLen);
}
return dk.slice(0, dkLen);
}
async function ecdhesDeriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(), apv = new Uint8Array()) {
checkEcdhCryptoKey(publicKey);
checkEcdhCryptoKey(privateKey, 'deriveBits');
const algorithmID = lengthAndInput(encode(algorithm));
const partyUInfo = lengthAndInput(apu);
const partyVInfo = lengthAndInput(apv);
const suppPubInfo = uint32be(keyLength);
const suppPrivInfo = new Uint8Array();
const otherInfo = concat(algorithmID, partyUInfo, partyVInfo, suppPubInfo, suppPrivInfo);
const Z = new Uint8Array(await crypto.subtle.deriveBits({
name: publicKey.algorithm.name,
public: publicKey,
}, privateKey, getEcdhBitLength(publicKey)));
return concatKdf(Z, keyLength, otherInfo);
}
function getEcdhBitLength(publicKey) {
if (publicKey.algorithm.name === 'X25519') {
return 256;
}
return (Math.ceil(parseInt(publicKey.algorithm.namedCurve.slice(-3), 10) / 8) << 3);
}
function ecdhesAllowed(key) {
switch (key.algorithm.namedCurve) {
case 'P-256':
case 'P-384':
case 'P-521':
return true;
default:
return key.algorithm.name === 'X25519';
}
}
const unsupportedAlgHeader = 'Invalid or unsupported "alg" (JWE Algorithm) header value';

@@ -20,3 +170,3 @@ function assertEncryptedKey(encryptedKey) {

}
export async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) {
export async function decryptKeyManagement(alg, enc, key, encryptedKey, joseHeader, options) {
switch (alg) {

@@ -37,6 +187,5 @@ case 'dir': {

assertCryptoKey(key);
if (!ecdhes.allowed(key))
if (!ecdhesAllowed(key))
throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
const epk = await importJWK(joseHeader.epk, alg);
assertCryptoKey(epk);
const epk = await jwkToKey(jweAlgorithm(alg), joseHeader.epk);
let partyUInfo;

@@ -54,7 +203,7 @@ let partyVInfo;

}
const sharedSecret = await ecdhes.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? cekLength(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo);
const sharedSecret = await ecdhesDeriveKey(epk, key, alg === 'ECDH-ES' ? enc.alg : alg, alg === 'ECDH-ES' ? enc.cekBits : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo);
if (alg === 'ECDH-ES')
return sharedSecret;
assertEncryptedKey(encryptedKey);
return aeskw.unwrap(alg.slice(-6), sharedSecret, encryptedKey);
return aeskwUnwrap(alg.slice(-6), sharedSecret, encryptedKey);
}

@@ -67,3 +216,3 @@ case 'RSA-OAEP':

assertCryptoKey(key);
return rsaes.decrypt(alg, key, encryptedKey);
return rsaesDecrypt(alg, key, encryptedKey);
}

@@ -83,3 +232,3 @@ case 'PBES2-HS256+A128KW':

p2s = decodeBase64url(joseHeader.p2s, 'p2s', JWEInvalid);
return pbes2kw.unwrap(alg, key, encryptedKey, joseHeader.p2c, p2s);
return pbes2kwUnwrap(alg, key, encryptedKey, joseHeader.p2c, p2s);
}

@@ -90,3 +239,3 @@ case 'A128KW':

assertEncryptedKey(encryptedKey);
return aeskw.unwrap(alg, key, encryptedKey);
return aeskwUnwrap(alg, key, encryptedKey);
}

@@ -105,3 +254,3 @@ case 'A128GCMKW':

tag = decodeBase64url(joseHeader.tag, 'tag', JWEInvalid);
return aesGcmKwUnwrap(alg, key, encryptedKey, iv, tag);
return aesGcmKwUnwrap(jweEncryption(jweAlgorithm(alg).gcmkw), key, encryptedKey, iv, tag);
}

@@ -127,3 +276,3 @@ default: {

assertCryptoKey(key);
if (!ecdhes.allowed(key)) {
if (!ecdhesAllowed(key)) {
throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');

@@ -134,3 +283,3 @@ }

if (providedParameters.epk) {
ephemeralKey = (await normalizeKey(providedParameters.epk, alg));
ephemeralKey = (await prepareKey(jweAlgorithm(alg), providedParameters.epk, 'decrypt'));
}

@@ -140,4 +289,12 @@ else {

}
const { x, y, crv, kty } = await exportJWK(ephemeralKey);
const sharedSecret = await ecdhes.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv);
const subtle = crypto.subtle;
let exportableEpk = ephemeralKey;
if (!exportableEpk.extractable) {
if (typeof subtle.getPublicKey !== 'function') {
throw new TypeError('CryptoKey for "epk" must be extractable');
}
exportableEpk = await subtle.getPublicKey(ephemeralKey, []);
}
const { x, y, crv, kty } = (await subtle.exportKey('jwk', exportableEpk));
const sharedSecret = await ecdhesDeriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc.alg : alg, alg === 'ECDH-ES' ? enc.cekBits : parseInt(alg.slice(-5, -2), 10), apu, apv);
parameters = { epk: { x, crv, kty } };

@@ -156,3 +313,3 @@ if (kty === 'EC')

const kwAlg = alg.slice(-6);
encryptedKey = await aeskw.wrap(kwAlg, sharedSecret, cek);
encryptedKey = await aeskwWrap(kwAlg, sharedSecret, cek);
break;

@@ -166,3 +323,3 @@ }

assertCryptoKey(key);
encryptedKey = await rsaes.encrypt(alg, key, cek);
encryptedKey = await rsaesEncrypt(alg, key, cek);
break;

@@ -175,3 +332,3 @@ }

const { p2c, p2s } = providedParameters;
({ encryptedKey, ...parameters } = await pbes2kw.wrap(alg, key, cek, p2c, p2s));
({ encryptedKey, ...parameters } = await pbes2kwWrap(alg, key, cek, p2c, p2s));
break;

@@ -183,3 +340,3 @@ }

cek = providedCek || generateCek(enc);
encryptedKey = await aeskw.wrap(alg, key, cek);
encryptedKey = await aeskwWrap(alg, key, cek);
break;

@@ -192,3 +349,3 @@ }

const { iv } = providedParameters;
({ encryptedKey, ...parameters } = await aesGcmKwWrap(alg, key, cek, iv));
({ encryptedKey, ...parameters } = await aesGcmKwWrap(jweEncryption(jweAlgorithm(alg).gcmkw), key, cek, iv));
break;

@@ -195,0 +352,0 @@ }

@@ -1,64 +0,32 @@

import { JOSENotSupported } from '../util/errors.js';
import { checkSigCryptoKey } from './crypto_key.js';
import { invalidKeyInput } from './invalid_key_input.js';
export function checkKeyLength(alg, key) {
if (alg.startsWith('RS') || alg.startsWith('PS')) {
const { modulusLength } = key.algorithm;
if (typeof modulusLength !== 'number' || modulusLength < 2048) {
throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);
}
import { checkCryptoKey } from './crypto_key.js';
export function checkModulusLength(alg, key) {
const { modulusLength } = key.algorithm;
if (typeof modulusLength !== 'number' || modulusLength < 2048) {
throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);
}
}
function subtleAlgorithm(alg, algorithm) {
const hash = `SHA-${alg.slice(-3)}`;
switch (alg) {
case 'HS256':
case 'HS384':
case 'HS512':
return { hash, name: 'HMAC' };
case 'PS256':
case 'PS384':
case 'PS512':
return { hash, name: 'RSA-PSS', saltLength: parseInt(alg.slice(-3), 10) >> 3 };
case 'RS256':
case 'RS384':
case 'RS512':
return { hash, name: 'RSASSA-PKCS1-v1_5' };
case 'ES256':
case 'ES384':
case 'ES512':
return { hash, name: 'ECDSA', namedCurve: algorithm.namedCurve };
case 'Ed25519':
case 'EdDSA':
return { name: 'Ed25519' };
case 'ML-DSA-44':
case 'ML-DSA-65':
case 'ML-DSA-87':
return { name: alg };
default:
throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
function checkSigCryptoKey(entry, key, usage) {
checkCryptoKey(key, entry.subtle, usage);
if (entry.minModulusLength) {
checkModulusLength(entry.alg, key);
}
}
async function getSigKey(alg, key, usage) {
async function getSigKey(entry, key, usage) {
if (key instanceof Uint8Array) {
if (!alg.startsWith('HS')) {
throw new TypeError(invalidKeyInput(key, 'CryptoKey', 'KeyObject', 'JSON Web Key'));
}
return crypto.subtle.importKey('raw', key, { hash: `SHA-${alg.slice(-3)}`, name: 'HMAC' }, false, [usage]);
return crypto.subtle.importKey('raw', key, entry.subtle, false, [
usage,
]);
}
checkSigCryptoKey(key, alg, usage);
checkSigCryptoKey(entry, key, usage);
return key;
}
export async function sign(alg, key, data) {
const cryptoKey = await getSigKey(alg, key, 'sign');
checkKeyLength(alg, cryptoKey);
const signature = await crypto.subtle.sign(subtleAlgorithm(alg, cryptoKey.algorithm), cryptoKey, data);
export async function sign(entry, key, data) {
const cryptoKey = await getSigKey(entry, key, 'sign');
const signature = await crypto.subtle.sign(entry.operation, cryptoKey, data);
return new Uint8Array(signature);
}
export async function verify(alg, key, signature, data) {
const cryptoKey = await getSigKey(alg, key, 'verify');
checkKeyLength(alg, cryptoKey);
const algorithm = subtleAlgorithm(alg, cryptoKey.algorithm);
export async function verify(entry, key, signature, data) {
const cryptoKey = await getSigKey(entry, key, 'verify');
try {
return await crypto.subtle.verify(algorithm, cryptoKey, signature, data);
return await crypto.subtle.verify(entry.operation, cryptoKey, signature, data);
}

@@ -65,0 +33,0 @@ catch {

@@ -5,5 +5,10 @@ import { encoder, decoder } from '../lib/buffer_utils.js';

if (Uint8Array.fromBase64) {
return Uint8Array.fromBase64(typeof input === 'string' ? input : decoder.decode(input), {
alphabet: 'base64url',
});
try {
return Uint8Array.fromBase64(typeof input === 'string' ? input : decoder.decode(input), {
alphabet: 'base64url',
});
}
catch (cause) {
throw new TypeError('The input to be decoded is not correctly encoded.', { cause });
}
}

@@ -14,2 +19,5 @@ let encoded = input;

}
if (encoded.includes('+') || encoded.includes('/')) {
throw new TypeError('The input to be decoded is not correctly encoded.');
}
encoded = encoded.replace(/-/g, '+').replace(/_/g, '/');

@@ -16,0 +24,0 @@ try {

import { decode as b64u } from './base64url.js';
import { decoder } from '../lib/buffer_utils.js';
import { strictDecoder } from '../lib/buffer_utils.js';
import { isObject } from '../lib/type_checks.js';

@@ -24,3 +24,3 @@ import { JWTInvalid } from './errors.js';

try {
result = JSON.parse(decoder.decode(decoded));
result = JSON.parse(strictDecoder.decode(decoded));
}

@@ -27,0 +27,0 @@ catch {

@@ -1,4 +0,2 @@

import { decode as b64u } from './base64url.js';
import { decoder } from '../lib/buffer_utils.js';
import { isObject } from '../lib/type_checks.js';
import { parseJoseHeader } from '../lib/helpers.js';
export function decodeProtectedHeader(token) {

@@ -21,15 +19,7 @@ let protectedB64u;

}
try {
if (typeof protectedB64u !== 'string' || !protectedB64u) {
throw new Error();
}
const result = JSON.parse(decoder.decode(b64u(protectedB64u)));
if (!isObject(result)) {
throw new Error();
}
return result;
const invalid = 'Invalid Token or Protected Header formatting';
if (typeof protectedB64u !== 'string' || !protectedB64u) {
throw new TypeError(invalid);
}
catch {
throw new TypeError('Invalid Token or Protected Header formatting');
}
return parseJoseHeader(protectedB64u, TypeError, invalid);
}

@@ -79,3 +79,3 @@ export class JOSEError extends Error {

export class JWKSMultipleMatchingKeys extends JOSEError {
[Symbol.asyncIterator];
[Symbol.asyncIterator] = async function* () { };
static code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS';

@@ -82,0 +82,0 @@ code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS';

{
"name": "jose",
"version": "6.2.4",
"version": "6.2.5",
"description": "JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes",

@@ -196,6 +196,4 @@ "keywords": [

"!dist/**/*.min.js",
"!dist/types/runtime/*",
"!dist/types/lib/*",
"!dist/deno/**/*"
"!dist/types/lib/**"
]
}
+12
-12

@@ -127,15 +127,15 @@ # jose

- JSON Web Signature (JWS) - [RFC7515](https://www.rfc-editor.org/rfc/rfc7515)
- JSON Web Encryption (JWE) - [RFC7516](https://www.rfc-editor.org/rfc/rfc7516)
- JSON Web Key (JWK) - [RFC7517](https://www.rfc-editor.org/rfc/rfc7517)
- JSON Web Algorithms (JWA) - [RFC7518](https://www.rfc-editor.org/rfc/rfc7518)
- JSON Web Token (JWT) - [RFC7519](https://www.rfc-editor.org/rfc/rfc7519)
- JSON Web Key Thumbprint - [RFC7638](https://www.rfc-editor.org/rfc/rfc7638)
- JSON Web Key Thumbprint URI - [RFC9278](https://www.rfc-editor.org/rfc/rfc9278)
- JWS Unencoded Payload Option - [RFC7797](https://www.rfc-editor.org/rfc/rfc7797)
- CFRG Elliptic Curve ECDH and Signatures - [RFC8037](https://www.rfc-editor.org/rfc/rfc8037)
- Fully-Specified Algorithms for JOSE - [RFC9864](https://www.rfc-editor.org/rfc/rfc9864.html)
- ML-DSA for JOSE - [RFC9964](https://www.rfc-editor.org/rfc/rfc9964.html)
- JSON Web Signature (JWS) - [RFC7515](https://www.rfc-editor.org/info/rfc7515/)
- JSON Web Encryption (JWE) - [RFC7516](https://www.rfc-editor.org/info/rfc7516/)
- JSON Web Key (JWK) - [RFC7517](https://www.rfc-editor.org/info/rfc7517/)
- JSON Web Algorithms (JWA) - [RFC7518](https://www.rfc-editor.org/info/rfc7518/)
- JSON Web Token (JWT) - [RFC7519](https://www.rfc-editor.org/info/rfc7519/)
- JSON Web Key Thumbprint - [RFC7638](https://www.rfc-editor.org/info/rfc7638/)
- JSON Web Key Thumbprint URI - [RFC9278](https://www.rfc-editor.org/info/rfc9278/)
- JWS Unencoded Payload Option - [RFC7797](https://www.rfc-editor.org/info/rfc7797/)
- CFRG Elliptic Curve ECDH and Signatures - [RFC8037](https://www.rfc-editor.org/info/rfc8037/)
- Fully-Specified Algorithms for JOSE - [RFC9864](https://www.rfc-editor.org/info/rfc9864/)
- ML-DSA for JOSE - [RFC9964](https://www.rfc-editor.org/info/rfc9964/)
The algorithm implementations in `jose` have been tested using test vectors from their respective specifications as well as [RFC7520](https://www.rfc-editor.org/rfc/rfc7520).
The algorithm implementations in `jose` have been tested using test vectors from their respective specifications as well as [RFC7520](https://www.rfc-editor.org/info/rfc7520/).

@@ -142,0 +142,0 @@ </details>

import { encrypt, decrypt } from './content_encryption.js';
import { encode as b64u } from '../util/base64url.js';
export async function wrap(alg, key, cek, iv) {
const jweAlgorithm = alg.slice(0, 7);
const wrapped = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array());
return {
encryptedKey: wrapped.ciphertext,
iv: b64u(wrapped.iv),
tag: b64u(wrapped.tag),
};
}
export async function unwrap(alg, key, encryptedKey, iv, tag) {
const jweAlgorithm = alg.slice(0, 7);
return decrypt(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array());
}
import { checkEncCryptoKey } from './crypto_key.js';
function checkKeySize(key, alg) {
if (key.algorithm.length !== parseInt(alg.slice(1, 4), 10)) {
throw new TypeError(`Invalid key size for alg: ${alg}`);
}
}
function getCryptoKey(key, alg, usage) {
if (key instanceof Uint8Array) {
return crypto.subtle.importKey('raw', key, 'AES-KW', true, [usage]);
}
checkEncCryptoKey(key, alg, usage);
return key;
}
export async function wrap(alg, key, cek) {
const cryptoKey = await getCryptoKey(key, alg, 'wrapKey');
checkKeySize(cryptoKey, alg);
const cryptoKeyCek = await crypto.subtle.importKey('raw', cek, { hash: 'SHA-256', name: 'HMAC' }, true, ['sign']);
return new Uint8Array(await crypto.subtle.wrapKey('raw', cryptoKeyCek, cryptoKey, 'AES-KW'));
}
export async function unwrap(alg, key, encryptedKey) {
const cryptoKey = await getCryptoKey(key, alg, 'unwrapKey');
checkKeySize(cryptoKey, alg);
const cryptoKeyCek = await crypto.subtle.unwrapKey('raw', encryptedKey, cryptoKey, 'AES-KW', { hash: 'SHA-256', name: 'HMAC' }, true, ['sign']);
return new Uint8Array(await crypto.subtle.exportKey('raw', cryptoKeyCek));
}
import { withAlg as invalidKeyInput } from './invalid_key_input.js';
import { isKeyLike } from './is_key_like.js';
import * as jwk from './type_checks.js';
const tag = (key) => key?.[Symbol.toStringTag];
const jwkMatchesOp = (alg, key, usage) => {
if (key.use !== undefined) {
let expected;
switch (usage) {
case 'sign':
case 'verify':
expected = 'sig';
break;
case 'encrypt':
case 'decrypt':
expected = 'enc';
break;
}
if (key.use !== expected) {
throw new TypeError(`Invalid key for this operation, its "use" must be "${expected}" when present`);
}
}
if (key.alg !== undefined && key.alg !== alg) {
throw new TypeError(`Invalid key for this operation, its "alg" must be "${alg}" when present`);
}
if (Array.isArray(key.key_ops)) {
let expectedKeyOp;
switch (true) {
case usage === 'sign' || usage === 'verify':
case alg === 'dir':
case alg.includes('CBC-HS'):
expectedKeyOp = usage;
break;
case alg.startsWith('PBES2'):
expectedKeyOp = 'deriveBits';
break;
case /^A\d{3}(?:GCM)?(?:KW)?$/.test(alg):
if (!alg.includes('GCM') && alg.endsWith('KW')) {
expectedKeyOp = usage === 'encrypt' ? 'wrapKey' : 'unwrapKey';
}
else {
expectedKeyOp = usage;
}
break;
case usage === 'encrypt' && alg.startsWith('RSA'):
expectedKeyOp = 'wrapKey';
break;
case usage === 'decrypt':
expectedKeyOp = alg.startsWith('RSA') ? 'unwrapKey' : 'deriveBits';
break;
}
if (expectedKeyOp && key.key_ops?.includes?.(expectedKeyOp) === false) {
throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${expectedKeyOp}" when present`);
}
}
return true;
};
const symmetricTypeCheck = (alg, key, usage) => {
if (key instanceof Uint8Array)
return;
if (jwk.isJWK(key)) {
if (jwk.isSecretJWK(key) && jwkMatchesOp(alg, key, usage))
return;
throw new TypeError(`JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present`);
}
if (!isKeyLike(key)) {
throw new TypeError(invalidKeyInput(alg, key, 'CryptoKey', 'KeyObject', 'JSON Web Key', 'Uint8Array'));
}
if (key.type !== 'secret') {
throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type "secret"`);
}
};
const asymmetricTypeCheck = (alg, key, usage) => {
if (jwk.isJWK(key)) {
switch (usage) {
case 'decrypt':
case 'sign':
if (jwk.isPrivateJWK(key) && jwkMatchesOp(alg, key, usage))
return;
throw new TypeError(`JSON Web Key for this operation must be a private JWK`);
case 'encrypt':
case 'verify':
if (jwk.isPublicJWK(key) && jwkMatchesOp(alg, key, usage))
return;
throw new TypeError(`JSON Web Key for this operation must be a public JWK`);
}
}
if (!isKeyLike(key)) {
throw new TypeError(invalidKeyInput(alg, key, 'CryptoKey', 'KeyObject', 'JSON Web Key'));
}
if (key.type === 'secret') {
throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type "secret"`);
}
if (key.type === 'public') {
switch (usage) {
case 'sign':
throw new TypeError(`${tag(key)} instances for asymmetric algorithm signing must be of type "private"`);
case 'decrypt':
throw new TypeError(`${tag(key)} instances for asymmetric algorithm decryption must be of type "private"`);
}
}
if (key.type === 'private') {
switch (usage) {
case 'verify':
throw new TypeError(`${tag(key)} instances for asymmetric algorithm verifying must be of type "public"`);
case 'encrypt':
throw new TypeError(`${tag(key)} instances for asymmetric algorithm encryption must be of type "public"`);
}
}
};
export function checkKeyType(alg, key, usage) {
switch (alg.substring(0, 2)) {
case 'A1':
case 'A2':
case 'di':
case 'HS':
case 'PB':
symmetricTypeCheck(alg, key, usage);
break;
default:
asymmetricTypeCheck(alg, key, usage);
}
}
import { encode, concat, uint32be } from './buffer_utils.js';
import { checkEncCryptoKey } from './crypto_key.js';
import { digest } from './helpers.js';
function lengthAndInput(input) {
return concat(uint32be(input.length), input);
}
async function concatKdf(Z, L, OtherInfo) {
const dkLen = L >> 3;
const hashLen = 32;
const reps = Math.ceil(dkLen / hashLen);
const dk = new Uint8Array(reps * hashLen);
for (let i = 1; i <= reps; i++) {
const hashInput = new Uint8Array(4 + Z.length + OtherInfo.length);
hashInput.set(uint32be(i), 0);
hashInput.set(Z, 4);
hashInput.set(OtherInfo, 4 + Z.length);
const hashResult = await digest('sha256', hashInput);
dk.set(hashResult, (i - 1) * hashLen);
}
return dk.slice(0, dkLen);
}
export async function deriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(), apv = new Uint8Array()) {
checkEncCryptoKey(publicKey, 'ECDH');
checkEncCryptoKey(privateKey, 'ECDH', 'deriveBits');
const algorithmID = lengthAndInput(encode(algorithm));
const partyUInfo = lengthAndInput(apu);
const partyVInfo = lengthAndInput(apv);
const suppPubInfo = uint32be(keyLength);
const suppPrivInfo = new Uint8Array();
const otherInfo = concat(algorithmID, partyUInfo, partyVInfo, suppPubInfo, suppPrivInfo);
const Z = new Uint8Array(await crypto.subtle.deriveBits({
name: publicKey.algorithm.name,
public: publicKey,
}, privateKey, getEcdhBitLength(publicKey)));
return concatKdf(Z, keyLength, otherInfo);
}
function getEcdhBitLength(publicKey) {
if (publicKey.algorithm.name === 'X25519') {
return 256;
}
return (Math.ceil(parseInt(publicKey.algorithm.namedCurve.slice(-3), 10) / 8) << 3);
}
export function allowed(key) {
switch (key.algorithm.namedCurve) {
case 'P-256':
case 'P-384':
case 'P-521':
return true;
default:
return key.algorithm.name === 'X25519';
}
}
import { invalidKeyInput } from './invalid_key_input.js';
import { encode as b64u } from '../util/base64url.js';
import { isCryptoKey, isKeyObject } from './is_key_like.js';
function omitUndefinedProperties(jwk) {
return Object.fromEntries(Object.entries(jwk).filter(([, value]) => value !== undefined));
}
export 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;
}
import { isJWK } from './type_checks.js';
import { decode } from '../util/base64url.js';
import { jwkToKey } from './jwk_to_key.js';
import { isCryptoKey, isKeyObject } from './is_key_like.js';
const unusableForAlg = 'given KeyObject instance cannot be used for this algorithm';
let cache;
const handleJWK = async (key, jwk, alg, freeze = false) => {
cache ||= new WeakMap();
let cached = cache.get(key);
if (cached?.[alg]) {
return cached[alg];
}
const cryptoKey = await jwkToKey({ ...jwk, alg });
if (freeze)
Object.freeze(key);
if (!cached) {
cache.set(key, { [alg]: cryptoKey });
}
else {
cached[alg] = cryptoKey;
}
return cryptoKey;
};
const handleKeyObject = (keyObject, alg) => {
cache ||= new WeakMap();
let cached = cache.get(keyObject);
if (cached?.[alg]) {
return cached[alg];
}
const isPublic = keyObject.type === 'public';
const extractable = isPublic ? true : false;
let cryptoKey;
if (keyObject.asymmetricKeyType === 'x25519') {
switch (alg) {
case 'ECDH-ES':
case 'ECDH-ES+A128KW':
case 'ECDH-ES+A192KW':
case 'ECDH-ES+A256KW':
break;
default:
throw new TypeError(unusableForAlg);
}
cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, isPublic ? [] : ['deriveBits']);
}
if (keyObject.asymmetricKeyType === 'ed25519') {
if (alg !== 'EdDSA' && alg !== 'Ed25519') {
throw new TypeError(unusableForAlg);
}
cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [
isPublic ? 'verify' : 'sign',
]);
}
switch (keyObject.asymmetricKeyType) {
case 'ml-dsa-44':
case 'ml-dsa-65':
case 'ml-dsa-87': {
if (alg !== keyObject.asymmetricKeyType.toUpperCase()) {
throw new TypeError(unusableForAlg);
}
cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [
isPublic ? 'verify' : 'sign',
]);
}
}
if (keyObject.asymmetricKeyType === 'rsa') {
let hash;
switch (alg) {
case 'RSA-OAEP':
hash = 'SHA-1';
break;
case 'RS256':
case 'PS256':
case 'RSA-OAEP-256':
hash = 'SHA-256';
break;
case 'RS384':
case 'PS384':
case 'RSA-OAEP-384':
hash = 'SHA-384';
break;
case 'RS512':
case 'PS512':
case 'RSA-OAEP-512':
hash = 'SHA-512';
break;
default:
throw new TypeError(unusableForAlg);
}
if (alg.startsWith('RSA-OAEP')) {
return keyObject.toCryptoKey({
name: 'RSA-OAEP',
hash,
}, extractable, isPublic ? ['encrypt'] : ['decrypt']);
}
cryptoKey = keyObject.toCryptoKey({
name: alg.startsWith('PS') ? 'RSA-PSS' : 'RSASSA-PKCS1-v1_5',
hash,
}, extractable, [isPublic ? 'verify' : 'sign']);
}
if (keyObject.asymmetricKeyType === 'ec') {
const nist = new Map([
['prime256v1', 'P-256'],
['secp384r1', 'P-384'],
['secp521r1', 'P-521'],
]);
const namedCurve = nist.get(keyObject.asymmetricKeyDetails?.namedCurve);
if (!namedCurve) {
throw new TypeError(unusableForAlg);
}
const expectedCurve = { ES256: 'P-256', ES384: 'P-384', ES512: 'P-521' };
if (expectedCurve[alg] && namedCurve === expectedCurve[alg]) {
cryptoKey = keyObject.toCryptoKey({
name: 'ECDSA',
namedCurve,
}, extractable, [isPublic ? 'verify' : 'sign']);
}
if (alg.startsWith('ECDH-ES')) {
cryptoKey = keyObject.toCryptoKey({
name: 'ECDH',
namedCurve,
}, extractable, isPublic ? [] : ['deriveBits']);
}
}
if (!cryptoKey) {
throw new TypeError(unusableForAlg);
}
if (!cached) {
cache.set(keyObject, { [alg]: cryptoKey });
}
else {
cached[alg] = cryptoKey;
}
return cryptoKey;
};
export async function normalizeKey(key, alg) {
if (key instanceof Uint8Array) {
return key;
}
if (isCryptoKey(key)) {
return key;
}
if (isKeyObject(key)) {
if (key.type === 'secret') {
return key.export();
}
if ('toCryptoKey' in key && typeof key.toCryptoKey === 'function') {
try {
return handleKeyObject(key, alg);
}
catch (err) {
if (err instanceof TypeError) {
throw err;
}
}
}
let jwk = key.export({ format: 'jwk' });
return handleJWK(key, jwk, alg);
}
if (isJWK(key)) {
if (key.k) {
return decode(key.k);
}
return handleJWK(key, key, alg, true);
}
throw new Error('unreachable');
}
import { encode as b64u } from '../util/base64url.js';
import * as aeskw from './aeskw.js';
import { checkEncCryptoKey } from './crypto_key.js';
import { concat, encode } from './buffer_utils.js';
import { JWEInvalid } from '../util/errors.js';
function getCryptoKey(key, alg) {
if (key instanceof Uint8Array) {
return crypto.subtle.importKey('raw', key, 'PBKDF2', false, [
'deriveBits',
]);
}
checkEncCryptoKey(key, alg, 'deriveBits');
return key;
}
const concatSalt = (alg, p2sInput) => concat(encode(alg), Uint8Array.of(0x00), p2sInput);
async function deriveKey(p2s, alg, p2c, key) {
if (!(p2s instanceof Uint8Array) || p2s.length < 8) {
throw new JWEInvalid('PBES2 Salt Input must be 8 or more octets');
}
if (!Number.isSafeInteger(p2c) || Math.sign(p2c) !== 1) {
throw new JWEInvalid('PBES2 Count Input must be a positive integer');
}
const salt = concatSalt(alg, p2s);
const keylen = parseInt(alg.slice(13, 16), 10);
const subtleAlg = {
hash: `SHA-${alg.slice(8, 11)}`,
iterations: p2c,
name: 'PBKDF2',
salt,
};
const cryptoKey = await getCryptoKey(key, alg);
return new Uint8Array(await crypto.subtle.deriveBits(subtleAlg, cryptoKey, keylen));
}
export async function wrap(alg, key, cek, p2c = 2048, p2s = crypto.getRandomValues(new Uint8Array(16))) {
const derived = await deriveKey(p2s, alg, p2c, key);
const encryptedKey = await aeskw.wrap(alg.slice(-6), derived, cek);
return { encryptedKey, p2c, p2s: b64u(p2s) };
}
export async function unwrap(alg, key, encryptedKey, p2c, p2s) {
const derived = await deriveKey(p2s, alg, p2c, key);
return aeskw.unwrap(alg.slice(-6), derived, encryptedKey);
}
import { checkEncCryptoKey } from './crypto_key.js';
import { checkKeyLength } from './signing.js';
import { JOSENotSupported } from '../util/errors.js';
const subtleAlgorithm = (alg) => {
switch (alg) {
case 'RSA-OAEP':
case 'RSA-OAEP-256':
case 'RSA-OAEP-384':
case 'RSA-OAEP-512':
return 'RSA-OAEP';
default:
throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
}
};
export async function encrypt(alg, key, cek) {
checkEncCryptoKey(key, alg, 'encrypt');
checkKeyLength(alg, key);
return new Uint8Array(await crypto.subtle.encrypt(subtleAlgorithm(alg), key, cek));
}
export async function decrypt(alg, key, encryptedKey) {
checkEncCryptoKey(key, alg, 'decrypt');
checkKeyLength(alg, key);
return new Uint8Array(await crypto.subtle.decrypt(subtleAlgorithm(alg), key, encryptedKey));
}
export function validateAlgorithms(option, algorithms) {
if (algorithms !== undefined &&
(!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) {
throw new TypeError(`"${option}" option must be an array of strings`);
}
if (!algorithms) {
return undefined;
}
return new Set(algorithms);
}
import { JOSENotSupported, JWEInvalid, JWSInvalid } from '../util/errors.js';
export function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
if (joseHeader.crit !== undefined && protectedHeader?.crit === undefined) {
throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
}
if (!protectedHeader || protectedHeader.crit === undefined) {
return new Set();
}
if (!Array.isArray(protectedHeader.crit) ||
protectedHeader.crit.length === 0 ||
protectedHeader.crit.some((input) => typeof input !== 'string' || input.length === 0)) {
throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');
}
let recognized;
if (recognizedOption !== undefined) {
recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]);
}
else {
recognized = recognizedDefault;
}
for (const parameter of protectedHeader.crit) {
if (!recognized.has(parameter)) {
throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`);
}
if (joseHeader[parameter] === undefined) {
throw new Err(`Extension Header Parameter "${parameter}" is missing`);
}
if (recognized.get(parameter) && protectedHeader[parameter] === undefined) {
throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`);
}
}
return new Set(protectedHeader.crit);
}