@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
JavaScript
;
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
});