mirror of
https://github.com/danbulant/jose
synced 2026-05-24 12:35:36 +00:00
3251 lines
107 KiB
JavaScript
3251 lines
107 KiB
JavaScript
var __defProp = Object.defineProperty;
|
|
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
|
|
var __export = (target, all) => {
|
|
__markAsModule(target);
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
|
|
// dist/browser/lib/buffer_utils.js
|
|
var encoder = new TextEncoder();
|
|
var decoder = new TextDecoder();
|
|
var MAX_INT32 = 2 ** 32;
|
|
function concat(...buffers) {
|
|
const size = buffers.reduce((acc, { length }) => acc + length, 0);
|
|
const buf = new Uint8Array(size);
|
|
let i = 0;
|
|
buffers.forEach((buffer) => {
|
|
buf.set(buffer, i);
|
|
i += buffer.length;
|
|
});
|
|
return buf;
|
|
}
|
|
function p2s(alg, p2sInput) {
|
|
return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput);
|
|
}
|
|
function writeUInt32BE(buf, value, offset) {
|
|
if (value < 0 || value >= MAX_INT32) {
|
|
throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`);
|
|
}
|
|
buf.set([value >>> 24, value >>> 16, value >>> 8, value & 255], offset);
|
|
}
|
|
function uint64be(value) {
|
|
const high = Math.floor(value / MAX_INT32);
|
|
const low = value % MAX_INT32;
|
|
const buf = new Uint8Array(8);
|
|
writeUInt32BE(buf, high, 0);
|
|
writeUInt32BE(buf, low, 4);
|
|
return buf;
|
|
}
|
|
function uint32be(value) {
|
|
const buf = new Uint8Array(4);
|
|
writeUInt32BE(buf, value);
|
|
return buf;
|
|
}
|
|
function lengthAndInput(input) {
|
|
return concat(uint32be(input.length), input);
|
|
}
|
|
async function concatKdf(digest2, secret, bits, value) {
|
|
const iterations = Math.ceil((bits >> 3) / 32);
|
|
let res;
|
|
for (let iter = 1; iter <= iterations; iter++) {
|
|
const buf = new Uint8Array(4 + secret.length + value.length);
|
|
buf.set(uint32be(iter));
|
|
buf.set(secret, 4);
|
|
buf.set(value, 4 + secret.length);
|
|
if (!res) {
|
|
res = await digest2("sha256", buf);
|
|
} else {
|
|
res = concat(res, await digest2("sha256", buf));
|
|
}
|
|
}
|
|
res = res.slice(0, bits >> 3);
|
|
return res;
|
|
}
|
|
|
|
// dist/browser/runtime/base64url.js
|
|
var encodeBase64 = (input) => {
|
|
let unencoded = input;
|
|
if (typeof unencoded === "string") {
|
|
unencoded = encoder.encode(unencoded);
|
|
}
|
|
const CHUNK_SIZE = 32768;
|
|
const arr = [];
|
|
for (let i = 0; i < unencoded.length; i += CHUNK_SIZE) {
|
|
arr.push(String.fromCharCode.apply(null, unencoded.subarray(i, i + CHUNK_SIZE)));
|
|
}
|
|
return btoa(arr.join(""));
|
|
};
|
|
var encode = (input) => {
|
|
return encodeBase64(input).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
};
|
|
var decodeBase64 = (encoded) => {
|
|
return new Uint8Array(atob(encoded).split("").map((c) => c.charCodeAt(0)));
|
|
};
|
|
var decode = (input) => {
|
|
let encoded = input;
|
|
if (encoded instanceof Uint8Array) {
|
|
encoded = decoder.decode(encoded);
|
|
}
|
|
encoded = encoded.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, "");
|
|
try {
|
|
return decodeBase64(encoded);
|
|
} catch (_a) {
|
|
throw new TypeError("The input to be decoded is not correctly encoded.");
|
|
}
|
|
};
|
|
|
|
// dist/browser/util/errors.js
|
|
var errors_exports = {};
|
|
__export(errors_exports, {
|
|
JOSEAlgNotAllowed: () => JOSEAlgNotAllowed,
|
|
JOSEError: () => JOSEError,
|
|
JOSENotSupported: () => JOSENotSupported,
|
|
JWEDecryptionFailed: () => JWEDecryptionFailed,
|
|
JWEInvalid: () => JWEInvalid,
|
|
JWKInvalid: () => JWKInvalid,
|
|
JWKSInvalid: () => JWKSInvalid,
|
|
JWKSMultipleMatchingKeys: () => JWKSMultipleMatchingKeys,
|
|
JWKSNoMatchingKey: () => JWKSNoMatchingKey,
|
|
JWKSTimeout: () => JWKSTimeout,
|
|
JWSInvalid: () => JWSInvalid,
|
|
JWSSignatureVerificationFailed: () => JWSSignatureVerificationFailed,
|
|
JWTClaimValidationFailed: () => JWTClaimValidationFailed,
|
|
JWTExpired: () => JWTExpired,
|
|
JWTInvalid: () => JWTInvalid
|
|
});
|
|
var JOSEError = class extends Error {
|
|
constructor(message) {
|
|
var _a;
|
|
super(message);
|
|
this.code = "ERR_JOSE_GENERIC";
|
|
this.name = this.constructor.name;
|
|
(_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor);
|
|
}
|
|
static get code() {
|
|
return "ERR_JOSE_GENERIC";
|
|
}
|
|
};
|
|
var JWTClaimValidationFailed = class extends JOSEError {
|
|
constructor(message, claim = "unspecified", reason = "unspecified") {
|
|
super(message);
|
|
this.code = "ERR_JWT_CLAIM_VALIDATION_FAILED";
|
|
this.claim = claim;
|
|
this.reason = reason;
|
|
}
|
|
static get code() {
|
|
return "ERR_JWT_CLAIM_VALIDATION_FAILED";
|
|
}
|
|
};
|
|
var JWTExpired = class extends JOSEError {
|
|
constructor(message, claim = "unspecified", reason = "unspecified") {
|
|
super(message);
|
|
this.code = "ERR_JWT_EXPIRED";
|
|
this.claim = claim;
|
|
this.reason = reason;
|
|
}
|
|
static get code() {
|
|
return "ERR_JWT_EXPIRED";
|
|
}
|
|
};
|
|
var JOSEAlgNotAllowed = class extends JOSEError {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.code = "ERR_JOSE_ALG_NOT_ALLOWED";
|
|
}
|
|
static get code() {
|
|
return "ERR_JOSE_ALG_NOT_ALLOWED";
|
|
}
|
|
};
|
|
var JOSENotSupported = class extends JOSEError {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.code = "ERR_JOSE_NOT_SUPPORTED";
|
|
}
|
|
static get code() {
|
|
return "ERR_JOSE_NOT_SUPPORTED";
|
|
}
|
|
};
|
|
var JWEDecryptionFailed = class extends JOSEError {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.code = "ERR_JWE_DECRYPTION_FAILED";
|
|
this.message = "decryption operation failed";
|
|
}
|
|
static get code() {
|
|
return "ERR_JWE_DECRYPTION_FAILED";
|
|
}
|
|
};
|
|
var JWEInvalid = class extends JOSEError {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.code = "ERR_JWE_INVALID";
|
|
}
|
|
static get code() {
|
|
return "ERR_JWE_INVALID";
|
|
}
|
|
};
|
|
var JWSInvalid = class extends JOSEError {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.code = "ERR_JWS_INVALID";
|
|
}
|
|
static get code() {
|
|
return "ERR_JWS_INVALID";
|
|
}
|
|
};
|
|
var JWTInvalid = class extends JOSEError {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.code = "ERR_JWT_INVALID";
|
|
}
|
|
static get code() {
|
|
return "ERR_JWT_INVALID";
|
|
}
|
|
};
|
|
var JWKInvalid = class extends JOSEError {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.code = "ERR_JWK_INVALID";
|
|
}
|
|
static get code() {
|
|
return "ERR_JWK_INVALID";
|
|
}
|
|
};
|
|
var JWKSInvalid = class extends JOSEError {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.code = "ERR_JWKS_INVALID";
|
|
}
|
|
static get code() {
|
|
return "ERR_JWKS_INVALID";
|
|
}
|
|
};
|
|
var JWKSNoMatchingKey = class extends JOSEError {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.code = "ERR_JWKS_NO_MATCHING_KEY";
|
|
this.message = "no applicable key found in the JSON Web Key Set";
|
|
}
|
|
static get code() {
|
|
return "ERR_JWKS_NO_MATCHING_KEY";
|
|
}
|
|
};
|
|
var JWKSMultipleMatchingKeys = class extends JOSEError {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.code = "ERR_JWKS_MULTIPLE_MATCHING_KEYS";
|
|
this.message = "multiple matching keys found in the JSON Web Key Set";
|
|
}
|
|
static get code() {
|
|
return "ERR_JWKS_MULTIPLE_MATCHING_KEYS";
|
|
}
|
|
};
|
|
var JWKSTimeout = class extends JOSEError {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.code = "ERR_JWKS_TIMEOUT";
|
|
this.message = "request timed out";
|
|
}
|
|
static get code() {
|
|
return "ERR_JWKS_TIMEOUT";
|
|
}
|
|
};
|
|
var JWSSignatureVerificationFailed = class extends JOSEError {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED";
|
|
this.message = "signature verification failed";
|
|
}
|
|
static get code() {
|
|
return "ERR_JWS_SIGNATURE_VERIFICATION_FAILED";
|
|
}
|
|
};
|
|
|
|
// dist/browser/runtime/webcrypto.js
|
|
var webcrypto_default = crypto;
|
|
function isCryptoKey(key) {
|
|
try {
|
|
return key != null && typeof key.extractable === "boolean" && typeof key.algorithm.name === "string" && typeof key.type === "string";
|
|
} catch (_a) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// dist/browser/runtime/random.js
|
|
var random_default = webcrypto_default.getRandomValues.bind(webcrypto_default);
|
|
|
|
// dist/browser/lib/iv.js
|
|
function bitLength(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}`);
|
|
}
|
|
}
|
|
var iv_default = (alg) => random_default(new Uint8Array(bitLength(alg) >> 3));
|
|
|
|
// dist/browser/lib/check_iv_length.js
|
|
var checkIvLength = (enc, iv) => {
|
|
if (iv.length << 3 !== bitLength(enc)) {
|
|
throw new JWEInvalid("Invalid Initialization Vector length");
|
|
}
|
|
};
|
|
var check_iv_length_default = checkIvLength;
|
|
|
|
// dist/browser/runtime/check_cek_length.js
|
|
var checkCekLength = (cek, expected) => {
|
|
if (cek.length << 3 !== expected) {
|
|
throw new JWEInvalid("Invalid Content Encryption Key length");
|
|
}
|
|
};
|
|
var check_cek_length_default = checkCekLength;
|
|
|
|
// dist/browser/runtime/timing_safe_equal.js
|
|
var timingSafeEqual = (a, b) => {
|
|
if (!(a instanceof Uint8Array)) {
|
|
throw new TypeError("First argument must be a buffer");
|
|
}
|
|
if (!(b instanceof Uint8Array)) {
|
|
throw new TypeError("Second argument must be a buffer");
|
|
}
|
|
if (a.length !== b.length) {
|
|
throw new TypeError("Input buffers must have the same length");
|
|
}
|
|
const len = a.length;
|
|
let out = 0;
|
|
let i = -1;
|
|
while (++i < len) {
|
|
out |= a[i] ^ b[i];
|
|
}
|
|
return out === 0;
|
|
};
|
|
var timing_safe_equal_default = timingSafeEqual;
|
|
|
|
// dist/browser/runtime/env.js
|
|
function isCloudflareWorkers() {
|
|
return typeof WebSocketPair === "function";
|
|
}
|
|
function isNodeJs() {
|
|
try {
|
|
return process.versions.node !== void 0;
|
|
} catch (_a) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// dist/browser/lib/crypto_key.js
|
|
function unusable(name, prop = "algorithm.name") {
|
|
return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
|
|
}
|
|
function isAlgorithm(algorithm, name) {
|
|
return algorithm.name === name;
|
|
}
|
|
function getHashLength(hash) {
|
|
return parseInt(hash.name.substr(4), 10);
|
|
}
|
|
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, usages) {
|
|
if (usages.length && !usages.some((expected) => key.usages.includes(expected))) {
|
|
let msg = "CryptoKey does not support this operation, its usages must include ";
|
|
if (usages.length > 2) {
|
|
const last = usages.pop();
|
|
msg += `one of ${usages.join(", ")}, or ${last}.`;
|
|
} else if (usages.length === 2) {
|
|
msg += `one of ${usages[0]} or ${usages[1]}.`;
|
|
} else {
|
|
msg += `${usages[0]}.`;
|
|
}
|
|
throw new TypeError(msg);
|
|
}
|
|
}
|
|
function checkSigCryptoKey(key, alg, ...usages) {
|
|
switch (alg) {
|
|
case "HS256":
|
|
case "HS384":
|
|
case "HS512": {
|
|
if (!isAlgorithm(key.algorithm, "HMAC"))
|
|
throw unusable("HMAC");
|
|
const expected = parseInt(alg.substr(2), 10);
|
|
const actual = getHashLength(key.algorithm.hash);
|
|
if (actual !== expected)
|
|
throw unusable(`SHA-${expected}`, "algorithm.hash");
|
|
break;
|
|
}
|
|
case "RS256":
|
|
case "RS384":
|
|
case "RS512": {
|
|
if (!isAlgorithm(key.algorithm, "RSASSA-PKCS1-v1_5"))
|
|
throw unusable("RSASSA-PKCS1-v1_5");
|
|
const expected = parseInt(alg.substr(2), 10);
|
|
const actual = getHashLength(key.algorithm.hash);
|
|
if (actual !== expected)
|
|
throw unusable(`SHA-${expected}`, "algorithm.hash");
|
|
break;
|
|
}
|
|
case "PS256":
|
|
case "PS384":
|
|
case "PS512": {
|
|
if (!isAlgorithm(key.algorithm, "RSA-PSS"))
|
|
throw unusable("RSA-PSS");
|
|
const expected = parseInt(alg.substr(2), 10);
|
|
const actual = getHashLength(key.algorithm.hash);
|
|
if (actual !== expected)
|
|
throw unusable(`SHA-${expected}`, "algorithm.hash");
|
|
break;
|
|
}
|
|
case (isNodeJs() && "EdDSA"): {
|
|
if (key.algorithm.name !== "NODE-ED25519" && key.algorithm.name !== "NODE-ED448")
|
|
throw unusable("NODE-ED25519 or NODE-ED448");
|
|
break;
|
|
}
|
|
case (isCloudflareWorkers() && "EdDSA"): {
|
|
if (!isAlgorithm(key.algorithm, "NODE-ED25519"))
|
|
throw unusable("NODE-ED25519");
|
|
break;
|
|
}
|
|
case "ES256":
|
|
case "ES384":
|
|
case "ES512": {
|
|
if (!isAlgorithm(key.algorithm, "ECDSA"))
|
|
throw unusable("ECDSA");
|
|
const expected = getNamedCurve(alg);
|
|
const actual = key.algorithm.namedCurve;
|
|
if (actual !== expected)
|
|
throw unusable(expected, "algorithm.namedCurve");
|
|
break;
|
|
}
|
|
default:
|
|
throw new TypeError("CryptoKey does not support this operation");
|
|
}
|
|
checkUsage(key, usages);
|
|
}
|
|
function checkEncCryptoKey(key, alg, ...usages) {
|
|
switch (alg) {
|
|
case "A128GCM":
|
|
case "A192GCM":
|
|
case "A256GCM": {
|
|
if (!isAlgorithm(key.algorithm, "AES-GCM"))
|
|
throw unusable("AES-GCM");
|
|
const expected = parseInt(alg.substr(1, 3), 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.substr(1, 3), 10);
|
|
const actual = key.algorithm.length;
|
|
if (actual !== expected)
|
|
throw unusable(expected, "algorithm.length");
|
|
break;
|
|
}
|
|
case "ECDH-ES":
|
|
if (!isAlgorithm(key.algorithm, "ECDH"))
|
|
throw unusable("ECDH");
|
|
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");
|
|
const expected = parseInt(alg.substr(9), 10) || 1;
|
|
const actual = getHashLength(key.algorithm.hash);
|
|
if (actual !== expected)
|
|
throw unusable(`SHA-${expected}`, "algorithm.hash");
|
|
break;
|
|
}
|
|
default:
|
|
throw new TypeError("CryptoKey does not support this operation");
|
|
}
|
|
checkUsage(key, usages);
|
|
}
|
|
|
|
// dist/browser/lib/invalid_key_input.js
|
|
var invalid_key_input_default = (actual, ...types2) => {
|
|
let msg = "Key must be ";
|
|
if (types2.length > 2) {
|
|
const last = types2.pop();
|
|
msg += `one of type ${types2.join(", ")}, or ${last}.`;
|
|
} else if (types2.length === 2) {
|
|
msg += `one of type ${types2[0]} or ${types2[1]}.`;
|
|
} else {
|
|
msg += `of type ${types2[0]}.`;
|
|
}
|
|
if (actual == null) {
|
|
msg += ` Received ${actual}`;
|
|
} else if (typeof actual === "function" && actual.name) {
|
|
msg += ` Received function ${actual.name}`;
|
|
} else if (typeof actual === "object" && actual != null) {
|
|
if (actual.constructor && actual.constructor.name) {
|
|
msg += ` Received an instance of ${actual.constructor.name}`;
|
|
}
|
|
}
|
|
return msg;
|
|
};
|
|
|
|
// dist/browser/runtime/is_key_like.js
|
|
var is_key_like_default = (key) => {
|
|
return isCryptoKey(key);
|
|
};
|
|
var types = ["CryptoKey"];
|
|
|
|
// dist/browser/runtime/decrypt.js
|
|
async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
if (!(cek instanceof Uint8Array)) {
|
|
throw new TypeError(invalid_key_input_default(cek, "Uint8Array"));
|
|
}
|
|
const keySize = parseInt(enc.substr(1, 3), 10);
|
|
const encKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(keySize >> 3), "AES-CBC", false, ["decrypt"]);
|
|
const macKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(0, keySize >> 3), {
|
|
hash: `SHA-${keySize << 1}`,
|
|
name: "HMAC"
|
|
}, false, ["sign"]);
|
|
const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3));
|
|
const expectedTag = new Uint8Array((await webcrypto_default.subtle.sign("HMAC", macKey, macData)).slice(0, keySize >> 3));
|
|
let macCheckPassed;
|
|
try {
|
|
macCheckPassed = timing_safe_equal_default(tag, expectedTag);
|
|
} catch (_a) {
|
|
}
|
|
if (!macCheckPassed) {
|
|
throw new JWEDecryptionFailed();
|
|
}
|
|
let plaintext;
|
|
try {
|
|
plaintext = new Uint8Array(await webcrypto_default.subtle.decrypt({ iv, name: "AES-CBC" }, encKey, ciphertext));
|
|
} catch (_b) {
|
|
}
|
|
if (!plaintext) {
|
|
throw new JWEDecryptionFailed();
|
|
}
|
|
return plaintext;
|
|
}
|
|
async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
let encKey;
|
|
if (cek instanceof Uint8Array) {
|
|
encKey = await webcrypto_default.subtle.importKey("raw", cek, "AES-GCM", false, ["decrypt"]);
|
|
} else {
|
|
checkEncCryptoKey(cek, enc, "decrypt");
|
|
encKey = cek;
|
|
}
|
|
try {
|
|
return new Uint8Array(await webcrypto_default.subtle.decrypt({
|
|
additionalData: aad,
|
|
iv,
|
|
name: "AES-GCM",
|
|
tagLength: 128
|
|
}, encKey, concat(ciphertext, tag)));
|
|
} catch (_a) {
|
|
throw new JWEDecryptionFailed();
|
|
}
|
|
}
|
|
var decrypt = async (enc, cek, ciphertext, iv, tag, aad) => {
|
|
if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) {
|
|
throw new TypeError(invalid_key_input_default(cek, ...types, "Uint8Array"));
|
|
}
|
|
check_iv_length_default(enc, iv);
|
|
switch (enc) {
|
|
case "A128CBC-HS256":
|
|
case "A192CBC-HS384":
|
|
case "A256CBC-HS512":
|
|
if (cek instanceof Uint8Array)
|
|
check_cek_length_default(cek, parseInt(enc.substr(-3), 10));
|
|
return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad);
|
|
case "A128GCM":
|
|
case "A192GCM":
|
|
case "A256GCM":
|
|
if (cek instanceof Uint8Array)
|
|
check_cek_length_default(cek, parseInt(enc.substr(1, 3), 10));
|
|
return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad);
|
|
default:
|
|
throw new JOSENotSupported("Unsupported JWE Content Encryption Algorithm");
|
|
}
|
|
};
|
|
var decrypt_default = decrypt;
|
|
|
|
// dist/browser/runtime/zlib.js
|
|
var inflate = async () => {
|
|
throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `inflateRaw` decrypt option to provide Inflate Raw implementation.');
|
|
};
|
|
var deflate = async () => {
|
|
throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported by your javascript runtime. You need to use the `deflateRaw` encrypt option to provide Deflate Raw implementation.');
|
|
};
|
|
|
|
// dist/browser/lib/is_disjoint.js
|
|
var isDisjoint = (...headers) => {
|
|
const sources = headers.filter(Boolean);
|
|
if (sources.length === 0 || sources.length === 1) {
|
|
return true;
|
|
}
|
|
let acc;
|
|
for (const header of sources) {
|
|
const parameters = Object.keys(header);
|
|
if (!acc || acc.size === 0) {
|
|
acc = new Set(parameters);
|
|
continue;
|
|
}
|
|
for (const parameter of parameters) {
|
|
if (acc.has(parameter)) {
|
|
return false;
|
|
}
|
|
acc.add(parameter);
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
var is_disjoint_default = isDisjoint;
|
|
|
|
// dist/browser/lib/is_object.js
|
|
function isObjectLike(value) {
|
|
return typeof value === "object" && value !== null;
|
|
}
|
|
function isObject(input) {
|
|
if (!isObjectLike(input) || Object.prototype.toString.call(input) !== "[object Object]") {
|
|
return false;
|
|
}
|
|
if (Object.getPrototypeOf(input) === null) {
|
|
return true;
|
|
}
|
|
let proto = input;
|
|
while (Object.getPrototypeOf(proto) !== null) {
|
|
proto = Object.getPrototypeOf(proto);
|
|
}
|
|
return Object.getPrototypeOf(input) === proto;
|
|
}
|
|
|
|
// dist/browser/runtime/bogus.js
|
|
var bogusWebCrypto = [
|
|
{ hash: "SHA-256", name: "HMAC" },
|
|
true,
|
|
["sign"]
|
|
];
|
|
var bogus_default = bogusWebCrypto;
|
|
|
|
// dist/browser/runtime/aeskw.js
|
|
function checkKeySize(key, alg) {
|
|
if (key.algorithm.length !== parseInt(alg.substr(1, 3), 10)) {
|
|
throw new TypeError(`Invalid key size for alg: ${alg}`);
|
|
}
|
|
}
|
|
function getCryptoKey(key, alg, usage) {
|
|
if (isCryptoKey(key)) {
|
|
checkEncCryptoKey(key, alg, usage);
|
|
return key;
|
|
}
|
|
if (key instanceof Uint8Array) {
|
|
return webcrypto_default.subtle.importKey("raw", key, "AES-KW", true, [usage]);
|
|
}
|
|
throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array"));
|
|
}
|
|
var wrap = async (alg, key, cek) => {
|
|
const cryptoKey = await getCryptoKey(key, alg, "wrapKey");
|
|
checkKeySize(cryptoKey, alg);
|
|
const cryptoKeyCek = await webcrypto_default.subtle.importKey("raw", cek, ...bogus_default);
|
|
return new Uint8Array(await webcrypto_default.subtle.wrapKey("raw", cryptoKeyCek, cryptoKey, "AES-KW"));
|
|
};
|
|
var unwrap = async (alg, key, encryptedKey) => {
|
|
const cryptoKey = await getCryptoKey(key, alg, "unwrapKey");
|
|
checkKeySize(cryptoKey, alg);
|
|
const cryptoKeyCek = await webcrypto_default.subtle.unwrapKey("raw", encryptedKey, cryptoKey, "AES-KW", ...bogus_default);
|
|
return new Uint8Array(await webcrypto_default.subtle.exportKey("raw", cryptoKeyCek));
|
|
};
|
|
|
|
// dist/browser/runtime/digest.js
|
|
var digest = async (algorithm, data) => {
|
|
const subtleDigest = `SHA-${algorithm.substr(-3)}`;
|
|
return new Uint8Array(await webcrypto_default.subtle.digest(subtleDigest, data));
|
|
};
|
|
var digest_default = digest;
|
|
|
|
// dist/browser/runtime/ecdhes.js
|
|
var deriveKey = async (publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) => {
|
|
if (!isCryptoKey(publicKey)) {
|
|
throw new TypeError(invalid_key_input_default(publicKey, ...types));
|
|
}
|
|
checkEncCryptoKey(publicKey, "ECDH-ES");
|
|
if (!isCryptoKey(privateKey)) {
|
|
throw new TypeError(invalid_key_input_default(privateKey, ...types));
|
|
}
|
|
checkEncCryptoKey(privateKey, "ECDH-ES", "deriveBits", "deriveKey");
|
|
const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength));
|
|
if (!privateKey.usages.includes("deriveBits")) {
|
|
throw new TypeError('ECDH-ES private key "usages" must include "deriveBits"');
|
|
}
|
|
const sharedSecret = new Uint8Array(await webcrypto_default.subtle.deriveBits({
|
|
name: "ECDH",
|
|
public: publicKey
|
|
}, privateKey, Math.ceil(parseInt(privateKey.algorithm.namedCurve.substr(-3), 10) / 8) << 3));
|
|
return concatKdf(digest_default, sharedSecret, keyLength, value);
|
|
};
|
|
var generateEpk = async (key) => {
|
|
if (!isCryptoKey(key)) {
|
|
throw new TypeError(invalid_key_input_default(key, ...types));
|
|
}
|
|
return (await webcrypto_default.subtle.generateKey({ name: "ECDH", namedCurve: key.algorithm.namedCurve }, true, ["deriveBits"])).privateKey;
|
|
};
|
|
var ecdhAllowed = (key) => {
|
|
if (!isCryptoKey(key)) {
|
|
throw new TypeError(invalid_key_input_default(key, ...types));
|
|
}
|
|
return ["P-256", "P-384", "P-521"].includes(key.algorithm.namedCurve);
|
|
};
|
|
|
|
// dist/browser/lib/check_p2s.js
|
|
function checkP2s(p2s2) {
|
|
if (!(p2s2 instanceof Uint8Array) || p2s2.length < 8) {
|
|
throw new JWEInvalid("PBES2 Salt Input must be 8 or more octets");
|
|
}
|
|
}
|
|
|
|
// dist/browser/runtime/pbes2kw.js
|
|
function getCryptoKey2(key, alg) {
|
|
if (key instanceof Uint8Array) {
|
|
return webcrypto_default.subtle.importKey("raw", key, "PBKDF2", false, ["deriveBits"]);
|
|
}
|
|
if (isCryptoKey(key)) {
|
|
checkEncCryptoKey(key, alg, "deriveBits", "deriveKey");
|
|
return key;
|
|
}
|
|
throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array"));
|
|
}
|
|
async function deriveKey2(p2s2, alg, p2c, key) {
|
|
checkP2s(p2s2);
|
|
const salt = p2s(alg, p2s2);
|
|
const keylen = parseInt(alg.substr(13, 3), 10);
|
|
const subtleAlg = {
|
|
hash: `SHA-${alg.substr(8, 3)}`,
|
|
iterations: p2c,
|
|
name: "PBKDF2",
|
|
salt
|
|
};
|
|
const wrapAlg = {
|
|
length: keylen,
|
|
name: "AES-KW"
|
|
};
|
|
const cryptoKey = await getCryptoKey2(key, alg);
|
|
if (cryptoKey.usages.includes("deriveBits")) {
|
|
return new Uint8Array(await webcrypto_default.subtle.deriveBits(subtleAlg, cryptoKey, keylen));
|
|
}
|
|
if (cryptoKey.usages.includes("deriveKey")) {
|
|
return webcrypto_default.subtle.deriveKey(subtleAlg, cryptoKey, wrapAlg, false, ["wrapKey", "unwrapKey"]);
|
|
}
|
|
throw new TypeError('PBKDF2 key "usages" must include "deriveBits" or "deriveKey"');
|
|
}
|
|
var encrypt = async (alg, key, cek, p2c = Math.floor(Math.random() * 2049) + 2048, p2s2 = random_default(new Uint8Array(16))) => {
|
|
const derived = await deriveKey2(p2s2, alg, p2c, key);
|
|
const encryptedKey = await wrap(alg.substr(-6), derived, cek);
|
|
return { encryptedKey, p2c, p2s: encode(p2s2) };
|
|
};
|
|
var decrypt2 = async (alg, key, encryptedKey, p2c, p2s2) => {
|
|
const derived = await deriveKey2(p2s2, alg, p2c, key);
|
|
return unwrap(alg.substr(-6), derived, encryptedKey);
|
|
};
|
|
|
|
// dist/browser/runtime/subtle_rsaes.js
|
|
function subtleRsaEs(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`);
|
|
}
|
|
}
|
|
|
|
// dist/browser/runtime/check_key_length.js
|
|
var check_key_length_default = (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`);
|
|
}
|
|
}
|
|
};
|
|
|
|
// dist/browser/runtime/rsaes.js
|
|
var encrypt2 = async (alg, key, cek) => {
|
|
if (!isCryptoKey(key)) {
|
|
throw new TypeError(invalid_key_input_default(key, ...types));
|
|
}
|
|
checkEncCryptoKey(key, alg, "encrypt", "wrapKey");
|
|
check_key_length_default(alg, key);
|
|
if (key.usages.includes("encrypt")) {
|
|
return new Uint8Array(await webcrypto_default.subtle.encrypt(subtleRsaEs(alg), key, cek));
|
|
}
|
|
if (key.usages.includes("wrapKey")) {
|
|
const cryptoKeyCek = await webcrypto_default.subtle.importKey("raw", cek, ...bogus_default);
|
|
return new Uint8Array(await webcrypto_default.subtle.wrapKey("raw", cryptoKeyCek, key, subtleRsaEs(alg)));
|
|
}
|
|
throw new TypeError('RSA-OAEP key "usages" must include "encrypt" or "wrapKey" for this operation');
|
|
};
|
|
var decrypt3 = async (alg, key, encryptedKey) => {
|
|
if (!isCryptoKey(key)) {
|
|
throw new TypeError(invalid_key_input_default(key, ...types));
|
|
}
|
|
checkEncCryptoKey(key, alg, "decrypt", "unwrapKey");
|
|
check_key_length_default(alg, key);
|
|
if (key.usages.includes("decrypt")) {
|
|
return new Uint8Array(await webcrypto_default.subtle.decrypt(subtleRsaEs(alg), key, encryptedKey));
|
|
}
|
|
if (key.usages.includes("unwrapKey")) {
|
|
const cryptoKeyCek = await webcrypto_default.subtle.unwrapKey("raw", encryptedKey, key, subtleRsaEs(alg), ...bogus_default);
|
|
return new Uint8Array(await webcrypto_default.subtle.exportKey("raw", cryptoKeyCek));
|
|
}
|
|
throw new TypeError('RSA-OAEP key "usages" must include "decrypt" or "unwrapKey" for this operation');
|
|
};
|
|
|
|
// dist/browser/lib/cek.js
|
|
function bitLength2(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}`);
|
|
}
|
|
}
|
|
var cek_default = (alg) => random_default(new Uint8Array(bitLength2(alg) >> 3));
|
|
|
|
// dist/browser/lib/format_pem.js
|
|
var format_pem_default = (b64, descriptor) => {
|
|
const newlined = (b64.match(/.{1,64}/g) || []).join("\n");
|
|
return `-----BEGIN ${descriptor}-----
|
|
${newlined}
|
|
-----END ${descriptor}-----`;
|
|
};
|
|
|
|
// dist/browser/runtime/asn1.js
|
|
var genericExport = async (keyType, keyFormat, key) => {
|
|
if (!isCryptoKey(key)) {
|
|
throw new TypeError(invalid_key_input_default(key, ...types));
|
|
}
|
|
if (!key.extractable) {
|
|
throw new TypeError("CryptoKey is not extractable");
|
|
}
|
|
if (key.type !== keyType) {
|
|
throw new TypeError(`key is not a ${keyType} key`);
|
|
}
|
|
return format_pem_default(encodeBase64(new Uint8Array(await webcrypto_default.subtle.exportKey(keyFormat, key))), `${keyType.toUpperCase()} KEY`);
|
|
};
|
|
var toSPKI = (key) => {
|
|
return genericExport("public", "spki", key);
|
|
};
|
|
var toPKCS8 = (key) => {
|
|
return genericExport("private", "pkcs8", key);
|
|
};
|
|
var getNamedCurve2 = (keyData) => {
|
|
const keyDataStr = keyData.toString();
|
|
switch (true) {
|
|
case keyDataStr.includes(new Uint8Array([
|
|
6,
|
|
7,
|
|
42,
|
|
134,
|
|
72,
|
|
206,
|
|
61,
|
|
2,
|
|
1,
|
|
6,
|
|
8,
|
|
42,
|
|
134,
|
|
72,
|
|
206,
|
|
61,
|
|
3,
|
|
1,
|
|
7
|
|
]).toString()):
|
|
return "P-256";
|
|
case keyDataStr.includes(new Uint8Array([
|
|
6,
|
|
7,
|
|
42,
|
|
134,
|
|
72,
|
|
206,
|
|
61,
|
|
2,
|
|
1,
|
|
6,
|
|
5,
|
|
43,
|
|
129,
|
|
4,
|
|
0,
|
|
34
|
|
]).toString()):
|
|
return "P-384";
|
|
case keyDataStr.includes(new Uint8Array([
|
|
6,
|
|
7,
|
|
42,
|
|
134,
|
|
72,
|
|
206,
|
|
61,
|
|
2,
|
|
1,
|
|
6,
|
|
5,
|
|
43,
|
|
129,
|
|
4,
|
|
0,
|
|
35
|
|
]).toString()):
|
|
return "P-521";
|
|
case ((isCloudflareWorkers() || isNodeJs()) && keyDataStr.includes(new Uint8Array([6, 3, 43, 101, 112]).toString())):
|
|
return "Ed25519";
|
|
case (isNodeJs() && keyDataStr.includes(new Uint8Array([6, 3, 43, 101, 113]).toString())):
|
|
return "Ed448";
|
|
default:
|
|
throw new JOSENotSupported("Invalid or unsupported EC Key Curve or OKP Key Sub Type");
|
|
}
|
|
};
|
|
var genericImport = async (replace, keyFormat, pem, alg, options) => {
|
|
var _a;
|
|
let algorithm;
|
|
let keyUsages;
|
|
const keyData = new Uint8Array(atob(pem.replace(replace, "")).split("").map((c) => c.charCodeAt(0)));
|
|
const isPublic = keyFormat === "spki";
|
|
switch (alg) {
|
|
case "PS256":
|
|
case "PS384":
|
|
case "PS512":
|
|
algorithm = { name: "RSA-PSS", hash: `SHA-${alg.substr(-3)}` };
|
|
keyUsages = isPublic ? ["verify"] : ["sign"];
|
|
break;
|
|
case "RS256":
|
|
case "RS384":
|
|
case "RS512":
|
|
algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${alg.substr(-3)}` };
|
|
keyUsages = isPublic ? ["verify"] : ["sign"];
|
|
break;
|
|
case "RSA-OAEP":
|
|
case "RSA-OAEP-256":
|
|
case "RSA-OAEP-384":
|
|
case "RSA-OAEP-512":
|
|
algorithm = {
|
|
name: "RSA-OAEP",
|
|
hash: `SHA-${parseInt(alg.substr(-3), 10) || 1}`
|
|
};
|
|
keyUsages = isPublic ? ["encrypt", "wrapKey"] : ["decrypt", "unwrapKey"];
|
|
break;
|
|
case "ES256":
|
|
algorithm = { name: "ECDSA", namedCurve: "P-256" };
|
|
keyUsages = isPublic ? ["verify"] : ["sign"];
|
|
break;
|
|
case "ES384":
|
|
algorithm = { name: "ECDSA", namedCurve: "P-384" };
|
|
keyUsages = isPublic ? ["verify"] : ["sign"];
|
|
break;
|
|
case "ES512":
|
|
algorithm = { name: "ECDSA", namedCurve: "P-521" };
|
|
keyUsages = isPublic ? ["verify"] : ["sign"];
|
|
break;
|
|
case "ECDH-ES":
|
|
case "ECDH-ES+A128KW":
|
|
case "ECDH-ES+A192KW":
|
|
case "ECDH-ES+A256KW":
|
|
algorithm = { name: "ECDH", namedCurve: getNamedCurve2(keyData) };
|
|
keyUsages = isPublic ? [] : ["deriveBits"];
|
|
break;
|
|
case ((isCloudflareWorkers() || isNodeJs()) && "EdDSA"):
|
|
const namedCurve = getNamedCurve2(keyData).toUpperCase();
|
|
algorithm = { name: `NODE-${namedCurve}`, namedCurve: `NODE-${namedCurve}` };
|
|
keyUsages = isPublic ? ["verify"] : ["sign"];
|
|
break;
|
|
default:
|
|
throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value');
|
|
}
|
|
return webcrypto_default.subtle.importKey(keyFormat, keyData, algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages);
|
|
};
|
|
var fromPKCS8 = (pem, alg, options) => {
|
|
return genericImport(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, "pkcs8", pem, alg, options);
|
|
};
|
|
var fromSPKI = (pem, alg, options) => {
|
|
return genericImport(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, "spki", pem, alg, options);
|
|
};
|
|
|
|
// dist/browser/runtime/jwk_to_key.js
|
|
function subtleMapping(jwk) {
|
|
let algorithm;
|
|
let keyUsages;
|
|
switch (jwk.kty) {
|
|
case "oct": {
|
|
switch (jwk.alg) {
|
|
case "HS256":
|
|
case "HS384":
|
|
case "HS512":
|
|
algorithm = { name: "HMAC", hash: `SHA-${jwk.alg.substr(-3)}` };
|
|
keyUsages = ["sign", "verify"];
|
|
break;
|
|
case "A128CBC-HS256":
|
|
case "A192CBC-HS384":
|
|
case "A256CBC-HS512":
|
|
throw new JOSENotSupported(`${jwk.alg} keys cannot be imported as CryptoKey instances`);
|
|
case "A128GCM":
|
|
case "A192GCM":
|
|
case "A256GCM":
|
|
case "A128GCMKW":
|
|
case "A192GCMKW":
|
|
case "A256GCMKW":
|
|
algorithm = { name: "AES-GCM" };
|
|
keyUsages = ["encrypt", "decrypt"];
|
|
break;
|
|
case "A128KW":
|
|
case "A192KW":
|
|
case "A256KW":
|
|
algorithm = { name: "AES-KW" };
|
|
keyUsages = ["wrapKey", "unwrapKey"];
|
|
break;
|
|
case "PBES2-HS256+A128KW":
|
|
case "PBES2-HS384+A192KW":
|
|
case "PBES2-HS512+A256KW":
|
|
algorithm = { name: "PBKDF2" };
|
|
keyUsages = ["deriveBits"];
|
|
break;
|
|
default:
|
|
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
|
|
}
|
|
break;
|
|
}
|
|
case "RSA": {
|
|
switch (jwk.alg) {
|
|
case "PS256":
|
|
case "PS384":
|
|
case "PS512":
|
|
algorithm = { name: "RSA-PSS", hash: `SHA-${jwk.alg.substr(-3)}` };
|
|
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
break;
|
|
case "RS256":
|
|
case "RS384":
|
|
case "RS512":
|
|
algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${jwk.alg.substr(-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.substr(-3), 10) || 1}`
|
|
};
|
|
keyUsages = jwk.d ? ["decrypt", "unwrapKey"] : ["encrypt", "wrapKey"];
|
|
break;
|
|
default:
|
|
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
|
|
}
|
|
break;
|
|
}
|
|
case "EC": {
|
|
switch (jwk.alg) {
|
|
case "ES256":
|
|
algorithm = { name: "ECDSA", namedCurve: "P-256" };
|
|
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
break;
|
|
case "ES384":
|
|
algorithm = { name: "ECDSA", namedCurve: "P-384" };
|
|
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
break;
|
|
case "ES512":
|
|
algorithm = { name: "ECDSA", namedCurve: "P-521" };
|
|
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('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
|
|
}
|
|
break;
|
|
}
|
|
case ((isCloudflareWorkers() || isNodeJs()) && "OKP"):
|
|
if (jwk.alg !== "EdDSA") {
|
|
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
|
|
}
|
|
switch (jwk.crv) {
|
|
case "Ed25519":
|
|
algorithm = { name: "NODE-ED25519", namedCurve: "NODE-ED25519" };
|
|
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
break;
|
|
case (isNodeJs() && "Ed448"):
|
|
algorithm = { name: "NODE-ED448", namedCurve: "NODE-ED448" };
|
|
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
break;
|
|
default:
|
|
throw new JOSENotSupported('Invalid or unsupported JWK "crv" (Subtype of Key Pair) Parameter value');
|
|
}
|
|
break;
|
|
default:
|
|
throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value');
|
|
}
|
|
return { algorithm, keyUsages };
|
|
}
|
|
var parse = async (jwk) => {
|
|
var _a, _b;
|
|
const { algorithm, keyUsages } = subtleMapping(jwk);
|
|
const rest = [
|
|
algorithm,
|
|
(_a = jwk.ext) !== null && _a !== void 0 ? _a : false,
|
|
(_b = jwk.key_ops) !== null && _b !== void 0 ? _b : keyUsages
|
|
];
|
|
if (algorithm.name === "PBKDF2") {
|
|
return webcrypto_default.subtle.importKey("raw", decode(jwk.k), ...rest);
|
|
}
|
|
const keyData = { ...jwk };
|
|
delete keyData.alg;
|
|
return webcrypto_default.subtle.importKey("jwk", keyData, ...rest);
|
|
};
|
|
var jwk_to_key_default = parse;
|
|
|
|
// dist/browser/key/import.js
|
|
function getElement(seq) {
|
|
let result = [];
|
|
let next = 0;
|
|
while (next < seq.length) {
|
|
let nextPart = parseElement(seq.subarray(next));
|
|
result.push(nextPart);
|
|
next += nextPart.byteLength;
|
|
}
|
|
return result;
|
|
}
|
|
function parseElement(bytes) {
|
|
let position = 0;
|
|
let tag = bytes[0] & 31;
|
|
position++;
|
|
if (tag === 31) {
|
|
tag = 0;
|
|
while (bytes[position] >= 128) {
|
|
tag = tag * 128 + bytes[position] - 128;
|
|
position++;
|
|
}
|
|
tag = tag * 128 + bytes[position] - 128;
|
|
position++;
|
|
}
|
|
let length = 0;
|
|
if (bytes[position] < 128) {
|
|
length = bytes[position];
|
|
position++;
|
|
} else {
|
|
let numberOfDigits = bytes[position] & 127;
|
|
position++;
|
|
length = 0;
|
|
for (let i = 0; i < numberOfDigits; i++) {
|
|
length = length * 256 + bytes[position];
|
|
position++;
|
|
}
|
|
}
|
|
if (length === 128) {
|
|
length = 0;
|
|
while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) {
|
|
length++;
|
|
}
|
|
const byteLength2 = position + length + 2;
|
|
return {
|
|
byteLength: byteLength2,
|
|
contents: bytes.subarray(position, position + length),
|
|
raw: bytes.subarray(0, byteLength2)
|
|
};
|
|
}
|
|
const byteLength = position + length;
|
|
return {
|
|
byteLength,
|
|
contents: bytes.subarray(position, byteLength),
|
|
raw: bytes.subarray(0, byteLength)
|
|
};
|
|
}
|
|
function spkiFromX509(buf) {
|
|
const tbsCertificate = getElement(getElement(parseElement(buf).contents)[0].contents);
|
|
return encodeBase64(tbsCertificate[tbsCertificate[0].raw[0] === 160 ? 6 : 5].raw);
|
|
}
|
|
function getSPKI(x509) {
|
|
const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, "");
|
|
const raw = decodeBase64(pem);
|
|
return format_pem_default(spkiFromX509(raw), "PUBLIC KEY");
|
|
}
|
|
async function importSPKI(spki, alg, options) {
|
|
if (typeof spki !== "string" || spki.indexOf("-----BEGIN PUBLIC KEY-----") !== 0) {
|
|
throw new TypeError('"spki" must be SPKI formatted string');
|
|
}
|
|
return fromSPKI(spki, alg, options);
|
|
}
|
|
async function importX509(x509, alg, options) {
|
|
if (typeof x509 !== "string" || x509.indexOf("-----BEGIN CERTIFICATE-----") !== 0) {
|
|
throw new TypeError('"x509" must be X.509 formatted string');
|
|
}
|
|
const spki = getSPKI(x509);
|
|
return fromSPKI(spki, alg, options);
|
|
}
|
|
async function importPKCS8(pkcs8, alg, options) {
|
|
if (typeof pkcs8 !== "string" || pkcs8.indexOf("-----BEGIN PRIVATE KEY-----") !== 0) {
|
|
throw new TypeError('"pkcs8" must be PCKS8 formatted string');
|
|
}
|
|
return fromPKCS8(pkcs8, alg, options);
|
|
}
|
|
async function importJWK(jwk, alg, octAsKeyObject) {
|
|
if (!isObject(jwk)) {
|
|
throw new TypeError("JWK must be an object");
|
|
}
|
|
alg || (alg = jwk.alg);
|
|
if (typeof alg !== "string" || !alg) {
|
|
throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
|
|
}
|
|
switch (jwk.kty) {
|
|
case "oct":
|
|
if (typeof jwk.k !== "string" || !jwk.k) {
|
|
throw new TypeError('missing "k" (Key Value) Parameter value');
|
|
}
|
|
octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : octAsKeyObject = jwk.ext !== true;
|
|
if (octAsKeyObject) {
|
|
return jwk_to_key_default({ ...jwk, alg, ext: false });
|
|
}
|
|
return decode(jwk.k);
|
|
case "RSA":
|
|
if (jwk.oth !== void 0) {
|
|
throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');
|
|
}
|
|
case "EC":
|
|
case "OKP":
|
|
return jwk_to_key_default({ ...jwk, alg });
|
|
default:
|
|
throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value');
|
|
}
|
|
}
|
|
|
|
// dist/browser/lib/check_key_type.js
|
|
var symmetricTypeCheck = (key) => {
|
|
if (key instanceof Uint8Array)
|
|
return;
|
|
if (!is_key_like_default(key)) {
|
|
throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array"));
|
|
}
|
|
if (key.type !== "secret") {
|
|
throw new TypeError(`${types.join(" or ")} instances for symmetric algorithms must be of type "secret"`);
|
|
}
|
|
};
|
|
var asymmetricTypeCheck = (key, usage) => {
|
|
if (!is_key_like_default(key)) {
|
|
throw new TypeError(invalid_key_input_default(key, ...types));
|
|
}
|
|
if (key.type === "secret") {
|
|
throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithms must not be of type "secret"`);
|
|
}
|
|
if (usage === "sign" && key.type === "public") {
|
|
throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm signing must be of type "private"`);
|
|
}
|
|
if (usage === "decrypt" && key.type === "public") {
|
|
throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm decryption must be of type "private"`);
|
|
}
|
|
if (key.algorithm && usage === "verify" && key.type === "private") {
|
|
throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm verifying must be of type "public"`);
|
|
}
|
|
if (key.algorithm && usage === "encrypt" && key.type === "private") {
|
|
throw new TypeError(`${types.join(" or ")} instances for asymmetric algorithm encryption must be of type "public"`);
|
|
}
|
|
};
|
|
var checkKeyType = (alg, key, usage) => {
|
|
const symmetric = alg.startsWith("HS") || alg === "dir" || alg.startsWith("PBES2") || /^A\d{3}(?:GCM)?KW$/.test(alg);
|
|
if (symmetric) {
|
|
symmetricTypeCheck(key);
|
|
} else {
|
|
asymmetricTypeCheck(key, usage);
|
|
}
|
|
};
|
|
var check_key_type_default = checkKeyType;
|
|
|
|
// dist/browser/runtime/encrypt.js
|
|
async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
|
|
if (!(cek instanceof Uint8Array)) {
|
|
throw new TypeError(invalid_key_input_default(cek, "Uint8Array"));
|
|
}
|
|
const keySize = parseInt(enc.substr(1, 3), 10);
|
|
const encKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(keySize >> 3), "AES-CBC", false, ["encrypt"]);
|
|
const macKey = await webcrypto_default.subtle.importKey("raw", cek.subarray(0, keySize >> 3), {
|
|
hash: `SHA-${keySize << 1}`,
|
|
name: "HMAC"
|
|
}, false, ["sign"]);
|
|
const ciphertext = new Uint8Array(await webcrypto_default.subtle.encrypt({
|
|
iv,
|
|
name: "AES-CBC"
|
|
}, encKey, plaintext));
|
|
const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3));
|
|
const tag = new Uint8Array((await webcrypto_default.subtle.sign("HMAC", macKey, macData)).slice(0, keySize >> 3));
|
|
return { ciphertext, tag };
|
|
}
|
|
async function gcmEncrypt(enc, plaintext, cek, iv, aad) {
|
|
let encKey;
|
|
if (cek instanceof Uint8Array) {
|
|
encKey = await webcrypto_default.subtle.importKey("raw", cek, "AES-GCM", false, ["encrypt"]);
|
|
} else {
|
|
checkEncCryptoKey(cek, enc, "encrypt");
|
|
encKey = cek;
|
|
}
|
|
const encrypted = new Uint8Array(await webcrypto_default.subtle.encrypt({
|
|
additionalData: aad,
|
|
iv,
|
|
name: "AES-GCM",
|
|
tagLength: 128
|
|
}, encKey, plaintext));
|
|
const tag = encrypted.slice(-16);
|
|
const ciphertext = encrypted.slice(0, -16);
|
|
return { ciphertext, tag };
|
|
}
|
|
var encrypt3 = async (enc, plaintext, cek, iv, aad) => {
|
|
if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) {
|
|
throw new TypeError(invalid_key_input_default(cek, ...types, "Uint8Array"));
|
|
}
|
|
check_iv_length_default(enc, iv);
|
|
switch (enc) {
|
|
case "A128CBC-HS256":
|
|
case "A192CBC-HS384":
|
|
case "A256CBC-HS512":
|
|
if (cek instanceof Uint8Array)
|
|
check_cek_length_default(cek, parseInt(enc.substr(-3), 10));
|
|
return cbcEncrypt(enc, plaintext, cek, iv, aad);
|
|
case "A128GCM":
|
|
case "A192GCM":
|
|
case "A256GCM":
|
|
if (cek instanceof Uint8Array)
|
|
check_cek_length_default(cek, parseInt(enc.substr(1, 3), 10));
|
|
return gcmEncrypt(enc, plaintext, cek, iv, aad);
|
|
default:
|
|
throw new JOSENotSupported("Unsupported JWE Content Encryption Algorithm");
|
|
}
|
|
};
|
|
var encrypt_default = encrypt3;
|
|
|
|
// dist/browser/lib/aesgcmkw.js
|
|
async function wrap2(alg, key, cek, iv) {
|
|
const jweAlgorithm = alg.substr(0, 7);
|
|
iv || (iv = iv_default(jweAlgorithm));
|
|
const { ciphertext: encryptedKey, tag } = await encrypt_default(jweAlgorithm, cek, key, iv, new Uint8Array(0));
|
|
return { encryptedKey, iv: encode(iv), tag: encode(tag) };
|
|
}
|
|
async function unwrap2(alg, key, encryptedKey, iv, tag) {
|
|
const jweAlgorithm = alg.substr(0, 7);
|
|
return decrypt_default(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0));
|
|
}
|
|
|
|
// dist/browser/lib/decrypt_key_management.js
|
|
async function decryptKeyManagement(alg, key, encryptedKey, joseHeader) {
|
|
check_key_type_default(alg, key, "decrypt");
|
|
switch (alg) {
|
|
case "dir": {
|
|
if (encryptedKey !== void 0)
|
|
throw new JWEInvalid("Encountered unexpected JWE Encrypted Key");
|
|
return key;
|
|
}
|
|
case "ECDH-ES":
|
|
if (encryptedKey !== void 0)
|
|
throw new JWEInvalid("Encountered unexpected JWE Encrypted Key");
|
|
case "ECDH-ES+A128KW":
|
|
case "ECDH-ES+A192KW":
|
|
case "ECDH-ES+A256KW": {
|
|
if (!isObject(joseHeader.epk))
|
|
throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`);
|
|
if (!ecdhAllowed(key))
|
|
throw new JOSENotSupported("ECDH-ES with the provided key is not allowed or not supported by your javascript runtime");
|
|
const epk = await importJWK(joseHeader.epk, alg);
|
|
let partyUInfo;
|
|
let partyVInfo;
|
|
if (joseHeader.apu !== void 0) {
|
|
if (typeof joseHeader.apu !== "string")
|
|
throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`);
|
|
partyUInfo = decode(joseHeader.apu);
|
|
}
|
|
if (joseHeader.apv !== void 0) {
|
|
if (typeof joseHeader.apv !== "string")
|
|
throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`);
|
|
partyVInfo = decode(joseHeader.apv);
|
|
}
|
|
const sharedSecret = await deriveKey(epk, key, alg === "ECDH-ES" ? joseHeader.enc : alg, alg === "ECDH-ES" ? bitLength2(joseHeader.enc) : parseInt(alg.substr(-5, 3), 10), partyUInfo, partyVInfo);
|
|
if (alg === "ECDH-ES")
|
|
return sharedSecret;
|
|
if (encryptedKey === void 0)
|
|
throw new JWEInvalid("JWE Encrypted Key missing");
|
|
return unwrap(alg.substr(-6), sharedSecret, encryptedKey);
|
|
}
|
|
case "RSA1_5":
|
|
case "RSA-OAEP":
|
|
case "RSA-OAEP-256":
|
|
case "RSA-OAEP-384":
|
|
case "RSA-OAEP-512": {
|
|
if (encryptedKey === void 0)
|
|
throw new JWEInvalid("JWE Encrypted Key missing");
|
|
return decrypt3(alg, key, encryptedKey);
|
|
}
|
|
case "PBES2-HS256+A128KW":
|
|
case "PBES2-HS384+A192KW":
|
|
case "PBES2-HS512+A256KW": {
|
|
if (encryptedKey === void 0)
|
|
throw new JWEInvalid("JWE Encrypted Key missing");
|
|
if (typeof joseHeader.p2c !== "number")
|
|
throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`);
|
|
if (typeof joseHeader.p2s !== "string")
|
|
throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`);
|
|
return decrypt2(alg, key, encryptedKey, joseHeader.p2c, decode(joseHeader.p2s));
|
|
}
|
|
case "A128KW":
|
|
case "A192KW":
|
|
case "A256KW": {
|
|
if (encryptedKey === void 0)
|
|
throw new JWEInvalid("JWE Encrypted Key missing");
|
|
return unwrap(alg, key, encryptedKey);
|
|
}
|
|
case "A128GCMKW":
|
|
case "A192GCMKW":
|
|
case "A256GCMKW": {
|
|
if (encryptedKey === void 0)
|
|
throw new JWEInvalid("JWE Encrypted Key missing");
|
|
if (typeof joseHeader.iv !== "string")
|
|
throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`);
|
|
if (typeof joseHeader.tag !== "string")
|
|
throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`);
|
|
const iv = decode(joseHeader.iv);
|
|
const tag = decode(joseHeader.tag);
|
|
return unwrap2(alg, key, encryptedKey, iv, tag);
|
|
}
|
|
default: {
|
|
throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value');
|
|
}
|
|
}
|
|
}
|
|
var decrypt_key_management_default = decryptKeyManagement;
|
|
|
|
// dist/browser/lib/validate_crit.js
|
|
function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
|
|
if (joseHeader.crit !== void 0 && protectedHeader.crit === void 0) {
|
|
throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
|
|
}
|
|
if (!protectedHeader || protectedHeader.crit === void 0) {
|
|
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 !== void 0) {
|
|
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] === void 0) {
|
|
throw new Err(`Extension Header Parameter "${parameter}" is missing`);
|
|
} else if (recognized.get(parameter) && protectedHeader[parameter] === void 0) {
|
|
throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`);
|
|
}
|
|
}
|
|
return new Set(protectedHeader.crit);
|
|
}
|
|
var validate_crit_default = validateCrit;
|
|
|
|
// dist/browser/lib/validate_algorithms.js
|
|
var validateAlgorithms = (option, algorithms) => {
|
|
if (algorithms !== void 0 && (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== "string"))) {
|
|
throw new TypeError(`"${option}" option must be an array of strings`);
|
|
}
|
|
if (!algorithms) {
|
|
return void 0;
|
|
}
|
|
return new Set(algorithms);
|
|
};
|
|
var validate_algorithms_default = validateAlgorithms;
|
|
|
|
// dist/browser/jwe/flattened/decrypt.js
|
|
async function flattenedDecrypt(jwe, key, options) {
|
|
var _a;
|
|
if (!isObject(jwe)) {
|
|
throw new JWEInvalid("Flattened JWE must be an object");
|
|
}
|
|
if (jwe.protected === void 0 && jwe.header === void 0 && jwe.unprotected === void 0) {
|
|
throw new JWEInvalid("JOSE Header missing");
|
|
}
|
|
if (typeof jwe.iv !== "string") {
|
|
throw new JWEInvalid("JWE Initialization Vector missing or incorrect type");
|
|
}
|
|
if (typeof jwe.ciphertext !== "string") {
|
|
throw new JWEInvalid("JWE Ciphertext missing or incorrect type");
|
|
}
|
|
if (typeof jwe.tag !== "string") {
|
|
throw new JWEInvalid("JWE Authentication Tag missing or incorrect type");
|
|
}
|
|
if (jwe.protected !== void 0 && typeof jwe.protected !== "string") {
|
|
throw new JWEInvalid("JWE Protected Header incorrect type");
|
|
}
|
|
if (jwe.encrypted_key !== void 0 && typeof jwe.encrypted_key !== "string") {
|
|
throw new JWEInvalid("JWE Encrypted Key incorrect type");
|
|
}
|
|
if (jwe.aad !== void 0 && typeof jwe.aad !== "string") {
|
|
throw new JWEInvalid("JWE AAD incorrect type");
|
|
}
|
|
if (jwe.header !== void 0 && !isObject(jwe.header)) {
|
|
throw new JWEInvalid("JWE Shared Unprotected Header incorrect type");
|
|
}
|
|
if (jwe.unprotected !== void 0 && !isObject(jwe.unprotected)) {
|
|
throw new JWEInvalid("JWE Per-Recipient Unprotected Header incorrect type");
|
|
}
|
|
let parsedProt;
|
|
if (jwe.protected) {
|
|
const protectedHeader2 = decode(jwe.protected);
|
|
try {
|
|
parsedProt = JSON.parse(decoder.decode(protectedHeader2));
|
|
} catch (_b) {
|
|
throw new JWEInvalid("JWE Protected Header is invalid");
|
|
}
|
|
}
|
|
if (!is_disjoint_default(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
|
|
};
|
|
validate_crit_default(JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader);
|
|
if (joseHeader.zip !== void 0) {
|
|
if (!parsedProt || !parsedProt.zip) {
|
|
throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');
|
|
}
|
|
if (joseHeader.zip !== "DEF") {
|
|
throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value');
|
|
}
|
|
}
|
|
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 && validate_algorithms_default("keyManagementAlgorithms", options.keyManagementAlgorithms);
|
|
const contentEncryptionAlgorithms = options && validate_algorithms_default("contentEncryptionAlgorithms", options.contentEncryptionAlgorithms);
|
|
if (keyManagementAlgorithms && !keyManagementAlgorithms.has(alg)) {
|
|
throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed');
|
|
}
|
|
if (contentEncryptionAlgorithms && !contentEncryptionAlgorithms.has(enc)) {
|
|
throw new JOSEAlgNotAllowed('"enc" (Encryption Algorithm) Header Parameter not allowed');
|
|
}
|
|
let encryptedKey;
|
|
if (jwe.encrypted_key !== void 0) {
|
|
encryptedKey = decode(jwe.encrypted_key);
|
|
}
|
|
let resolvedKey = false;
|
|
if (typeof key === "function") {
|
|
key = await key(parsedProt, jwe);
|
|
resolvedKey = true;
|
|
}
|
|
let cek;
|
|
try {
|
|
cek = await decrypt_key_management_default(alg, key, encryptedKey, joseHeader);
|
|
} catch (err) {
|
|
if (err instanceof TypeError) {
|
|
throw err;
|
|
}
|
|
cek = cek_default(enc);
|
|
}
|
|
const iv = decode(jwe.iv);
|
|
const tag = decode(jwe.tag);
|
|
const protectedHeader = encoder.encode((_a = jwe.protected) !== null && _a !== void 0 ? _a : "");
|
|
let additionalData;
|
|
if (jwe.aad !== void 0) {
|
|
additionalData = concat(protectedHeader, encoder.encode("."), encoder.encode(jwe.aad));
|
|
} else {
|
|
additionalData = protectedHeader;
|
|
}
|
|
let plaintext = await decrypt_default(enc, cek, decode(jwe.ciphertext), iv, tag, additionalData);
|
|
if (joseHeader.zip === "DEF") {
|
|
plaintext = await ((options === null || options === void 0 ? void 0 : options.inflateRaw) || inflate)(plaintext);
|
|
}
|
|
const result = { plaintext };
|
|
if (jwe.protected !== void 0) {
|
|
result.protectedHeader = parsedProt;
|
|
}
|
|
if (jwe.aad !== void 0) {
|
|
result.additionalAuthenticatedData = decode(jwe.aad);
|
|
}
|
|
if (jwe.unprotected !== void 0) {
|
|
result.sharedUnprotectedHeader = jwe.unprotected;
|
|
}
|
|
if (jwe.header !== void 0) {
|
|
result.unprotectedHeader = jwe.header;
|
|
}
|
|
if (resolvedKey) {
|
|
return { ...result, key };
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// dist/browser/jwe/compact/decrypt.js
|
|
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: ciphertext || void 0,
|
|
iv: iv || void 0,
|
|
protected: protectedHeader || void 0,
|
|
tag: tag || void 0,
|
|
encrypted_key: encryptedKey || void 0
|
|
}, key, options);
|
|
const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader };
|
|
if (typeof key === "function") {
|
|
return { ...result, key: decrypted.key };
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// dist/browser/jwe/general/decrypt.js
|
|
async function generalDecrypt(jwe, key, options) {
|
|
if (!isObject(jwe)) {
|
|
throw new JWEInvalid("General JWE must be an object");
|
|
}
|
|
if (!Array.isArray(jwe.recipients) || !jwe.recipients.every(isObject)) {
|
|
throw new JWEInvalid("JWE Recipients missing or incorrect type");
|
|
}
|
|
if (!jwe.recipients.length) {
|
|
throw new JWEInvalid("JWE Recipients has no members");
|
|
}
|
|
for (const recipient of jwe.recipients) {
|
|
try {
|
|
return await flattenedDecrypt({
|
|
aad: jwe.aad,
|
|
ciphertext: jwe.ciphertext,
|
|
encrypted_key: recipient.encrypted_key,
|
|
header: recipient.header,
|
|
iv: jwe.iv,
|
|
protected: jwe.protected,
|
|
tag: jwe.tag,
|
|
unprotected: jwe.unprotected
|
|
}, key, options);
|
|
} catch (_a) {
|
|
}
|
|
}
|
|
throw new JWEDecryptionFailed();
|
|
}
|
|
|
|
// dist/browser/runtime/key_to_jwk.js
|
|
var keyToJWK = async (key) => {
|
|
if (key instanceof Uint8Array) {
|
|
return {
|
|
kty: "oct",
|
|
k: encode(key)
|
|
};
|
|
}
|
|
if (!isCryptoKey(key)) {
|
|
throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array"));
|
|
}
|
|
if (!key.extractable) {
|
|
throw new TypeError("non-extractable CryptoKey cannot be exported as a JWK");
|
|
}
|
|
const { ext, key_ops, alg, use, ...jwk } = await webcrypto_default.subtle.exportKey("jwk", key);
|
|
return jwk;
|
|
};
|
|
var key_to_jwk_default = keyToJWK;
|
|
|
|
// dist/browser/key/export.js
|
|
async function exportSPKI(key) {
|
|
return toSPKI(key);
|
|
}
|
|
async function exportPKCS8(key) {
|
|
return toPKCS8(key);
|
|
}
|
|
async function exportJWK(key) {
|
|
return key_to_jwk_default(key);
|
|
}
|
|
|
|
// dist/browser/lib/encrypt_key_management.js
|
|
async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) {
|
|
let encryptedKey;
|
|
let parameters;
|
|
let cek;
|
|
check_key_type_default(alg, key, "encrypt");
|
|
switch (alg) {
|
|
case "dir": {
|
|
cek = key;
|
|
break;
|
|
}
|
|
case "ECDH-ES":
|
|
case "ECDH-ES+A128KW":
|
|
case "ECDH-ES+A192KW":
|
|
case "ECDH-ES+A256KW": {
|
|
if (!ecdhAllowed(key)) {
|
|
throw new JOSENotSupported("ECDH-ES with the provided key is not allowed or not supported by your javascript runtime");
|
|
}
|
|
const { apu, apv } = providedParameters;
|
|
let { epk: ephemeralKey } = providedParameters;
|
|
ephemeralKey || (ephemeralKey = await generateEpk(key));
|
|
const { x, y, crv, kty } = await exportJWK(ephemeralKey);
|
|
const sharedSecret = await deriveKey(key, ephemeralKey, alg === "ECDH-ES" ? enc : alg, alg === "ECDH-ES" ? bitLength2(enc) : parseInt(alg.substr(-5, 3), 10), apu, apv);
|
|
parameters = { epk: { x, y, crv, kty } };
|
|
if (apu)
|
|
parameters.apu = encode(apu);
|
|
if (apv)
|
|
parameters.apv = encode(apv);
|
|
if (alg === "ECDH-ES") {
|
|
cek = sharedSecret;
|
|
break;
|
|
}
|
|
cek = providedCek || cek_default(enc);
|
|
const kwAlg = alg.substr(-6);
|
|
encryptedKey = await wrap(kwAlg, sharedSecret, cek);
|
|
break;
|
|
}
|
|
case "RSA1_5":
|
|
case "RSA-OAEP":
|
|
case "RSA-OAEP-256":
|
|
case "RSA-OAEP-384":
|
|
case "RSA-OAEP-512": {
|
|
cek = providedCek || cek_default(enc);
|
|
encryptedKey = await encrypt2(alg, key, cek);
|
|
break;
|
|
}
|
|
case "PBES2-HS256+A128KW":
|
|
case "PBES2-HS384+A192KW":
|
|
case "PBES2-HS512+A256KW": {
|
|
cek = providedCek || cek_default(enc);
|
|
const { p2c, p2s: p2s2 } = providedParameters;
|
|
({ encryptedKey, ...parameters } = await encrypt(alg, key, cek, p2c, p2s2));
|
|
break;
|
|
}
|
|
case "A128KW":
|
|
case "A192KW":
|
|
case "A256KW": {
|
|
cek = providedCek || cek_default(enc);
|
|
encryptedKey = await wrap(alg, key, cek);
|
|
break;
|
|
}
|
|
case "A128GCMKW":
|
|
case "A192GCMKW":
|
|
case "A256GCMKW": {
|
|
cek = providedCek || cek_default(enc);
|
|
const { iv } = providedParameters;
|
|
({ encryptedKey, ...parameters } = await wrap2(alg, key, cek, iv));
|
|
break;
|
|
}
|
|
default: {
|
|
throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value');
|
|
}
|
|
}
|
|
return { cek, encryptedKey, parameters };
|
|
}
|
|
var encrypt_key_management_default = encryptKeyManagement;
|
|
|
|
// dist/browser/jwe/flattened/encrypt.js
|
|
var unprotected = Symbol();
|
|
var FlattenedEncrypt = class {
|
|
constructor(plaintext) {
|
|
if (!(plaintext instanceof Uint8Array)) {
|
|
throw new TypeError("plaintext must be an instance of Uint8Array");
|
|
}
|
|
this._plaintext = plaintext;
|
|
}
|
|
setKeyManagementParameters(parameters) {
|
|
if (this._keyManagementParameters) {
|
|
throw new TypeError("setKeyManagementParameters can only be called once");
|
|
}
|
|
this._keyManagementParameters = parameters;
|
|
return this;
|
|
}
|
|
setProtectedHeader(protectedHeader) {
|
|
if (this._protectedHeader) {
|
|
throw new TypeError("setProtectedHeader can only be called once");
|
|
}
|
|
this._protectedHeader = protectedHeader;
|
|
return this;
|
|
}
|
|
setSharedUnprotectedHeader(sharedUnprotectedHeader) {
|
|
if (this._sharedUnprotectedHeader) {
|
|
throw new TypeError("setSharedUnprotectedHeader can only be called once");
|
|
}
|
|
this._sharedUnprotectedHeader = sharedUnprotectedHeader;
|
|
return this;
|
|
}
|
|
setUnprotectedHeader(unprotectedHeader) {
|
|
if (this._unprotectedHeader) {
|
|
throw new TypeError("setUnprotectedHeader can only be called once");
|
|
}
|
|
this._unprotectedHeader = unprotectedHeader;
|
|
return this;
|
|
}
|
|
setAdditionalAuthenticatedData(aad) {
|
|
this._aad = aad;
|
|
return this;
|
|
}
|
|
setContentEncryptionKey(cek) {
|
|
if (this._cek) {
|
|
throw new TypeError("setContentEncryptionKey can only be called once");
|
|
}
|
|
this._cek = cek;
|
|
return this;
|
|
}
|
|
setInitializationVector(iv) {
|
|
if (this._iv) {
|
|
throw new TypeError("setInitializationVector can only be called once");
|
|
}
|
|
this._iv = iv;
|
|
return this;
|
|
}
|
|
async encrypt(key, options) {
|
|
if (!this._protectedHeader && !this._unprotectedHeader && !this._sharedUnprotectedHeader) {
|
|
throw new JWEInvalid("either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()");
|
|
}
|
|
if (!is_disjoint_default(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
|
|
};
|
|
validate_crit_default(JWEInvalid, new Map(), options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader);
|
|
if (joseHeader.zip !== void 0) {
|
|
if (!this._protectedHeader || !this._protectedHeader.zip) {
|
|
throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');
|
|
}
|
|
if (joseHeader.zip !== "DEF") {
|
|
throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value');
|
|
}
|
|
}
|
|
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 (alg === "dir") {
|
|
if (this._cek) {
|
|
throw new TypeError("setContentEncryptionKey cannot be called when using Direct Encryption");
|
|
}
|
|
} else if (alg === "ECDH-ES") {
|
|
if (this._cek) {
|
|
throw new TypeError("setContentEncryptionKey cannot be called when using Direct Key Agreement");
|
|
}
|
|
}
|
|
let cek;
|
|
{
|
|
let parameters;
|
|
({ cek, encryptedKey, parameters } = await encrypt_key_management_default(alg, enc, key, 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 };
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this._iv || (this._iv = iv_default(enc));
|
|
let additionalData;
|
|
let protectedHeader;
|
|
let aadMember;
|
|
if (this._protectedHeader) {
|
|
protectedHeader = encoder.encode(encode(JSON.stringify(this._protectedHeader)));
|
|
} else {
|
|
protectedHeader = encoder.encode("");
|
|
}
|
|
if (this._aad) {
|
|
aadMember = encode(this._aad);
|
|
additionalData = concat(protectedHeader, encoder.encode("."), encoder.encode(aadMember));
|
|
} else {
|
|
additionalData = protectedHeader;
|
|
}
|
|
let ciphertext;
|
|
let tag;
|
|
if (joseHeader.zip === "DEF") {
|
|
const deflated = await ((options === null || options === void 0 ? void 0 : options.deflateRaw) || deflate)(this._plaintext);
|
|
({ ciphertext, tag } = await encrypt_default(enc, deflated, cek, this._iv, additionalData));
|
|
} else {
|
|
;
|
|
({ ciphertext, tag } = await encrypt_default(enc, this._plaintext, cek, this._iv, additionalData));
|
|
}
|
|
const jwe = {
|
|
ciphertext: encode(ciphertext),
|
|
iv: encode(this._iv),
|
|
tag: encode(tag)
|
|
};
|
|
if (encryptedKey) {
|
|
jwe.encrypted_key = encode(encryptedKey);
|
|
}
|
|
if (aadMember) {
|
|
jwe.aad = aadMember;
|
|
}
|
|
if (this._protectedHeader) {
|
|
jwe.protected = decoder.decode(protectedHeader);
|
|
}
|
|
if (this._sharedUnprotectedHeader) {
|
|
jwe.unprotected = this._sharedUnprotectedHeader;
|
|
}
|
|
if (this._unprotectedHeader) {
|
|
jwe.header = this._unprotectedHeader;
|
|
}
|
|
return jwe;
|
|
}
|
|
};
|
|
|
|
// dist/browser/jwe/general/encrypt.js
|
|
var IndividualRecipient = class {
|
|
constructor(enc, key, options) {
|
|
this.parent = enc;
|
|
this.key = key;
|
|
this.options = options;
|
|
}
|
|
setUnprotectedHeader(unprotectedHeader) {
|
|
if (this.unprotectedHeader) {
|
|
throw new TypeError("setUnprotectedHeader can only be called once");
|
|
}
|
|
this.unprotectedHeader = unprotectedHeader;
|
|
return this;
|
|
}
|
|
addRecipient(...args) {
|
|
return this.parent.addRecipient(...args);
|
|
}
|
|
encrypt(...args) {
|
|
return this.parent.encrypt(...args);
|
|
}
|
|
done() {
|
|
return this.parent;
|
|
}
|
|
};
|
|
var GeneralEncrypt = class {
|
|
constructor(plaintext) {
|
|
this._recipients = [];
|
|
this._plaintext = plaintext;
|
|
}
|
|
addRecipient(key, options) {
|
|
const recipient = new IndividualRecipient(this, key, { crit: options === null || options === void 0 ? void 0 : options.crit });
|
|
this._recipients.push(recipient);
|
|
return recipient;
|
|
}
|
|
setProtectedHeader(protectedHeader) {
|
|
if (this._protectedHeader) {
|
|
throw new TypeError("setProtectedHeader can only be called once");
|
|
}
|
|
this._protectedHeader = protectedHeader;
|
|
return this;
|
|
}
|
|
setSharedUnprotectedHeader(sharedUnprotectedHeader) {
|
|
if (this._unprotectedHeader) {
|
|
throw new TypeError("setSharedUnprotectedHeader can only be called once");
|
|
}
|
|
this._unprotectedHeader = sharedUnprotectedHeader;
|
|
return this;
|
|
}
|
|
setAdditionalAuthenticatedData(aad) {
|
|
this._aad = aad;
|
|
return this;
|
|
}
|
|
async encrypt(options) {
|
|
var _a, _b, _c;
|
|
if (!this._recipients.length) {
|
|
throw new JWEInvalid("at least one recipient must be added");
|
|
}
|
|
options = { deflateRaw: options === null || options === void 0 ? void 0 : options.deflateRaw };
|
|
if (this._recipients.length === 1) {
|
|
const [recipient] = this._recipients;
|
|
const flattened = await new FlattenedEncrypt(this._plaintext).setAdditionalAuthenticatedData(this._aad).setProtectedHeader(this._protectedHeader).setSharedUnprotectedHeader(this._unprotectedHeader).setUnprotectedHeader(recipient.unprotectedHeader).encrypt(recipient.key, { ...recipient.options, ...options });
|
|
let jwe2 = {
|
|
ciphertext: flattened.ciphertext,
|
|
iv: flattened.iv,
|
|
recipients: [{}],
|
|
tag: flattened.tag
|
|
};
|
|
if (flattened.aad)
|
|
jwe2.aad = flattened.aad;
|
|
if (flattened.protected)
|
|
jwe2.protected = flattened.protected;
|
|
if (flattened.unprotected)
|
|
jwe2.unprotected = flattened.unprotected;
|
|
if (flattened.encrypted_key)
|
|
jwe2.recipients[0].encrypted_key = flattened.encrypted_key;
|
|
if (flattened.header)
|
|
jwe2.recipients[0].header = flattened.header;
|
|
return jwe2;
|
|
}
|
|
let enc;
|
|
for (let i = 0; i < this._recipients.length; i++) {
|
|
const recipient = this._recipients[i];
|
|
if (!is_disjoint_default(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 { alg } = joseHeader;
|
|
if (typeof alg !== "string" || !alg) {
|
|
throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid');
|
|
}
|
|
if (alg === "dir" || 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;
|
|
} else if (enc !== joseHeader.enc) {
|
|
throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients');
|
|
}
|
|
validate_crit_default(JWEInvalid, new Map(), recipient.options.crit, this._protectedHeader, joseHeader);
|
|
if (joseHeader.zip !== void 0) {
|
|
if (!this._protectedHeader || !this._protectedHeader.zip) {
|
|
throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');
|
|
}
|
|
}
|
|
}
|
|
const cek = cek_default(enc);
|
|
let jwe = {
|
|
ciphertext: "",
|
|
iv: "",
|
|
recipients: [],
|
|
tag: ""
|
|
};
|
|
for (let i = 0; i < this._recipients.length; i++) {
|
|
const recipient = this._recipients[i];
|
|
const target = {};
|
|
jwe.recipients.push(target);
|
|
if (i === 0) {
|
|
const flattened = await new FlattenedEncrypt(this._plaintext).setAdditionalAuthenticatedData(this._aad).setContentEncryptionKey(cek).setProtectedHeader(this._protectedHeader).setSharedUnprotectedHeader(this._unprotectedHeader).setUnprotectedHeader(recipient.unprotectedHeader).encrypt(recipient.key, {
|
|
...recipient.options,
|
|
...options,
|
|
[unprotected]: true
|
|
});
|
|
jwe.ciphertext = flattened.ciphertext;
|
|
jwe.iv = flattened.iv;
|
|
jwe.tag = flattened.tag;
|
|
if (flattened.aad)
|
|
jwe.aad = flattened.aad;
|
|
if (flattened.protected)
|
|
jwe.protected = flattened.protected;
|
|
if (flattened.unprotected)
|
|
jwe.unprotected = flattened.unprotected;
|
|
target.encrypted_key = flattened.encrypted_key;
|
|
if (flattened.header)
|
|
target.header = flattened.header;
|
|
continue;
|
|
}
|
|
const { encryptedKey, parameters } = await encrypt_key_management_default(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) || ((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) || ((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek);
|
|
target.encrypted_key = encode(encryptedKey);
|
|
if (recipient.unprotectedHeader || parameters)
|
|
target.header = { ...recipient.unprotectedHeader, ...parameters };
|
|
}
|
|
return jwe;
|
|
}
|
|
};
|
|
|
|
// dist/browser/runtime/subtle_dsa.js
|
|
function subtleDsa(alg, namedCurve) {
|
|
const length = parseInt(alg.substr(-3), 10);
|
|
switch (alg) {
|
|
case "HS256":
|
|
case "HS384":
|
|
case "HS512":
|
|
return { hash: `SHA-${length}`, name: "HMAC" };
|
|
case "PS256":
|
|
case "PS384":
|
|
case "PS512":
|
|
return { hash: `SHA-${length}`, name: "RSA-PSS", saltLength: length >> 3 };
|
|
case "RS256":
|
|
case "RS384":
|
|
case "RS512":
|
|
return { hash: `SHA-${length}`, name: "RSASSA-PKCS1-v1_5" };
|
|
case "ES256":
|
|
case "ES384":
|
|
case "ES512":
|
|
return { hash: `SHA-${length}`, name: "ECDSA", namedCurve };
|
|
case ((isCloudflareWorkers() || isNodeJs()) && "EdDSA"):
|
|
return { name: namedCurve, namedCurve };
|
|
default:
|
|
throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
|
|
}
|
|
}
|
|
|
|
// dist/browser/runtime/get_sign_verify_key.js
|
|
function getCryptoKey3(alg, key, usage) {
|
|
if (isCryptoKey(key)) {
|
|
checkSigCryptoKey(key, alg, usage);
|
|
return key;
|
|
}
|
|
if (key instanceof Uint8Array) {
|
|
if (!alg.startsWith("HS")) {
|
|
throw new TypeError(invalid_key_input_default(key, ...types));
|
|
}
|
|
return webcrypto_default.subtle.importKey("raw", key, { hash: `SHA-${alg.substr(-3)}`, name: "HMAC" }, false, [usage]);
|
|
}
|
|
throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array"));
|
|
}
|
|
|
|
// dist/browser/runtime/verify.js
|
|
var verify = async (alg, key, signature, data) => {
|
|
const cryptoKey = await getCryptoKey3(alg, key, "verify");
|
|
check_key_length_default(alg, cryptoKey);
|
|
const algorithm = subtleDsa(alg, cryptoKey.algorithm.namedCurve);
|
|
try {
|
|
return await webcrypto_default.subtle.verify(algorithm, cryptoKey, signature, data);
|
|
} catch (_a) {
|
|
return false;
|
|
}
|
|
};
|
|
var verify_default = verify;
|
|
|
|
// dist/browser/jws/flattened/verify.js
|
|
async function flattenedVerify(jws, key, options) {
|
|
var _a;
|
|
if (!isObject(jws)) {
|
|
throw new JWSInvalid("Flattened JWS must be an object");
|
|
}
|
|
if (jws.protected === void 0 && jws.header === void 0) {
|
|
throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members');
|
|
}
|
|
if (jws.protected !== void 0 && typeof jws.protected !== "string") {
|
|
throw new JWSInvalid("JWS Protected Header incorrect type");
|
|
}
|
|
if (jws.payload === void 0) {
|
|
throw new JWSInvalid("JWS Payload missing");
|
|
}
|
|
if (typeof jws.signature !== "string") {
|
|
throw new JWSInvalid("JWS Signature missing or incorrect type");
|
|
}
|
|
if (jws.header !== void 0 && !isObject(jws.header)) {
|
|
throw new JWSInvalid("JWS Unprotected Header incorrect type");
|
|
}
|
|
let parsedProt = {};
|
|
if (jws.protected) {
|
|
const protectedHeader = decode(jws.protected);
|
|
try {
|
|
parsedProt = JSON.parse(decoder.decode(protectedHeader));
|
|
} catch (_b) {
|
|
throw new JWSInvalid("JWS Protected Header is invalid");
|
|
}
|
|
}
|
|
if (!is_disjoint_default(parsedProt, jws.header)) {
|
|
throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
|
|
}
|
|
const joseHeader = {
|
|
...parsedProt,
|
|
...jws.header
|
|
};
|
|
const extensions = validate_crit_default(JWSInvalid, new Map([["b64", true]]), options === null || options === void 0 ? void 0 : 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 && validate_algorithms_default("algorithms", options.algorithms);
|
|
if (algorithms && !algorithms.has(alg)) {
|
|
throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter 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;
|
|
}
|
|
check_key_type_default(alg, key, "verify");
|
|
const data = concat(encoder.encode((_a = jws.protected) !== null && _a !== void 0 ? _a : ""), encoder.encode("."), typeof jws.payload === "string" ? encoder.encode(jws.payload) : jws.payload);
|
|
const signature = decode(jws.signature);
|
|
const verified = await verify_default(alg, key, signature, data);
|
|
if (!verified) {
|
|
throw new JWSSignatureVerificationFailed();
|
|
}
|
|
let payload;
|
|
if (b64) {
|
|
payload = decode(jws.payload);
|
|
} else if (typeof jws.payload === "string") {
|
|
payload = encoder.encode(jws.payload);
|
|
} else {
|
|
payload = jws.payload;
|
|
}
|
|
const result = { payload };
|
|
if (jws.protected !== void 0) {
|
|
result.protectedHeader = parsedProt;
|
|
}
|
|
if (jws.header !== void 0) {
|
|
result.unprotectedHeader = jws.header;
|
|
}
|
|
if (resolvedKey) {
|
|
return { ...result, key };
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// dist/browser/jws/compact/verify.js
|
|
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: payload || void 0,
|
|
protected: protectedHeader || void 0,
|
|
signature: signature || void 0
|
|
}, key, options);
|
|
const result = { payload: verified.payload, protectedHeader: verified.protectedHeader };
|
|
if (typeof key === "function") {
|
|
return { ...result, key: verified.key };
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// dist/browser/jws/general/verify.js
|
|
async function generalVerify(jws, key, options) {
|
|
if (!isObject(jws)) {
|
|
throw new JWSInvalid("General JWS must be an object");
|
|
}
|
|
if (!Array.isArray(jws.signatures) || !jws.signatures.every(isObject)) {
|
|
throw new JWSInvalid("JWS Signatures missing or incorrect type");
|
|
}
|
|
for (const signature of jws.signatures) {
|
|
try {
|
|
return await flattenedVerify({
|
|
header: signature.header,
|
|
payload: jws.payload,
|
|
protected: signature.protected,
|
|
signature: signature.signature
|
|
}, key, options);
|
|
} catch (_a) {
|
|
}
|
|
}
|
|
throw new JWSSignatureVerificationFailed();
|
|
}
|
|
|
|
// dist/browser/lib/epoch.js
|
|
var epoch_default = (date) => Math.floor(date.getTime() / 1e3);
|
|
|
|
// dist/browser/lib/secs.js
|
|
var minute = 60;
|
|
var hour = minute * 60;
|
|
var day = hour * 24;
|
|
var week = day * 7;
|
|
var year = day * 365.25;
|
|
var REGEX = /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i;
|
|
var secs_default = (str) => {
|
|
const matched = REGEX.exec(str);
|
|
if (!matched) {
|
|
throw new TypeError("Invalid time period format");
|
|
}
|
|
const value = parseFloat(matched[1]);
|
|
const unit = matched[2].toLowerCase();
|
|
switch (unit) {
|
|
case "sec":
|
|
case "secs":
|
|
case "second":
|
|
case "seconds":
|
|
case "s":
|
|
return Math.round(value);
|
|
case "minute":
|
|
case "minutes":
|
|
case "min":
|
|
case "mins":
|
|
case "m":
|
|
return Math.round(value * minute);
|
|
case "hour":
|
|
case "hours":
|
|
case "hr":
|
|
case "hrs":
|
|
case "h":
|
|
return Math.round(value * hour);
|
|
case "day":
|
|
case "days":
|
|
case "d":
|
|
return Math.round(value * day);
|
|
case "week":
|
|
case "weeks":
|
|
case "w":
|
|
return Math.round(value * week);
|
|
default:
|
|
return Math.round(value * year);
|
|
}
|
|
};
|
|
|
|
// dist/browser/lib/jwt_claims_set.js
|
|
var normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, "");
|
|
var checkAudiencePresence = (audPayload, audOption) => {
|
|
if (typeof audPayload === "string") {
|
|
return audOption.includes(audPayload);
|
|
}
|
|
if (Array.isArray(audPayload)) {
|
|
return audOption.some(Set.prototype.has.bind(new Set(audPayload)));
|
|
}
|
|
return false;
|
|
};
|
|
var jwt_claims_set_default = (protectedHeader, encodedPayload, options = {}) => {
|
|
const { typ } = options;
|
|
if (typ && (typeof protectedHeader.typ !== "string" || normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) {
|
|
throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', "typ", "check_failed");
|
|
}
|
|
let payload;
|
|
try {
|
|
payload = JSON.parse(decoder.decode(encodedPayload));
|
|
} catch (_a) {
|
|
}
|
|
if (!isObject(payload)) {
|
|
throw new JWTInvalid("JWT Claims Set must be a top-level JSON object");
|
|
}
|
|
const { issuer } = options;
|
|
if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) {
|
|
throw new JWTClaimValidationFailed('unexpected "iss" claim value', "iss", "check_failed");
|
|
}
|
|
const { subject } = options;
|
|
if (subject && payload.sub !== subject) {
|
|
throw new JWTClaimValidationFailed('unexpected "sub" claim value', "sub", "check_failed");
|
|
}
|
|
const { audience } = options;
|
|
if (audience && !checkAudiencePresence(payload.aud, typeof audience === "string" ? [audience] : audience)) {
|
|
throw new JWTClaimValidationFailed('unexpected "aud" claim value', "aud", "check_failed");
|
|
}
|
|
let tolerance;
|
|
switch (typeof options.clockTolerance) {
|
|
case "string":
|
|
tolerance = secs_default(options.clockTolerance);
|
|
break;
|
|
case "number":
|
|
tolerance = options.clockTolerance;
|
|
break;
|
|
case "undefined":
|
|
tolerance = 0;
|
|
break;
|
|
default:
|
|
throw new TypeError("Invalid clockTolerance option type");
|
|
}
|
|
const { currentDate } = options;
|
|
const now = epoch_default(currentDate || new Date());
|
|
if (payload.iat !== void 0 || options.maxTokenAge) {
|
|
if (typeof payload.iat !== "number") {
|
|
throw new JWTClaimValidationFailed('"iat" claim must be a number', "iat", "invalid");
|
|
}
|
|
if (payload.exp === void 0 && payload.iat > now + tolerance) {
|
|
throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', "iat", "check_failed");
|
|
}
|
|
}
|
|
if (payload.nbf !== void 0) {
|
|
if (typeof payload.nbf !== "number") {
|
|
throw new JWTClaimValidationFailed('"nbf" claim must be a number', "nbf", "invalid");
|
|
}
|
|
if (payload.nbf > now + tolerance) {
|
|
throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', "nbf", "check_failed");
|
|
}
|
|
}
|
|
if (payload.exp !== void 0) {
|
|
if (typeof payload.exp !== "number") {
|
|
throw new JWTClaimValidationFailed('"exp" claim must be a number', "exp", "invalid");
|
|
}
|
|
if (payload.exp <= now - tolerance) {
|
|
throw new JWTExpired('"exp" claim timestamp check failed', "exp", "check_failed");
|
|
}
|
|
}
|
|
if (options.maxTokenAge) {
|
|
const age = now - payload.iat;
|
|
const max = typeof options.maxTokenAge === "number" ? options.maxTokenAge : secs_default(options.maxTokenAge);
|
|
if (age - tolerance > max) {
|
|
throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', "iat", "check_failed");
|
|
}
|
|
if (age < 0 - tolerance) {
|
|
throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', "iat", "check_failed");
|
|
}
|
|
}
|
|
return payload;
|
|
};
|
|
|
|
// dist/browser/jwt/verify.js
|
|
async function jwtVerify(jwt, key, options) {
|
|
var _a;
|
|
const verified = await compactVerify(jwt, key, options);
|
|
if (((_a = verified.protectedHeader.crit) === null || _a === void 0 ? void 0 : _a.includes("b64")) && verified.protectedHeader.b64 === false) {
|
|
throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
|
|
}
|
|
const payload = jwt_claims_set_default(verified.protectedHeader, verified.payload, options);
|
|
const result = { payload, protectedHeader: verified.protectedHeader };
|
|
if (typeof key === "function") {
|
|
return { ...result, key: verified.key };
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// dist/browser/jwt/decrypt.js
|
|
async function jwtDecrypt(jwt, key, options) {
|
|
const decrypted = await compactDecrypt(jwt, key, options);
|
|
const payload = jwt_claims_set_default(decrypted.protectedHeader, decrypted.plaintext, options);
|
|
const { protectedHeader } = decrypted;
|
|
if (protectedHeader.iss !== void 0 && protectedHeader.iss !== payload.iss) {
|
|
throw new JWTClaimValidationFailed('replicated "iss" claim header parameter mismatch', "iss", "mismatch");
|
|
}
|
|
if (protectedHeader.sub !== void 0 && protectedHeader.sub !== payload.sub) {
|
|
throw new JWTClaimValidationFailed('replicated "sub" claim header parameter mismatch', "sub", "mismatch");
|
|
}
|
|
if (protectedHeader.aud !== void 0 && JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud)) {
|
|
throw new JWTClaimValidationFailed('replicated "aud" claim header parameter mismatch', "aud", "mismatch");
|
|
}
|
|
const result = { payload, protectedHeader };
|
|
if (typeof key === "function") {
|
|
return { ...result, key: decrypted.key };
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// dist/browser/jwe/compact/encrypt.js
|
|
var CompactEncrypt = class {
|
|
constructor(plaintext) {
|
|
this._flattened = new FlattenedEncrypt(plaintext);
|
|
}
|
|
setContentEncryptionKey(cek) {
|
|
this._flattened.setContentEncryptionKey(cek);
|
|
return this;
|
|
}
|
|
setInitializationVector(iv) {
|
|
this._flattened.setInitializationVector(iv);
|
|
return this;
|
|
}
|
|
setProtectedHeader(protectedHeader) {
|
|
this._flattened.setProtectedHeader(protectedHeader);
|
|
return this;
|
|
}
|
|
setKeyManagementParameters(parameters) {
|
|
this._flattened.setKeyManagementParameters(parameters);
|
|
return this;
|
|
}
|
|
async encrypt(key, options) {
|
|
const jwe = await this._flattened.encrypt(key, options);
|
|
return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join(".");
|
|
}
|
|
};
|
|
|
|
// dist/browser/runtime/sign.js
|
|
var sign = async (alg, key, data) => {
|
|
const cryptoKey = await getCryptoKey3(alg, key, "sign");
|
|
check_key_length_default(alg, cryptoKey);
|
|
const signature = await webcrypto_default.subtle.sign(subtleDsa(alg, cryptoKey.algorithm.namedCurve), cryptoKey, data);
|
|
return new Uint8Array(signature);
|
|
};
|
|
var sign_default = sign;
|
|
|
|
// dist/browser/jws/flattened/sign.js
|
|
var FlattenedSign = class {
|
|
constructor(payload) {
|
|
if (!(payload instanceof Uint8Array)) {
|
|
throw new TypeError("payload must be an instance of Uint8Array");
|
|
}
|
|
this._payload = payload;
|
|
}
|
|
setProtectedHeader(protectedHeader) {
|
|
if (this._protectedHeader) {
|
|
throw new TypeError("setProtectedHeader can only be called once");
|
|
}
|
|
this._protectedHeader = protectedHeader;
|
|
return this;
|
|
}
|
|
setUnprotectedHeader(unprotectedHeader) {
|
|
if (this._unprotectedHeader) {
|
|
throw new TypeError("setUnprotectedHeader can only be called once");
|
|
}
|
|
this._unprotectedHeader = unprotectedHeader;
|
|
return this;
|
|
}
|
|
async sign(key, options) {
|
|
if (!this._protectedHeader && !this._unprotectedHeader) {
|
|
throw new JWSInvalid("either setProtectedHeader or setUnprotectedHeader must be called before #sign()");
|
|
}
|
|
if (!is_disjoint_default(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 = validate_crit_default(JWSInvalid, new Map([["b64", true]]), options === null || options === void 0 ? void 0 : 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');
|
|
}
|
|
check_key_type_default(alg, key, "sign");
|
|
let payload = this._payload;
|
|
if (b64) {
|
|
payload = encoder.encode(encode(payload));
|
|
}
|
|
let protectedHeader;
|
|
if (this._protectedHeader) {
|
|
protectedHeader = encoder.encode(encode(JSON.stringify(this._protectedHeader)));
|
|
} else {
|
|
protectedHeader = encoder.encode("");
|
|
}
|
|
const data = concat(protectedHeader, encoder.encode("."), payload);
|
|
const signature = await sign_default(alg, key, data);
|
|
const jws = {
|
|
signature: encode(signature),
|
|
payload: ""
|
|
};
|
|
if (b64) {
|
|
jws.payload = decoder.decode(payload);
|
|
}
|
|
if (this._unprotectedHeader) {
|
|
jws.header = this._unprotectedHeader;
|
|
}
|
|
if (this._protectedHeader) {
|
|
jws.protected = decoder.decode(protectedHeader);
|
|
}
|
|
return jws;
|
|
}
|
|
};
|
|
|
|
// dist/browser/jws/compact/sign.js
|
|
var CompactSign = class {
|
|
constructor(payload) {
|
|
this._flattened = new FlattenedSign(payload);
|
|
}
|
|
setProtectedHeader(protectedHeader) {
|
|
this._flattened.setProtectedHeader(protectedHeader);
|
|
return this;
|
|
}
|
|
async sign(key, options) {
|
|
const jws = await this._flattened.sign(key, options);
|
|
if (jws.payload === void 0) {
|
|
throw new TypeError("use the flattened module for creating JWS with b64: false");
|
|
}
|
|
return `${jws.protected}.${jws.payload}.${jws.signature}`;
|
|
}
|
|
};
|
|
|
|
// dist/browser/jws/general/sign.js
|
|
var IndividualSignature = class {
|
|
constructor(sig, key, options) {
|
|
this.parent = sig;
|
|
this.key = key;
|
|
this.options = options;
|
|
}
|
|
setProtectedHeader(protectedHeader) {
|
|
if (this.protectedHeader) {
|
|
throw new TypeError("setProtectedHeader can only be called once");
|
|
}
|
|
this.protectedHeader = protectedHeader;
|
|
return this;
|
|
}
|
|
setUnprotectedHeader(unprotectedHeader) {
|
|
if (this.unprotectedHeader) {
|
|
throw new TypeError("setUnprotectedHeader can only be called once");
|
|
}
|
|
this.unprotectedHeader = unprotectedHeader;
|
|
return this;
|
|
}
|
|
addSignature(...args) {
|
|
return this.parent.addSignature(...args);
|
|
}
|
|
sign(...args) {
|
|
return this.parent.sign(...args);
|
|
}
|
|
done() {
|
|
return this.parent;
|
|
}
|
|
};
|
|
var GeneralSign = class {
|
|
constructor(payload) {
|
|
this._signatures = [];
|
|
this._payload = payload;
|
|
}
|
|
addSignature(key, options) {
|
|
const signature = new IndividualSignature(this, key, options);
|
|
this._signatures.push(signature);
|
|
return signature;
|
|
}
|
|
async sign() {
|
|
if (!this._signatures.length) {
|
|
throw new JWSInvalid("at least one signature must be added");
|
|
}
|
|
const jws = {
|
|
signatures: [],
|
|
payload: ""
|
|
};
|
|
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 (i === 0) {
|
|
jws.payload = payload;
|
|
} else if (jws.payload !== payload) {
|
|
throw new JWSInvalid("inconsistent use of JWS Unencoded Payload Option (RFC7797)");
|
|
}
|
|
jws.signatures.push(rest);
|
|
}
|
|
return jws;
|
|
}
|
|
};
|
|
|
|
// dist/browser/jwt/produce.js
|
|
var ProduceJWT = class {
|
|
constructor(payload) {
|
|
if (!isObject(payload)) {
|
|
throw new TypeError("JWT Claims Set MUST be an object");
|
|
}
|
|
this._payload = payload;
|
|
}
|
|
setIssuer(issuer) {
|
|
this._payload = { ...this._payload, iss: issuer };
|
|
return this;
|
|
}
|
|
setSubject(subject) {
|
|
this._payload = { ...this._payload, sub: subject };
|
|
return this;
|
|
}
|
|
setAudience(audience) {
|
|
this._payload = { ...this._payload, aud: audience };
|
|
return this;
|
|
}
|
|
setJti(jwtId) {
|
|
this._payload = { ...this._payload, jti: jwtId };
|
|
return this;
|
|
}
|
|
setNotBefore(input) {
|
|
if (typeof input === "number") {
|
|
this._payload = { ...this._payload, nbf: input };
|
|
} else {
|
|
this._payload = { ...this._payload, nbf: epoch_default(new Date()) + secs_default(input) };
|
|
}
|
|
return this;
|
|
}
|
|
setExpirationTime(input) {
|
|
if (typeof input === "number") {
|
|
this._payload = { ...this._payload, exp: input };
|
|
} else {
|
|
this._payload = { ...this._payload, exp: epoch_default(new Date()) + secs_default(input) };
|
|
}
|
|
return this;
|
|
}
|
|
setIssuedAt(input) {
|
|
if (typeof input === "undefined") {
|
|
this._payload = { ...this._payload, iat: epoch_default(new Date()) };
|
|
} else {
|
|
this._payload = { ...this._payload, iat: input };
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
|
|
// dist/browser/jwt/sign.js
|
|
var SignJWT = class extends ProduceJWT {
|
|
setProtectedHeader(protectedHeader) {
|
|
this._protectedHeader = protectedHeader;
|
|
return this;
|
|
}
|
|
async sign(key, options) {
|
|
var _a;
|
|
const sig = new CompactSign(encoder.encode(JSON.stringify(this._payload)));
|
|
sig.setProtectedHeader(this._protectedHeader);
|
|
if (Array.isArray((_a = this._protectedHeader) === null || _a === void 0 ? void 0 : _a.crit) && this._protectedHeader.crit.includes("b64") && this._protectedHeader.b64 === false) {
|
|
throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
|
|
}
|
|
return sig.sign(key, options);
|
|
}
|
|
};
|
|
|
|
// dist/browser/jwt/encrypt.js
|
|
var EncryptJWT = class extends ProduceJWT {
|
|
setProtectedHeader(protectedHeader) {
|
|
if (this._protectedHeader) {
|
|
throw new TypeError("setProtectedHeader can only be called once");
|
|
}
|
|
this._protectedHeader = protectedHeader;
|
|
return this;
|
|
}
|
|
setKeyManagementParameters(parameters) {
|
|
if (this._keyManagementParameters) {
|
|
throw new TypeError("setKeyManagementParameters can only be called once");
|
|
}
|
|
this._keyManagementParameters = parameters;
|
|
return this;
|
|
}
|
|
setContentEncryptionKey(cek) {
|
|
if (this._cek) {
|
|
throw new TypeError("setContentEncryptionKey can only be called once");
|
|
}
|
|
this._cek = cek;
|
|
return this;
|
|
}
|
|
setInitializationVector(iv) {
|
|
if (this._iv) {
|
|
throw new TypeError("setInitializationVector can only be called once");
|
|
}
|
|
this._iv = iv;
|
|
return this;
|
|
}
|
|
replicateIssuerAsHeader() {
|
|
this._replicateIssuerAsHeader = true;
|
|
return this;
|
|
}
|
|
replicateSubjectAsHeader() {
|
|
this._replicateSubjectAsHeader = true;
|
|
return this;
|
|
}
|
|
replicateAudienceAsHeader() {
|
|
this._replicateAudienceAsHeader = true;
|
|
return this;
|
|
}
|
|
async encrypt(key, options) {
|
|
const enc = new CompactEncrypt(encoder.encode(JSON.stringify(this._payload)));
|
|
if (this._replicateIssuerAsHeader) {
|
|
this._protectedHeader = { ...this._protectedHeader, iss: this._payload.iss };
|
|
}
|
|
if (this._replicateSubjectAsHeader) {
|
|
this._protectedHeader = { ...this._protectedHeader, sub: this._payload.sub };
|
|
}
|
|
if (this._replicateAudienceAsHeader) {
|
|
this._protectedHeader = { ...this._protectedHeader, aud: this._payload.aud };
|
|
}
|
|
enc.setProtectedHeader(this._protectedHeader);
|
|
if (this._iv) {
|
|
enc.setInitializationVector(this._iv);
|
|
}
|
|
if (this._cek) {
|
|
enc.setContentEncryptionKey(this._cek);
|
|
}
|
|
if (this._keyManagementParameters) {
|
|
enc.setKeyManagementParameters(this._keyManagementParameters);
|
|
}
|
|
return enc.encrypt(key, options);
|
|
}
|
|
};
|
|
|
|
// dist/browser/jwk/thumbprint.js
|
|
var check = (value, description) => {
|
|
if (typeof value !== "string" || !value) {
|
|
throw new JWKInvalid(`${description} missing or invalid`);
|
|
}
|
|
};
|
|
async function calculateJwkThumbprint(jwk, digestAlgorithm = "sha256") {
|
|
if (!isObject(jwk)) {
|
|
throw new TypeError("JWK must be an object");
|
|
}
|
|
let components;
|
|
switch (jwk.kty) {
|
|
case "EC":
|
|
check(jwk.crv, '"crv" (Curve) Parameter');
|
|
check(jwk.x, '"x" (X Coordinate) Parameter');
|
|
check(jwk.y, '"y" (Y Coordinate) Parameter');
|
|
components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y };
|
|
break;
|
|
case "OKP":
|
|
check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter');
|
|
check(jwk.x, '"x" (Public Key) Parameter');
|
|
components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x };
|
|
break;
|
|
case "RSA":
|
|
check(jwk.e, '"e" (Exponent) Parameter');
|
|
check(jwk.n, '"n" (Modulus) Parameter');
|
|
components = { e: jwk.e, kty: jwk.kty, n: jwk.n };
|
|
break;
|
|
case "oct":
|
|
check(jwk.k, '"k" (Key Value) Parameter');
|
|
components = { k: jwk.k, kty: jwk.kty };
|
|
break;
|
|
default:
|
|
throw new JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported');
|
|
}
|
|
const data = encoder.encode(JSON.stringify(components));
|
|
return encode(await digest_default(digestAlgorithm, data));
|
|
}
|
|
|
|
// dist/browser/jwk/embedded.js
|
|
async function EmbeddedJWK(protectedHeader, token) {
|
|
const joseHeader = {
|
|
...protectedHeader,
|
|
...token.header
|
|
};
|
|
if (!isObject(joseHeader.jwk)) {
|
|
throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object');
|
|
}
|
|
const key = await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true);
|
|
if (key instanceof Uint8Array || key.type !== "public") {
|
|
throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key');
|
|
}
|
|
return key;
|
|
}
|
|
|
|
// dist/browser/runtime/fetch_jwks.js
|
|
var fetchJwks = async (url, timeout) => {
|
|
let controller;
|
|
let id;
|
|
let timedOut = false;
|
|
if (typeof AbortController === "function") {
|
|
controller = new AbortController();
|
|
id = setTimeout(() => {
|
|
timedOut = true;
|
|
controller.abort();
|
|
}, timeout);
|
|
}
|
|
const response = await fetch(url.href, {
|
|
signal: controller ? controller.signal : void 0,
|
|
redirect: "manual",
|
|
method: "GET",
|
|
...!isCloudflareWorkers() ? {
|
|
referrerPolicy: "no-referrer",
|
|
credentials: "omit",
|
|
mode: "cors"
|
|
} : void 0
|
|
}).catch((err) => {
|
|
if (timedOut)
|
|
throw new JWKSTimeout();
|
|
throw err;
|
|
});
|
|
if (id !== void 0)
|
|
clearTimeout(id);
|
|
if (response.status !== 200) {
|
|
throw new JOSEError("Expected 200 OK from the JSON Web Key Set HTTP response");
|
|
}
|
|
try {
|
|
return await response.json();
|
|
} catch (_a) {
|
|
throw new JOSEError("Failed to parse the JSON Web Key Set HTTP response as JSON");
|
|
}
|
|
};
|
|
var fetch_jwks_default = fetchJwks;
|
|
|
|
// dist/browser/jwks/remote.js
|
|
function getKtyFromAlg(alg) {
|
|
switch (typeof alg === "string" && alg.substr(0, 2)) {
|
|
case "RS":
|
|
case "PS":
|
|
return "RSA";
|
|
case "ES":
|
|
return "EC";
|
|
case "Ed":
|
|
return "OKP";
|
|
default:
|
|
throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set');
|
|
}
|
|
}
|
|
function isJWKLike(key) {
|
|
return isObject(key);
|
|
}
|
|
var RemoteJWKSet = class {
|
|
constructor(url, options) {
|
|
this._cached = new WeakMap();
|
|
if (!(url instanceof URL)) {
|
|
throw new TypeError("url must be an instance of URL");
|
|
}
|
|
this._url = new URL(url.href);
|
|
this._options = { agent: options === null || options === void 0 ? void 0 : options.agent };
|
|
this._timeoutDuration = typeof (options === null || options === void 0 ? void 0 : options.timeoutDuration) === "number" ? options === null || options === void 0 ? void 0 : options.timeoutDuration : 5e3;
|
|
this._cooldownDuration = typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === "number" ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 3e4;
|
|
}
|
|
coolingDown() {
|
|
if (!this._cooldownStarted) {
|
|
return false;
|
|
}
|
|
return Date.now() < this._cooldownStarted + this._cooldownDuration;
|
|
}
|
|
async getKey(protectedHeader) {
|
|
if (!this._jwks) {
|
|
await this.reload();
|
|
}
|
|
const candidates = this._jwks.keys.filter((jwk2) => {
|
|
let candidate = jwk2.kty === getKtyFromAlg(protectedHeader.alg);
|
|
if (candidate && typeof protectedHeader.kid === "string") {
|
|
candidate = protectedHeader.kid === jwk2.kid;
|
|
}
|
|
if (candidate && typeof jwk2.alg === "string") {
|
|
candidate = protectedHeader.alg === jwk2.alg;
|
|
}
|
|
if (candidate && typeof jwk2.use === "string") {
|
|
candidate = jwk2.use === "sig";
|
|
}
|
|
if (candidate && Array.isArray(jwk2.key_ops)) {
|
|
candidate = jwk2.key_ops.includes("verify");
|
|
}
|
|
if (candidate && protectedHeader.alg === "EdDSA") {
|
|
candidate = jwk2.crv === "Ed25519" || jwk2.crv === "Ed448";
|
|
}
|
|
if (candidate) {
|
|
switch (protectedHeader.alg) {
|
|
case "ES256":
|
|
candidate = jwk2.crv === "P-256";
|
|
break;
|
|
case "ES256K":
|
|
candidate = jwk2.crv === "secp256k1";
|
|
break;
|
|
case "ES384":
|
|
candidate = jwk2.crv === "P-384";
|
|
break;
|
|
case "ES512":
|
|
candidate = jwk2.crv === "P-521";
|
|
break;
|
|
default:
|
|
}
|
|
}
|
|
return candidate;
|
|
});
|
|
const { 0: jwk, length } = candidates;
|
|
if (length === 0) {
|
|
if (this.coolingDown() === false) {
|
|
await this.reload();
|
|
return this.getKey(protectedHeader);
|
|
}
|
|
throw new JWKSNoMatchingKey();
|
|
} else if (length !== 1) {
|
|
throw new JWKSMultipleMatchingKeys();
|
|
}
|
|
const cached = this._cached.get(jwk) || this._cached.set(jwk, {}).get(jwk);
|
|
if (cached[protectedHeader.alg] === void 0) {
|
|
const keyObject = await importJWK({ ...jwk, ext: true }, protectedHeader.alg);
|
|
if (keyObject instanceof Uint8Array || keyObject.type !== "public") {
|
|
throw new JWKSInvalid("JSON Web Key Set members must be public keys");
|
|
}
|
|
cached[protectedHeader.alg] = keyObject;
|
|
}
|
|
return cached[protectedHeader.alg];
|
|
}
|
|
async reload() {
|
|
if (!this._pendingFetch) {
|
|
this._pendingFetch = fetch_jwks_default(this._url, this._timeoutDuration, this._options).then((json) => {
|
|
if (typeof json !== "object" || !json || !Array.isArray(json.keys) || !json.keys.every(isJWKLike)) {
|
|
throw new JWKSInvalid("JSON Web Key Set malformed");
|
|
}
|
|
this._jwks = { keys: json.keys };
|
|
this._cooldownStarted = Date.now();
|
|
this._pendingFetch = void 0;
|
|
}).catch((err) => {
|
|
this._pendingFetch = void 0;
|
|
throw err;
|
|
});
|
|
}
|
|
await this._pendingFetch;
|
|
}
|
|
};
|
|
function createRemoteJWKSet(url, options) {
|
|
return RemoteJWKSet.prototype.getKey.bind(new RemoteJWKSet(url, options));
|
|
}
|
|
|
|
// dist/browser/jwt/unsecured.js
|
|
var UnsecuredJWT = class extends ProduceJWT {
|
|
encode() {
|
|
const header = encode(JSON.stringify({ alg: "none" }));
|
|
const payload = encode(JSON.stringify(this._payload));
|
|
return `${header}.${payload}.`;
|
|
}
|
|
static decode(jwt, options) {
|
|
if (typeof jwt !== "string") {
|
|
throw new JWTInvalid("Unsecured JWT must be a string");
|
|
}
|
|
const { 0: encodedHeader, 1: encodedPayload, 2: signature, length } = jwt.split(".");
|
|
if (length !== 3 || signature !== "") {
|
|
throw new JWTInvalid("Invalid Unsecured JWT");
|
|
}
|
|
let header;
|
|
try {
|
|
header = JSON.parse(decoder.decode(decode(encodedHeader)));
|
|
if (header.alg !== "none")
|
|
throw new Error();
|
|
} catch (_a) {
|
|
throw new JWTInvalid("Invalid Unsecured JWT");
|
|
}
|
|
const payload = jwt_claims_set_default(header, decode(encodedPayload), options);
|
|
return { payload, header };
|
|
}
|
|
};
|
|
|
|
// dist/browser/util/base64url.js
|
|
var base64url_exports = {};
|
|
__export(base64url_exports, {
|
|
decode: () => decode2,
|
|
encode: () => encode2
|
|
});
|
|
var encode2 = encode;
|
|
var decode2 = decode;
|
|
|
|
// dist/browser/util/decode_protected_header.js
|
|
function decodeProtectedHeader(token) {
|
|
let protectedB64u;
|
|
if (typeof token === "string") {
|
|
const parts = token.split(".");
|
|
if (parts.length === 3 || parts.length === 5) {
|
|
;
|
|
[protectedB64u] = parts;
|
|
}
|
|
} else if (typeof token === "object" && token) {
|
|
if ("protected" in token) {
|
|
protectedB64u = token.protected;
|
|
} else {
|
|
throw new TypeError("Token does not contain a Protected Header");
|
|
}
|
|
}
|
|
try {
|
|
if (typeof protectedB64u !== "string" || !protectedB64u) {
|
|
throw new Error();
|
|
}
|
|
const result = JSON.parse(decoder.decode(decode2(protectedB64u)));
|
|
if (!isObject(result)) {
|
|
throw new Error();
|
|
}
|
|
return result;
|
|
} catch (_a) {
|
|
throw new TypeError("Invalid Token or Protected Header formatting");
|
|
}
|
|
}
|
|
|
|
// dist/browser/runtime/generate.js
|
|
async function generateSecret(alg, options) {
|
|
var _a;
|
|
let length;
|
|
let algorithm;
|
|
let keyUsages;
|
|
switch (alg) {
|
|
case "HS256":
|
|
case "HS384":
|
|
case "HS512":
|
|
length = parseInt(alg.substr(-3), 10);
|
|
algorithm = { name: "HMAC", hash: `SHA-${length}`, length };
|
|
keyUsages = ["sign", "verify"];
|
|
break;
|
|
case "A128CBC-HS256":
|
|
case "A192CBC-HS384":
|
|
case "A256CBC-HS512":
|
|
length = parseInt(alg.substr(-3), 10);
|
|
return random_default(new Uint8Array(length >> 3));
|
|
case "A128KW":
|
|
case "A192KW":
|
|
case "A256KW":
|
|
length = parseInt(alg.substring(1, 4), 10);
|
|
algorithm = { name: "AES-KW", length };
|
|
keyUsages = ["wrapKey", "unwrapKey"];
|
|
break;
|
|
case "A128GCMKW":
|
|
case "A192GCMKW":
|
|
case "A256GCMKW":
|
|
case "A128GCM":
|
|
case "A192GCM":
|
|
case "A256GCM":
|
|
length = parseInt(alg.substring(1, 4), 10);
|
|
algorithm = { name: "AES-GCM", length };
|
|
keyUsages = ["encrypt", "decrypt"];
|
|
break;
|
|
default:
|
|
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
|
|
}
|
|
return webcrypto_default.subtle.generateKey(algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages);
|
|
}
|
|
function getModulusLengthOption(options) {
|
|
var _a;
|
|
const modulusLength = (_a = options === null || options === void 0 ? void 0 : options.modulusLength) !== null && _a !== void 0 ? _a : 2048;
|
|
if (typeof modulusLength !== "number" || modulusLength < 2048) {
|
|
throw new JOSENotSupported("Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used");
|
|
}
|
|
return modulusLength;
|
|
}
|
|
async function generateKeyPair(alg, options) {
|
|
var _a, _b;
|
|
let algorithm;
|
|
let keyUsages;
|
|
switch (alg) {
|
|
case "PS256":
|
|
case "PS384":
|
|
case "PS512":
|
|
algorithm = {
|
|
name: "RSA-PSS",
|
|
hash: `SHA-${alg.substr(-3)}`,
|
|
publicExponent: new Uint8Array([1, 0, 1]),
|
|
modulusLength: getModulusLengthOption(options)
|
|
};
|
|
keyUsages = ["sign", "verify"];
|
|
break;
|
|
case "RS256":
|
|
case "RS384":
|
|
case "RS512":
|
|
algorithm = {
|
|
name: "RSASSA-PKCS1-v1_5",
|
|
hash: `SHA-${alg.substr(-3)}`,
|
|
publicExponent: new Uint8Array([1, 0, 1]),
|
|
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.substr(-3), 10) || 1}`,
|
|
publicExponent: new Uint8Array([1, 0, 1]),
|
|
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 ((isCloudflareWorkers() || isNodeJs()) && "EdDSA"):
|
|
switch (options === null || options === void 0 ? void 0 : options.crv) {
|
|
case void 0:
|
|
case "Ed25519":
|
|
algorithm = { name: "NODE-ED25519", namedCurve: "NODE-ED25519" };
|
|
keyUsages = ["sign", "verify"];
|
|
break;
|
|
case (isNodeJs() && "Ed448"):
|
|
algorithm = { name: "NODE-ED448", namedCurve: "NODE-ED448" };
|
|
keyUsages = ["sign", "verify"];
|
|
break;
|
|
default:
|
|
throw new JOSENotSupported("Invalid or unsupported crv option provided, supported values are Ed25519 and Ed448");
|
|
}
|
|
break;
|
|
case "ECDH-ES":
|
|
case "ECDH-ES+A128KW":
|
|
case "ECDH-ES+A192KW":
|
|
case "ECDH-ES+A256KW":
|
|
algorithm = { name: "ECDH", namedCurve: (_a = options === null || options === void 0 ? void 0 : options.crv) !== null && _a !== void 0 ? _a : "P-256" };
|
|
keyUsages = ["deriveKey", "deriveBits"];
|
|
break;
|
|
default:
|
|
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
|
|
}
|
|
return webcrypto_default.subtle.generateKey(algorithm, (_b = options === null || options === void 0 ? void 0 : options.extractable) !== null && _b !== void 0 ? _b : false, keyUsages);
|
|
}
|
|
|
|
// dist/browser/key/generate_key_pair.js
|
|
async function generateKeyPair2(alg, options) {
|
|
return generateKeyPair(alg, options);
|
|
}
|
|
|
|
// dist/browser/key/generate_secret.js
|
|
async function generateSecret2(alg, options) {
|
|
return generateSecret(alg, options);
|
|
}
|
|
export {
|
|
CompactEncrypt,
|
|
CompactSign,
|
|
EmbeddedJWK,
|
|
EncryptJWT,
|
|
FlattenedEncrypt,
|
|
FlattenedSign,
|
|
GeneralEncrypt,
|
|
GeneralSign,
|
|
SignJWT,
|
|
UnsecuredJWT,
|
|
base64url_exports as base64url,
|
|
calculateJwkThumbprint,
|
|
compactDecrypt,
|
|
compactVerify,
|
|
createRemoteJWKSet,
|
|
decodeProtectedHeader,
|
|
errors_exports as errors,
|
|
exportJWK,
|
|
exportPKCS8,
|
|
exportSPKI,
|
|
flattenedDecrypt,
|
|
flattenedVerify,
|
|
generalDecrypt,
|
|
generalVerify,
|
|
generateKeyPair2 as generateKeyPair,
|
|
generateSecret2 as generateSecret,
|
|
importJWK,
|
|
importPKCS8,
|
|
importSPKI,
|
|
importX509,
|
|
jwtDecrypt,
|
|
jwtVerify
|
|
};
|