UNPKG

@gaonengwww/jose

Version:

JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes

186 lines (180 loc) 5.74 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/lib/ecdhes.ts var ecdhes_exports = {}; __export(ecdhes_exports, { allowed: () => allowed, deriveKey: () => deriveKey }); module.exports = __toCommonJS(ecdhes_exports); // src/lib/buffer_utils.ts 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; for (const buffer of buffers) { buf.set(buffer, i); i += buffer.length; } return buf; } 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 uint32be(value) { const buf = new Uint8Array(4); writeUInt32BE(buf, value); return buf; } // src/lib/crypto_key.ts 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.slice(4), 10); } function checkUsage(key, usage) { if (usage && !key.usages.includes(usage)) { throw new TypeError( `CryptoKey does not support this operation, its usages must include ${usage}.` ); } } function checkEncCryptoKey(key, alg, usage) { switch (alg) { case "A128GCM": case "A192GCM": case "A256GCM": { if (!isAlgorithm(key.algorithm, "AES-GCM")) throw unusable("AES-GCM"); const expected = parseInt(alg.slice(1, 4), 10); const actual = key.algorithm.length; if (actual !== expected) throw unusable(expected, "algorithm.length"); break; } case "A128KW": case "A192KW": case "A256KW": { if (!isAlgorithm(key.algorithm, "AES-KW")) throw unusable("AES-KW"); const expected = parseInt(alg.slice(1, 4), 10); const actual = key.algorithm.length; if (actual !== expected) throw unusable(expected, "algorithm.length"); break; } case "ECDH": { switch (key.algorithm.name) { case "ECDH": case "X25519": break; default: throw unusable("ECDH or X25519"); } break; } case "PBES2-HS256+A128KW": case "PBES2-HS384+A192KW": case "PBES2-HS512+A256KW": if (!isAlgorithm(key.algorithm, "PBKDF2")) throw unusable("PBKDF2"); break; case "RSA-OAEP": case "RSA-OAEP-256": case "RSA-OAEP-384": case "RSA-OAEP-512": { if (!isAlgorithm(key.algorithm, "RSA-OAEP")) throw unusable("RSA-OAEP"); const expected = parseInt(alg.slice(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, usage); } // src/lib/digest.ts var digest_default = async (algorithm, data) => { const subtleDigest = `SHA-${algorithm.slice(-3)}`; return new Uint8Array(await crypto.subtle.digest(subtleDigest, data)); }; // src/lib/ecdhes.ts function lengthAndInput(input) { return concat(uint32be(input.length), input); } async function concatKdf(secret, bits, value) { const iterations = Math.ceil((bits >> 3) / 32); const res = new Uint8Array(iterations * 32); for (let iter = 0; iter < iterations; iter++) { const buf = new Uint8Array(4 + secret.length + value.length); buf.set(uint32be(iter + 1)); buf.set(secret, 4); buf.set(value, 4 + secret.length); res.set(await digest_default("sha256", buf), iter * 32); } return res.slice(0, bits >> 3); } async function deriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) { checkEncCryptoKey(publicKey, "ECDH"); checkEncCryptoKey(privateKey, "ECDH", "deriveBits"); const value = concat( lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength) ); let length; if (publicKey.algorithm.name === "X25519") { length = 256; } else { length = Math.ceil(parseInt(publicKey.algorithm.namedCurve.slice(-3), 10) / 8) << 3; } const sharedSecret = new Uint8Array( await crypto.subtle.deriveBits( { name: publicKey.algorithm.name, public: publicKey }, privateKey, length ) ); return concatKdf(sharedSecret, keyLength, value); } function allowed(key) { switch (key.algorithm.namedCurve) { case "P-256": case "P-384": case "P-521": return true; default: return key.algorithm.name === "X25519"; } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { allowed, deriveKey });