UNPKG

jose

Version:

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

47 lines (46 loc) • 2.9 kB
import { encode as b64u } from "../util/base64url.js"; import { jwsAlgorithm } from "./jws_algorithms.js"; import { isDisjoint, serializeJoseHeader, validateB64, validateCrit, validateCritDuplicates, JWS_RECOGNIZED } from "./validate.js"; import { JWSInvalid } from "../util/errors.js"; import { concat, encode, encoder } from "./buffer_utils.js"; import { prepareKey, rawKey, checkModulusLength } from "./key.js"; async function createSignature(input, key, rejectUnencoded) { let [payload, protectedHeader, unprotectedHeader, crit] = input, encodedProtectedHeader = ""; if (protectedHeader !== void 0) { const normalized = serializeJoseHeader(JWSInvalid, protectedHeader); protectedHeader = normalized[0], encodedProtectedHeader = b64u(normalized[1]); } if (unprotectedHeader !== void 0 && (unprotectedHeader = serializeJoseHeader(JWSInvalid, unprotectedHeader)[0]), !protectedHeader && !unprotectedHeader) throw new JWSInvalid("either setProtectedHeader or setUnprotectedHeader must be called before #sign()"); if (!isDisjoint(protectedHeader, unprotectedHeader)) throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint"); const joseHeader = { ...protectedHeader, ...unprotectedHeader }; validateCritDuplicates(JWSInvalid, protectedHeader); const b64 = validateB64(protectedHeader, validateCrit(JWSInvalid, JWS_RECOGNIZED, crit, protectedHeader, joseHeader)); b64 || rejectUnencoded?.(); const { alg } = joseHeader; if (typeof alg != "string" || !alg) throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); const entry = jwsAlgorithm(alg); let encodedPayload = "", signingPayload = payload, signingInput; if (b64) { const encodedPayloadCache = input[4]; encodedPayloadCache ? (encodedPayload = encodedPayloadCache[0] ??= b64u(payload), signingPayload = encodedPayloadCache[1] ??= encode(encodedPayload)) : (encodedPayload = b64u(payload), signingInput = encoder.encode(`${encodedProtectedHeader}.${encodedPayload}`)); } signingInput ??= concat(encode(encodedProtectedHeader), encode("."), signingPayload); const signingKey = await rawKey(await prepareKey(entry, key, "sign"), entry.subtle, "sign"); entry.minRsaBits && checkModulusLength(entry.alg, signingKey); const jws = { signature: b64u(new Uint8Array(await crypto.subtle.sign(entry.signing, signingKey, signingInput))), payload: encodedPayload }; return protectedHeader && (jws.protected = encodedProtectedHeader), unprotectedHeader && (jws.header = unprotectedHeader), [jws, b64]; } async function createCompactSignature(payload, protectedHeader, crit, key, rejectUnencoded) { const [jws] = await createSignature([payload, protectedHeader, void 0, crit], key, rejectUnencoded); return `${jws.protected}.${jws.payload}.${jws.signature}`; } export { createCompactSignature, createSignature };