UNPKG

@vdcs/jwt

Version:
168 lines (162 loc) 5.93 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); // src/jwt.ts import { base64urlDecode, base64urlEncode, uint8ArrayToBase64Url as uint8ArrayToBase64Url2 } from "@sd-jwt/utils"; // src/utils.ts import { numberToBytesBE } from "@noble/curves/utils"; import { Base64 as Base642 } from "js-base64"; // src/key/p256.ts import { p256 } from "@noble/curves/nist"; import { bytesToHex } from "@noble/curves/abstract/utils"; import { uint8ArrayToBase64Url } from "@sd-jwt/utils"; import { Base64 } from "js-base64"; var generateKeyPair = /* @__PURE__ */ __name(() => { const privateKey = p256.utils.randomPrivateKey(); const publicKey = p256.getPublicKey(privateKey); return { privateKey, publicKey }; }, "generateKeyPair"); var privateKeyUint8ArrayToJwk = /* @__PURE__ */ __name((privateKeyBytes) => { if (privateKeyBytes.length !== 32) { throw new Error("Invalid private key length. Must be 32 bytes."); } const publicKeyBytes = p256.getPublicKey(privateKeyBytes, false); const d = uint8ArrayToBase64Url(privateKeyBytes); const x = uint8ArrayToBase64Url(publicKeyBytes.slice(1, 33)); const y = uint8ArrayToBase64Url(publicKeyBytes.slice(33, 65)); return { kty: "EC", crv: "P-256", d, x, y }; }, "privateKeyUint8ArrayToJwk"); var privateKeyJwkToUint8Array = /* @__PURE__ */ __name((jwk) => { if (!jwk.d) { throw new Error('Invalid private JWK: missing "d" parameter.'); } const privateKeyBytes = Base64.toUint8Array(jwk.d); if (privateKeyBytes.length !== 32) { throw new Error('Invalid "d" parameter length. Must decode to 32 bytes.'); } return privateKeyBytes; }, "privateKeyJwkToUint8Array"); var publicKeyUint8ArrayToJwk = /* @__PURE__ */ __name((publicKeyBytes) => { if (publicKeyBytes.length !== 33 && publicKeyBytes.length !== 65) { throw new Error("Invalid public key length. Must be 33 (compressed) or 65 (uncompressed) bytes."); } const point = p256.Point.fromHex(bytesToHex(publicKeyBytes)); const x = uint8ArrayToBase64Url(bigIntTo32Bytes(point.x)); const y = uint8ArrayToBase64Url(bigIntTo32Bytes(point.y)); return { kty: "EC", crv: "P-256", x, y }; }, "publicKeyUint8ArrayToJwk"); var publicKeyJwkToUint8Array = /* @__PURE__ */ __name((jwk, compressed = false) => { const xBytes = Base64.toUint8Array(jwk.x); const yBytes = Base64.toUint8Array(jwk.y); const uncompressedPublicKey = new Uint8Array(65); uncompressedPublicKey[0] = 4; uncompressedPublicKey.set(xBytes, 1); uncompressedPublicKey.set(yBytes, 33); const point = p256.Point.fromHex(bytesToHex(uncompressedPublicKey)); return point.toRawBytes(compressed); }, "publicKeyJwkToUint8Array"); var sign = /* @__PURE__ */ __name((data, privateKey) => { const signature = p256.sign(data, privateKey); return signature.toCompactRawBytes(); }, "sign"); var verify = /* @__PURE__ */ __name((msgHash, signature, publicKey) => { return p256.verify(signature, msgHash, publicKey); }, "verify"); var P256 = { generateKeyPair, privateKeyUint8ArrayToJwk, privateKeyJwkToUint8Array, publicKeyUint8ArrayToJwk, publicKeyJwkToUint8Array, sign, verify }; // src/utils.ts var fromBase64Url = /* @__PURE__ */ __name((base64Url) => { return Base642.toUint8Array(base64Url); }, "fromBase64Url"); var bigIntTo32Bytes = /* @__PURE__ */ __name((num) => { const bytes = numberToBytesBE(num, 32); if (bytes.length > 32) { throw new Error("BigInt is too large for 32 bytes."); } const padded = new Uint8Array(32); padded.set(bytes, 32 - bytes.length); return padded; }, "bigIntTo32Bytes"); var normalizePrivateKey = /* @__PURE__ */ __name((privateKey) => { if (privateKey instanceof Uint8Array) { return privateKey; } if (!privateKey.d) { throw new Error('Invalid private JWK: missing "d" parameter.'); } return fromBase64Url(privateKey.d); }, "normalizePrivateKey"); var normalizePublicKey = /* @__PURE__ */ __name((publicKey) => { if (publicKey instanceof Uint8Array) { return publicKey; } if (!publicKey.x || !publicKey.y) { throw new Error('Invalid public JWK: missing "x" or "y" parameters.'); } return P256.publicKeyJwkToUint8Array(publicKey); }, "normalizePublicKey"); // src/jwt.ts import { sha256 } from "@sd-jwt/hash"; import { Base64 as Base643 } from "js-base64"; var signJWT = /* @__PURE__ */ __name((options, privateKey) => { const header = base64urlEncode(JSON.stringify(options.header)); const payload = base64urlEncode(JSON.stringify(options.payload)); const sigData = `${header}.${payload}`; const normalizedPrivateKey = normalizePrivateKey(privateKey); const signingInputBytes = sha256(sigData); const signature = P256.sign(signingInputBytes, normalizedPrivateKey); const base64UrlSignature = uint8ArrayToBase64Url2(signature); return `${sigData}.${base64UrlSignature}`; }, "signJWT"); var decodeJWT = /* @__PURE__ */ __name((compact) => { try { const [encodedHeader, encodedPayload] = compact.split("."); const header = JSON.parse(base64urlDecode(encodedHeader)); const payload = JSON.parse(base64urlDecode(encodedPayload)); return { header, payload }; } catch (e) { throw new Error("Invalid JWT"); } }, "decodeJWT"); var verifyJWT = /* @__PURE__ */ __name((compact, publicKey) => { const [encodedHeader, encodedPayload, encodedSignature] = compact.split("."); const normalizedPublicKey = normalizePublicKey(publicKey); const signingInputBytes = sha256(`${encodedHeader}.${encodedPayload}`); const result = P256.verify(signingInputBytes, Base643.toUint8Array(encodedSignature), normalizedPublicKey); if (!result) { throw new Error("Invalid signature"); } return decodeJWT(compact); }, "verifyJWT"); export { P256, bigIntTo32Bytes, decodeJWT, normalizePrivateKey, normalizePublicKey, signJWT, verifyJWT };