[{"data":1,"prerenderedAt":1621},["ShallowReactive",2],{"navigation":3,"-jwt-jws-multi-signature":167,"-jwt-jws-multi-signature-surround":1618},[4,22,78,106,141,148],{"title":5,"path":6,"stem":7,"children":8},"Introduction","\u002Fgetting-started","0.Getting-Started\u002F0.index",[9,10,14,18],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13},"Installation","\u002Fgetting-started\u002Finstallation","0.Getting-Started\u002F1.installation",{"title":15,"path":16,"stem":17},"Quickstart","\u002Fgetting-started\u002Fquickstart","0.Getting-Started\u002F2.quickstart",{"title":19,"path":20,"stem":21},"Core concepts","\u002Fgetting-started\u002Fcore-concepts","0.Getting-Started\u002F3.core-concepts",{"title":23,"path":24,"stem":25,"children":26,"icon":28},"JWT","\u002Fjwt","1.JWT\u002F0.index",[27,29,52],{"title":23,"path":24,"stem":25,"icon":28},"i-carbon-certificate",{"title":30,"path":31,"stem":32,"children":33,"icon":35},"JWS","\u002Fjwt\u002Fjws","1.JWT\u002F1.JWS\u002F0.index",[34,36,40,44,48],{"title":30,"path":31,"stem":32,"icon":35},"i-carbon-document-signed",{"title":37,"path":38,"stem":39},"Signing","\u002Fjwt\u002Fjws\u002Fsigning","1.JWT\u002F1.JWS\u002F1.signing",{"title":41,"path":42,"stem":43},"Verifying","\u002Fjwt\u002Fjws\u002Fverifying","1.JWT\u002F1.JWS\u002F2.verifying",{"title":45,"path":46,"stem":47},"Multi-signature","\u002Fjwt\u002Fjws\u002Fmulti-signature","1.JWT\u002F1.JWS\u002F3.multi-signature",{"title":49,"path":50,"stem":51},"Algorithms","\u002Fjwt\u002Fjws\u002Falgorithms","1.JWT\u002F1.JWS\u002F4.algorithms",{"title":53,"path":54,"stem":55,"children":56,"icon":58},"JWE","\u002Fjwt\u002Fjwe","1.JWT\u002F2.JWE\u002F0.index",[57,59,63,67,71,75],{"title":53,"path":54,"stem":55,"icon":58},"i-carbon-locked",{"title":60,"path":61,"stem":62},"Encrypting","\u002Fjwt\u002Fjwe\u002Fencrypting","1.JWT\u002F2.JWE\u002F1.encrypting",{"title":64,"path":65,"stem":66},"Decrypting","\u002Fjwt\u002Fjwe\u002Fdecrypting","1.JWT\u002F2.JWE\u002F2.decrypting",{"title":68,"path":69,"stem":70},"Multi-recipient","\u002Fjwt\u002Fjwe\u002Fmulti-recipient","1.JWT\u002F2.JWE\u002F3.multi-recipient",{"title":72,"path":73,"stem":74},"ECDH-ES and end-to-end encryption","\u002Fjwt\u002Fjwe\u002Fecdh-es","1.JWT\u002F2.JWE\u002F4.ecdh-es",{"title":49,"path":76,"stem":77},"\u002Fjwt\u002Fjwe\u002Falgorithms","1.JWT\u002F2.JWE\u002F5.algorithms",{"title":79,"path":80,"stem":81,"children":82,"icon":84},"Examples","\u002Fexamples","10.Examples\u002F0.index",[83,85,90,94,98,102],{"title":79,"path":80,"stem":81,"icon":84},"i-carbon-code-reference",{"title":86,"path":87,"stem":88,"icon":89},"Authentication basics","\u002Fexamples\u002Fauthentication-basics","10.Examples\u002F1.authentication-basics","i-lucide-code",{"title":91,"path":92,"stem":93,"icon":89},"Consuming a JWKS endpoint","\u002Fexamples\u002Fjwks-endpoint","10.Examples\u002F2.jwks-endpoint",{"title":95,"path":96,"stem":97,"icon":89},"Refresh token pattern","\u002Fexamples\u002Frefresh-token-pattern","10.Examples\u002F3.refresh-token-pattern",{"title":99,"path":100,"stem":101,"icon":89},"End-to-end encryption","\u002Fexamples\u002Fend-to-end-encryption","10.Examples\u002F4.end-to-end-encryption",{"title":103,"path":104,"stem":105,"icon":89},"Signed receipts","\u002Fexamples\u002Fsigned-receipts","10.Examples\u002F5.signed-receipts",{"title":107,"path":108,"stem":109,"children":110,"icon":112},"JWK","\u002Fjwk","2.JWK\u002F0.index",[111,113,117,121,125,129,133,137],{"title":107,"path":108,"stem":109,"icon":112},"i-carbon-two-factor-authentication",{"title":114,"path":115,"stem":116},"Generating keys","\u002Fjwk\u002Fgenerating","2.JWK\u002F1.generating",{"title":118,"path":119,"stem":120},"Importing and exporting","\u002Fjwk\u002Fimport-export","2.JWK\u002F2.import-export",{"title":122,"path":123,"stem":124},"PEM conversion","\u002Fjwk\u002Fpem","2.JWK\u002F3.pem",{"title":126,"path":127,"stem":128},"Key wrapping","\u002Fjwk\u002Fwrapping","2.JWK\u002F4.wrapping",{"title":130,"path":131,"stem":132},"Password derivation","\u002Fjwk\u002Fpassword-derivation","2.JWK\u002F5.password-derivation",{"title":134,"path":135,"stem":136},"JWK Sets","\u002Fjwk\u002Fjwk-sets","2.JWK\u002F6.jwk-sets",{"title":138,"path":139,"stem":140},"JWK cache","\u002Fjwk\u002Fcache","2.JWK\u002F7.cache",{"title":142,"path":143,"stem":144,"children":145,"icon":147},"Utilities","\u002Futilities","3.Utilities\u002F0.index",[146],{"title":142,"path":143,"stem":144,"icon":147},"i-carbon-tool-box",{"title":149,"path":150,"stem":151,"children":152,"icon":154},"Adapters","\u002Fadapters","99.Adapters\u002F0.index",[153,155,159,163],{"title":149,"path":150,"stem":151,"icon":154},"i-carbon-plug",{"title":156,"path":157,"stem":158},"H3 sessions","\u002Fadapters\u002Fh3-sessions","99.Adapters\u002F1.h3-sessions",{"title":160,"path":161,"stem":162},"Lifecycle hooks","\u002Fadapters\u002Fhooks","99.Adapters\u002F2.hooks",{"title":164,"path":165,"stem":166},"Lower-level functions","\u002Fadapters\u002Flower-level","99.Adapters\u002F3.lower-level",{"id":168,"title":45,"body":169,"description":211,"extension":1613,"meta":1614,"navigation":1615,"path":46,"seo":1616,"stem":47,"__hash__":1617},"content\u002F1.JWT\u002F1.JWS\u002F3.multi-signature.md",{"type":170,"value":171,"toc":1597},"minimark",[172,181,205,332,342,345,384,395,402,556,573,578,637,641,680,702,708,715,777,786,790,812,816,841,862,870,876,882,1261,1264,1363,1372,1393,1397,1417,1421,1464,1468,1477,1536,1542,1549,1553,1556,1586,1593],[173,174,175,176,180],"p",{},"Sometimes one signature isn't enough. Notarized documents, quorum-approved operations, multi-algorithm key-rotation overlap, cross-organization attestations — they all need ",[177,178,179],"strong",{},"multiple signatures on the same payload",".",[173,182,183,184,188,189,192,193,200,201,204],{},"The compact ",[185,186,187],"code",{},"sign()","\u002F",[185,190,191],{},"verify()"," path only covers one signer. For the rest, ",[194,195,199],"a",{"href":196,"rel":197},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc7515#section-7.2",[198],"nofollow","RFC 7515 §7.2"," defines the ",[177,202,203],{},"General JSON Serialization",":",[206,207,212],"pre",{"className":208,"code":209,"language":210,"meta":211,"style":211},"language-json shiki shiki-themes github-light github-dark github-dark","{\n  \"payload\": \"\u003Cbase64url of the shared payload>\",\n  \"signatures\": [\n    { \"protected\": \"\u003Cbase64url>\", \"header\": {...}, \"signature\": \"...\" },\n    { \"protected\": \"\u003Cbase64url>\", \"header\": {...}, \"signature\": \"...\" }\n  ]\n}\n","json","",[185,213,214,223,240,249,290,320,326],{"__ignoreMap":211},[215,216,219],"span",{"class":217,"line":218},"line",1,[215,220,222],{"class":221},"slsVL","{\n",[215,224,226,230,233,237],{"class":217,"line":225},2,[215,227,229],{"class":228},"suiK_","  \"payload\"",[215,231,232],{"class":221},": ",[215,234,236],{"class":235},"sfrk1","\"\u003Cbase64url of the shared payload>\"",[215,238,239],{"class":221},",\n",[215,241,243,246],{"class":217,"line":242},3,[215,244,245],{"class":228},"  \"signatures\"",[215,247,248],{"class":221},": [\n",[215,250,252,255,258,260,263,266,269,272,276,279,282,284,287],{"class":217,"line":251},4,[215,253,254],{"class":221},"    { ",[215,256,257],{"class":228},"\"protected\"",[215,259,232],{"class":221},[215,261,262],{"class":235},"\"\u003Cbase64url>\"",[215,264,265],{"class":221},", ",[215,267,268],{"class":228},"\"header\"",[215,270,271],{"class":221},": {",[215,273,275],{"class":274},"sVAnh","...",[215,277,278],{"class":221},"}, ",[215,280,281],{"class":228},"\"signature\"",[215,283,232],{"class":221},[215,285,286],{"class":235},"\"...\"",[215,288,289],{"class":221}," },\n",[215,291,293,295,297,299,301,303,305,307,309,311,313,315,317],{"class":217,"line":292},5,[215,294,254],{"class":221},[215,296,257],{"class":228},[215,298,232],{"class":221},[215,300,262],{"class":235},[215,302,265],{"class":221},[215,304,268],{"class":228},[215,306,271],{"class":221},[215,308,275],{"class":274},[215,310,278],{"class":221},[215,312,281],{"class":228},[215,314,232],{"class":221},[215,316,286],{"class":235},[215,318,319],{"class":221}," }\n",[215,321,323],{"class":217,"line":322},6,[215,324,325],{"class":221},"  ]\n",[215,327,329],{"class":217,"line":328},7,[215,330,331],{"class":221},"}\n",[173,333,334,335,265,338,341],{},"One payload, many signatures — each signer has their own protected header (with its own ",[185,336,337],{},"alg",[185,339,340],{},"kid",", etc.).",[173,343,344],{},"unjwt exposes three functions for this:",[346,347,348,358,371],"ul",{},[349,350,351,357],"li",{},[194,352,354],{"href":353},"#signmulti",[185,355,356],{},"signMulti()"," — produce the General serialization.",[349,359,360,366,367,370],{},[194,361,363],{"href":362},"#verifymulti",[185,364,365],{},"verifyMulti()"," — return the ",[177,368,369],{},"first"," signature that verifies.",[349,372,373,379,380,383],{},[194,374,376],{"href":375},"#verifymultiall",[185,377,378],{},"verifyMultiAll()"," — return ",[177,381,382],{},"every"," signature's outcome for policy-driven decisions.",[173,385,386,387,390,391,394],{},"All three are importable from ",[185,388,389],{},"unjwt\u002Fjws"," (or ",[185,392,393],{},"unjwt",").",[396,397,399],"h2",{"id":398},"signmulti",[185,400,401],{},"signMulti",[206,403,408],{"className":404,"code":405,"filename":406,"language":407,"meta":211,"style":211},"language-ts shiki shiki-themes github-light github-dark github-dark","import { signMulti } from \"unjwt\u002Fjws\";\n\nconst jws = await signMulti(\n  { sub: \"u1\", role: \"admin\" },\n  [\n    { key: aliceRsaPrivateJwk }, \u002F\u002F alg inferred from JWK → RS256\n    { key: bobEdPrivateJwk, protectedHeader: { typ: \"vc+jwt\" } }, \u002F\u002F alg from JWK → Ed25519\n    { key: witnessHmacJwk, unprotectedHeader: { \"x-role\": \"witness\" } },\n  ],\n  { expiresIn: \"1h\" },\n);\n\n\u002F\u002F jws.payload          — base64url of JSON-serialized payload\n\u002F\u002F jws.signatures       — array of { protected, header?, signature }\n","sign-multi.ts","ts",[185,409,410,428,434,455,471,476,485,499,516,522,533,539,544,550],{"__ignoreMap":211},[215,411,412,416,419,422,425],{"class":217,"line":218},[215,413,415],{"class":414},"so5gQ","import",[215,417,418],{"class":221}," { signMulti } ",[215,420,421],{"class":414},"from",[215,423,424],{"class":235}," \"unjwt\u002Fjws\"",[215,426,427],{"class":221},";\n",[215,429,430],{"class":217,"line":225},[215,431,433],{"emptyLinePlaceholder":432},true,"\n",[215,435,436,439,442,445,448,452],{"class":217,"line":242},[215,437,438],{"class":414},"const",[215,440,441],{"class":228}," jws",[215,443,444],{"class":414}," =",[215,446,447],{"class":414}," await",[215,449,451],{"class":450},"shcOC"," signMulti",[215,453,454],{"class":221},"(\n",[215,456,457,460,463,466,469],{"class":217,"line":251},[215,458,459],{"class":221},"  { sub: ",[215,461,462],{"class":235},"\"u1\"",[215,464,465],{"class":221},", role: ",[215,467,468],{"class":235},"\"admin\"",[215,470,289],{"class":221},[215,472,473],{"class":217,"line":292},[215,474,475],{"class":221},"  [\n",[215,477,478,481],{"class":217,"line":322},[215,479,480],{"class":221},"    { key: aliceRsaPrivateJwk }, ",[215,482,484],{"class":483},"sCsY4","\u002F\u002F alg inferred from JWK → RS256\n",[215,486,487,490,493,496],{"class":217,"line":328},[215,488,489],{"class":221},"    { key: bobEdPrivateJwk, protectedHeader: { typ: ",[215,491,492],{"class":235},"\"vc+jwt\"",[215,494,495],{"class":221}," } }, ",[215,497,498],{"class":483},"\u002F\u002F alg from JWK → Ed25519\n",[215,500,502,505,508,510,513],{"class":217,"line":501},8,[215,503,504],{"class":221},"    { key: witnessHmacJwk, unprotectedHeader: { ",[215,506,507],{"class":235},"\"x-role\"",[215,509,232],{"class":221},[215,511,512],{"class":235},"\"witness\"",[215,514,515],{"class":221}," } },\n",[215,517,519],{"class":217,"line":518},9,[215,520,521],{"class":221},"  ],\n",[215,523,525,528,531],{"class":217,"line":524},10,[215,526,527],{"class":221},"  { expiresIn: ",[215,529,530],{"class":235},"\"1h\"",[215,532,289],{"class":221},[215,534,536],{"class":217,"line":535},11,[215,537,538],{"class":221},");\n",[215,540,542],{"class":217,"line":541},12,[215,543,433],{"emptyLinePlaceholder":432},[215,545,547],{"class":217,"line":546},13,[215,548,549],{"class":483},"\u002F\u002F jws.payload          — base64url of JSON-serialized payload\n",[215,551,553],{"class":217,"line":552},14,[215,554,555],{"class":483},"\u002F\u002F jws.signatures       — array of { protected, header?, signature }\n",[173,557,558,559,562,563,265,566,265,569,572],{},"Each signer is independent: they sign ",[185,560,561],{},"BASE64URL(ownProtectedHeader).BASE64URL(payload)"," with their own key. The claims (",[185,564,565],{},"iat",[185,567,568],{},"exp",[185,570,571],{},"jti",") are computed once for the shared payload, not per signer.",[574,575,577],"h3",{"id":576},"per-signer-fields","Per-signer fields",[579,580,581,594],"table",{},[582,583,584],"thead",{},[585,586,587,591],"tr",{},[588,589,590],"th",{},"Field",[588,592,593],{},"Role",[595,596,597,614,627],"tbody",{},[585,598,599,605],{},[600,601,602],"td",{},[185,603,604],{},"key",[600,606,607,608],{},"The signing key for this signer. ",[177,609,610,613],{},[185,611,612],{},"key.alg"," is required.",[585,615,616,621],{},[600,617,618],{},[185,619,620],{},"protectedHeader",[600,622,623,624,626],{},"Fields that are signed. Cannot set ",[185,625,337],{}," here (comes from key).",[585,628,629,634],{},[600,630,631],{},[185,632,633],{},"unprotectedHeader",[600,635,636],{},"Fields not covered by the signature — metadata only.",[574,638,640],{"id":639},"errors-you-might-see","Errors you might see",[346,642,643,658,674],{},[349,644,645,648,649,651,652,654,655,180],{},[185,646,647],{},"ERR_JWS_SIGNER_ALG_INFERENCE"," — a signer's JWK has no ",[185,650,337],{}," field. Pass a JWK with ",[185,653,337],{}," or generate one with ",[185,656,657],{},"generateJWK()",[349,659,660,663,664,667,668,673],{},[185,661,662],{},"ERR_JWS_B64_INCONSISTENT"," — signers disagree on the ",[185,665,666],{},"b64"," header value. ",[194,669,672],{"href":670,"rel":671},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc7797#section-3",[198],"RFC 7797 §3"," mandates consistency.",[349,675,676,679],{},[185,677,678],{},"ERR_JWS_HEADER_PARAMS_NOT_DISJOINT"," — a parameter name appears in both the protected and unprotected header of the same signer.",[681,682,683],"note",{},[173,684,685,687,688,691,692,695,696,180],{},[185,686,401],{}," always emits the ",[177,689,690],{},"General"," serialization, even for a single signer. If you need the shorter ",[177,693,694],{},"Flattened"," form (one signer, JSON shape), post-process with ",[194,697,699],{"href":698},"#generaltoflattenedjws",[185,700,701],{},"generalToFlattenedJWS",[396,703,705],{"id":704},"verifymulti",[185,706,707],{},"verifyMulti",[173,709,710,711,714],{},"Verify until ",[177,712,713],{},"one"," signature passes — the \"first valid signature wins\" semantics:",[206,716,719],{"className":404,"code":717,"filename":718,"language":407,"meta":211,"style":211},"import { verifyMulti } from \"unjwt\u002Fjws\";\n\nconst { payload, signerIndex, signerHeader } = await verifyMulti(jws, alicePublicJwk);\n\u002F\u002F signerIndex: number — which entry of jws.signatures verified\n","verify-multi-first.ts",[185,720,721,734,738,772],{"__ignoreMap":211},[215,722,723,725,728,730,732],{"class":217,"line":218},[215,724,415],{"class":414},[215,726,727],{"class":221}," { verifyMulti } ",[215,729,421],{"class":414},[215,731,424],{"class":235},[215,733,427],{"class":221},[215,735,736],{"class":217,"line":225},[215,737,433],{"emptyLinePlaceholder":432},[215,739,740,742,745,748,750,753,755,758,761,764,766,769],{"class":217,"line":242},[215,741,438],{"class":414},[215,743,744],{"class":221}," { ",[215,746,747],{"class":228},"payload",[215,749,265],{"class":221},[215,751,752],{"class":228},"signerIndex",[215,754,265],{"class":221},[215,756,757],{"class":228},"signerHeader",[215,759,760],{"class":221}," } ",[215,762,763],{"class":414},"=",[215,765,447],{"class":414},[215,767,768],{"class":450}," verifyMulti",[215,770,771],{"class":221},"(jws, alicePublicJwk);\n",[215,773,774],{"class":217,"line":251},[215,775,776],{"class":483},"\u002F\u002F signerIndex: number — which entry of jws.signatures verified\n",[173,778,779,781,782,785],{},[185,780,365],{}," accepts ",[177,783,784],{},"parsed General or Flattened"," serializations (not raw strings — parse the JSON yourself). It's the right fit when you don't care which key signed, only that some trusted key did.",[574,787,789],{"id":788},"key-input-shapes","Key input shapes",[173,791,792,793,797,798,800,801,800,804,807,808,811],{},"Same as ",[194,794,795],{"href":42},[185,796,191],{},": a ",[185,799,107],{},", a ",[185,802,803],{},"JWKSet",[185,805,806],{},"CryptoKey",", raw bytes, or a ",[185,809,810],{},"JWKLookupFunction",". When you pass a set or a lookup, unjwt retries per signature until one verifies.",[574,813,815],{"id":814},"strict-signer-matching","Strict signer matching",[173,817,818,819,822,823,825,826,188,829,832,833,836,837,840],{},"With ",[185,820,821],{},"strictSignerMatch: true",", a signature is only attempted if its header unambiguously matches the provided key (by ",[185,824,340],{},", then by ",[185,827,828],{},"kty",[185,830,831],{},"crv","\u002Flength). Mismatched signatures are ",[177,834,835],{},"skipped"," rather than attempted — if none match, ",[185,838,839],{},"ERR_JWS_NO_MATCHING_SIGNER"," is thrown.",[206,842,844],{"className":404,"code":843,"language":407,"meta":211,"style":211},"await verifyMulti(jws, alicePublicJwk, { strictSignerMatch: true });\n",[185,845,846],{"__ignoreMap":211},[215,847,848,851,853,856,859],{"class":217,"line":218},[215,849,850],{"class":414},"await",[215,852,768],{"class":450},[215,854,855],{"class":221},"(jws, alicePublicJwk, { strictSignerMatch: ",[215,857,858],{"class":228},"true",[215,860,861],{"class":221}," });\n",[173,863,864,865,869],{},"Useful for audit paths where you want \"is ",[866,867,868],"em",{},"this specific key's"," signature valid?\" rather than \"is any signature valid?\".",[396,871,873],{"id":872},"verifymultiall",[185,874,875],{},"verifyMultiAll",[173,877,878,879,881],{},"Return the status of ",[177,880,382],{}," signature independently — the library never throws on a per-signature failure, so the caller can apply any policy:",[206,883,886],{"className":404,"code":884,"filename":885,"language":407,"meta":211,"style":211},"import { verifyMultiAll } from \"unjwt\u002Fjws\";\n\nconst outcomes = await verifyMultiAll(jws, async (header) => myKeyStore.get(header.kid!));\n\n\u002F\u002F All-must-verify policy\nif (!outcomes.every((o) => o.verified)) {\n  throw new Error(\"not all signatures valid\");\n}\n\n\u002F\u002F Quorum policy: M of N distinct signers\nconst verifiedKids = new Set(outcomes.filter((o) => o.verified).map((o) => o.protectedHeader.kid));\nif (verifiedKids.size \u003C 2) throw new Error(\"quorum not met\");\n\n\u002F\u002F Specific-signer policy\nconst signedBy = new Set(outcomes.filter((o) => o.verified).map((o) => o.protectedHeader.kid));\nif (!signedBy.has(\"alice\") || !signedBy.has(\"notary\")) {\n  throw new Error(\"missing required signers\");\n}\n\n\u002F\u002F Audit log — record every outcome regardless of policy\nfor (const o of outcomes) {\n  log(o.signerIndex, o.verified ? \"ok\" : o.error.code);\n}\n","verify-multi-all.ts",[185,887,888,901,905,953,957,962,989,1008,1012,1016,1021,1066,1095,1099,1104,1144,1184,1200,1205,1210,1216,1235,1256],{"__ignoreMap":211},[215,889,890,892,895,897,899],{"class":217,"line":218},[215,891,415],{"class":414},[215,893,894],{"class":221}," { verifyMultiAll } ",[215,896,421],{"class":414},[215,898,424],{"class":235},[215,900,427],{"class":221},[215,902,903],{"class":217,"line":225},[215,904,433],{"emptyLinePlaceholder":432},[215,906,907,909,912,914,916,919,922,925,928,932,935,938,941,944,947,950],{"class":217,"line":242},[215,908,438],{"class":414},[215,910,911],{"class":228}," outcomes",[215,913,444],{"class":414},[215,915,447],{"class":414},[215,917,918],{"class":450}," verifyMultiAll",[215,920,921],{"class":221},"(jws, ",[215,923,924],{"class":414},"async",[215,926,927],{"class":221}," (",[215,929,931],{"class":930},"sQHwn","header",[215,933,934],{"class":221},") ",[215,936,937],{"class":414},"=>",[215,939,940],{"class":221}," myKeyStore.",[215,942,943],{"class":450},"get",[215,945,946],{"class":221},"(header.kid",[215,948,949],{"class":414},"!",[215,951,952],{"class":221},"));\n",[215,954,955],{"class":217,"line":251},[215,956,433],{"emptyLinePlaceholder":432},[215,958,959],{"class":217,"line":292},[215,960,961],{"class":483},"\u002F\u002F All-must-verify policy\n",[215,963,964,967,969,971,974,976,979,982,984,986],{"class":217,"line":322},[215,965,966],{"class":414},"if",[215,968,927],{"class":221},[215,970,949],{"class":414},[215,972,973],{"class":221},"outcomes.",[215,975,382],{"class":450},[215,977,978],{"class":221},"((",[215,980,981],{"class":930},"o",[215,983,934],{"class":221},[215,985,937],{"class":414},[215,987,988],{"class":221}," o.verified)) {\n",[215,990,991,994,997,1000,1003,1006],{"class":217,"line":328},[215,992,993],{"class":414},"  throw",[215,995,996],{"class":414}," new",[215,998,999],{"class":450}," Error",[215,1001,1002],{"class":221},"(",[215,1004,1005],{"class":235},"\"not all signatures valid\"",[215,1007,538],{"class":221},[215,1009,1010],{"class":217,"line":501},[215,1011,331],{"class":221},[215,1013,1014],{"class":217,"line":518},[215,1015,433],{"emptyLinePlaceholder":432},[215,1017,1018],{"class":217,"line":524},[215,1019,1020],{"class":483},"\u002F\u002F Quorum policy: M of N distinct signers\n",[215,1022,1023,1025,1028,1030,1032,1035,1038,1041,1043,1045,1047,1049,1052,1055,1057,1059,1061,1063],{"class":217,"line":535},[215,1024,438],{"class":414},[215,1026,1027],{"class":228}," verifiedKids",[215,1029,444],{"class":414},[215,1031,996],{"class":414},[215,1033,1034],{"class":450}," Set",[215,1036,1037],{"class":221},"(outcomes.",[215,1039,1040],{"class":450},"filter",[215,1042,978],{"class":221},[215,1044,981],{"class":930},[215,1046,934],{"class":221},[215,1048,937],{"class":414},[215,1050,1051],{"class":221}," o.verified).",[215,1053,1054],{"class":450},"map",[215,1056,978],{"class":221},[215,1058,981],{"class":930},[215,1060,934],{"class":221},[215,1062,937],{"class":414},[215,1064,1065],{"class":221}," o.protectedHeader.kid));\n",[215,1067,1068,1070,1073,1076,1079,1081,1084,1086,1088,1090,1093],{"class":217,"line":541},[215,1069,966],{"class":414},[215,1071,1072],{"class":221}," (verifiedKids.size ",[215,1074,1075],{"class":414},"\u003C",[215,1077,1078],{"class":228}," 2",[215,1080,934],{"class":221},[215,1082,1083],{"class":414},"throw",[215,1085,996],{"class":414},[215,1087,999],{"class":450},[215,1089,1002],{"class":221},[215,1091,1092],{"class":235},"\"quorum not met\"",[215,1094,538],{"class":221},[215,1096,1097],{"class":217,"line":546},[215,1098,433],{"emptyLinePlaceholder":432},[215,1100,1101],{"class":217,"line":552},[215,1102,1103],{"class":483},"\u002F\u002F Specific-signer policy\n",[215,1105,1107,1109,1112,1114,1116,1118,1120,1122,1124,1126,1128,1130,1132,1134,1136,1138,1140,1142],{"class":217,"line":1106},15,[215,1108,438],{"class":414},[215,1110,1111],{"class":228}," signedBy",[215,1113,444],{"class":414},[215,1115,996],{"class":414},[215,1117,1034],{"class":450},[215,1119,1037],{"class":221},[215,1121,1040],{"class":450},[215,1123,978],{"class":221},[215,1125,981],{"class":930},[215,1127,934],{"class":221},[215,1129,937],{"class":414},[215,1131,1051],{"class":221},[215,1133,1054],{"class":450},[215,1135,978],{"class":221},[215,1137,981],{"class":930},[215,1139,934],{"class":221},[215,1141,937],{"class":414},[215,1143,1065],{"class":221},[215,1145,1147,1149,1151,1153,1156,1159,1161,1164,1166,1169,1172,1174,1176,1178,1181],{"class":217,"line":1146},16,[215,1148,966],{"class":414},[215,1150,927],{"class":221},[215,1152,949],{"class":414},[215,1154,1155],{"class":221},"signedBy.",[215,1157,1158],{"class":450},"has",[215,1160,1002],{"class":221},[215,1162,1163],{"class":235},"\"alice\"",[215,1165,934],{"class":221},[215,1167,1168],{"class":414},"||",[215,1170,1171],{"class":414}," !",[215,1173,1155],{"class":221},[215,1175,1158],{"class":450},[215,1177,1002],{"class":221},[215,1179,1180],{"class":235},"\"notary\"",[215,1182,1183],{"class":221},")) {\n",[215,1185,1187,1189,1191,1193,1195,1198],{"class":217,"line":1186},17,[215,1188,993],{"class":414},[215,1190,996],{"class":414},[215,1192,999],{"class":450},[215,1194,1002],{"class":221},[215,1196,1197],{"class":235},"\"missing required signers\"",[215,1199,538],{"class":221},[215,1201,1203],{"class":217,"line":1202},18,[215,1204,331],{"class":221},[215,1206,1208],{"class":217,"line":1207},19,[215,1209,433],{"emptyLinePlaceholder":432},[215,1211,1213],{"class":217,"line":1212},20,[215,1214,1215],{"class":483},"\u002F\u002F Audit log — record every outcome regardless of policy\n",[215,1217,1219,1222,1224,1226,1229,1232],{"class":217,"line":1218},21,[215,1220,1221],{"class":414},"for",[215,1223,927],{"class":221},[215,1225,438],{"class":414},[215,1227,1228],{"class":228}," o",[215,1230,1231],{"class":414}," of",[215,1233,1234],{"class":221}," outcomes) {\n",[215,1236,1238,1241,1244,1247,1250,1253],{"class":217,"line":1237},22,[215,1239,1240],{"class":450},"  log",[215,1242,1243],{"class":221},"(o.signerIndex, o.verified ",[215,1245,1246],{"class":414},"?",[215,1248,1249],{"class":235}," \"ok\"",[215,1251,1252],{"class":414}," :",[215,1254,1255],{"class":221}," o.error.code);\n",[215,1257,1259],{"class":217,"line":1258},23,[215,1260,331],{"class":221},[173,1262,1263],{},"Each outcome is one of:",[206,1265,1267],{"className":404,"code":1266,"language":407,"meta":211,"style":211},"\u002F\u002F Success\n{ signerIndex: number, verified: true, payload: T, protectedHeader: ..., signerHeader?: ... }\n\n\u002F\u002F Failure (captured — does NOT throw)\n{ signerIndex: number, verified: false, error: JWTError, protectedHeader?: ..., signerHeader?: ... }\n",[185,1268,1269,1274,1319,1323,1328],{"__ignoreMap":211},[215,1270,1271],{"class":217,"line":218},[215,1272,1273],{"class":483},"\u002F\u002F Success\n",[215,1275,1276,1279,1281,1284,1287,1289,1291,1293,1295,1297,1300,1302,1304,1306,1308,1311,1314,1317],{"class":217,"line":225},[215,1277,1278],{"class":221},"{ ",[215,1280,752],{"class":450},[215,1282,1283],{"class":221},": number, ",[215,1285,1286],{"class":450},"verified",[215,1288,232],{"class":221},[215,1290,858],{"class":228},[215,1292,265],{"class":221},[215,1294,747],{"class":450},[215,1296,232],{"class":221},[215,1298,1299],{"class":228},"T",[215,1301,265],{"class":221},[215,1303,620],{"class":450},[215,1305,232],{"class":221},[215,1307,275],{"class":414},[215,1309,1310],{"class":221},", signerHeader",[215,1312,1313],{"class":414},"?:",[215,1315,1316],{"class":414}," ...",[215,1318,319],{"class":221},[215,1320,1321],{"class":217,"line":242},[215,1322,433],{"emptyLinePlaceholder":432},[215,1324,1325],{"class":217,"line":251},[215,1326,1327],{"class":483},"\u002F\u002F Failure (captured — does NOT throw)\n",[215,1329,1330,1332,1334,1336,1338,1340,1343,1345,1348,1351,1353,1355,1357,1359,1361],{"class":217,"line":292},[215,1331,1278],{"class":221},[215,1333,752],{"class":450},[215,1335,1283],{"class":221},[215,1337,1286],{"class":450},[215,1339,232],{"class":221},[215,1341,1342],{"class":228},"false",[215,1344,265],{"class":221},[215,1346,1347],{"class":450},"error",[215,1349,1350],{"class":221},": JWTError, protectedHeader",[215,1352,1313],{"class":414},[215,1354,1316],{"class":414},[215,1356,1310],{"class":221},[215,1358,1313],{"class":414},[215,1360,1316],{"class":414},[215,1362,319],{"class":221},[173,1364,1365,1366,265,1368,1371],{},"Failures captured include: malformed headers, disallowed ",[185,1367,337],{},[185,1369,1370],{},"typ"," mismatch, resolver errors, bad signatures, critical-header violations, JWT-claim failures.",[1373,1374,1375],"warning",{},[173,1376,1377,1378,1381,1382,1384,1385,1388,1389,1392],{},"Structural errors on the ",[177,1379,1380],{},"envelope itself"," (non-object input, missing ",[185,1383,747],{},", missing ",[185,1386,1387],{},"signatures[]",") still throw ",[185,1390,1391],{},"ERR_JWS_INVALID_SERIALIZATION"," — there's no per-signature outcome to record in that case.",[574,1394,1396],{"id":1395},"the-key-resolver-is-required","The key resolver is required",[173,1398,1399,1400,1403,1404,265,1406,1408,1409,1412,1413,1416],{},"Unlike ",[185,1401,1402],{},"verify"," and ",[185,1405,707],{},[185,1407,875],{}," always takes a ",[177,1410,1411],{},"function",". Signatures typically come from different signers with different keys; a function is the natural way to express that. Wrap a static set as ",[185,1414,1415],{},"(header) => myJwkSet"," if that's what you have.",[396,1418,1420],{"id":1419},"use-cases","Use cases",[346,1422,1423,1434,1440,1446,1452],{},[349,1424,1425,1428,1429,1431,1432,180],{},[177,1426,1427],{},"Key rotation overlap."," During a rotation window, sign with both the old and new key; verifiers accept either via ",[185,1430,707],{},". Once the old key is retired, switch back to single ",[185,1433,187],{},[349,1435,1436,1439],{},[177,1437,1438],{},"Algorithm agility."," Sign with an HMAC key (fast, cheap to verify for your own backend) and an EdDSA key (publicly verifiable via JWKS). Each consumer uses the signature they trust.",[349,1441,1442,1445],{},[177,1443,1444],{},"Notary \u002F witness."," Attach a secondary signature from a neutral party (\"alice signed, notary witnessed\") without bundling their keys.",[349,1447,1448,1451],{},[177,1449,1450],{},"Hybrid classical + post-quantum signatures."," Sign with two algorithms so a migration doesn't break old tokens.",[349,1453,1454,1457,1458,1460,1461,1463],{},[177,1455,1456],{},"M-of-N approval."," Use ",[185,1459,875],{}," and reject unless at least M of the registered signer ",[185,1462,340],{},"s are present.",[396,1465,1467],{"id":1466},"flattened-form","Flattened form",[173,1469,1470,1471,1473,1474,1476],{},"For consumers that strictly expect ",[177,1472,694],{}," serialization (single signer, JSON shape), call ",[185,1475,701],{}," on a single-signer General output:",[206,1478,1481],{"className":404,"code":1479,"filename":1480,"language":407,"meta":211,"style":211},"import { signMulti, generalToFlattenedJWS } from \"unjwt\u002Fjws\";\n\nconst general = await signMulti(payload, [singleSigner], opts);\nconst flattened = generalToFlattenedJWS(general);\n\u002F\u002F { payload, protected, header?, signature }\n","flattened.ts",[185,1482,1483,1496,1500,1516,1531],{"__ignoreMap":211},[215,1484,1485,1487,1490,1492,1494],{"class":217,"line":218},[215,1486,415],{"class":414},[215,1488,1489],{"class":221}," { signMulti, generalToFlattenedJWS } ",[215,1491,421],{"class":414},[215,1493,424],{"class":235},[215,1495,427],{"class":221},[215,1497,1498],{"class":217,"line":225},[215,1499,433],{"emptyLinePlaceholder":432},[215,1501,1502,1504,1507,1509,1511,1513],{"class":217,"line":242},[215,1503,438],{"class":414},[215,1505,1506],{"class":228}," general",[215,1508,444],{"class":414},[215,1510,447],{"class":414},[215,1512,451],{"class":450},[215,1514,1515],{"class":221},"(payload, [singleSigner], opts);\n",[215,1517,1518,1520,1523,1525,1528],{"class":217,"line":251},[215,1519,438],{"class":414},[215,1521,1522],{"class":228}," flattened",[215,1524,444],{"class":414},[215,1526,1527],{"class":450}," generalToFlattenedJWS",[215,1529,1530],{"class":221},"(general);\n",[215,1532,1533],{"class":217,"line":292},[215,1534,1535],{"class":483},"\u002F\u002F { payload, protected, header?, signature }\n",[173,1537,1538,1539,1541],{},"Throws ",[185,1540,1391],{}," if the input has zero or multiple signatures — Flattened is strictly single-signer.",[173,1543,1544,1403,1546,1548],{},[185,1545,707],{},[185,1547,875],{}," both accept Flattened input directly — they auto-normalize to General in memory.",[396,1550,1552],{"id":1551},"how-jws-multi-sig-differs-from-jwe-multi-recipient","How JWS multi-sig differs from JWE multi-recipient",[173,1554,1555],{},"They look similar on the surface, but:",[346,1557,1558,1567,1576],{},[349,1559,1560,1563,1564,180],{},[177,1561,1562],{},"Payload is shared, headers are per-signer."," Opposite of JWE where the protected header is shared and per-recipient state lives in ",[185,1565,1566],{},"recipients[]",[349,1568,1569,1572,1573,1575],{},[177,1570,1571],{},"No shared unprotected header at the top level"," — only per-signature ",[185,1574,931],{}," fields.",[349,1577,1578,1585],{},[177,1579,1580,1581,1584],{},"The ",[185,1582,1583],{},"b64: false"," constraint"," — all signers must agree, since they all sign the same payload bytes.",[173,1587,1588,1589,1592],{},"See ",[194,1590,1591],{"href":69},"JWE multi-recipient →"," for the other side.",[1594,1595,1596],"style",{},"html pre.shiki code .slsVL, html code.shiki .slsVL{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .suiK_, html code.shiki .suiK_{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html pre.shiki code .sfrk1, html code.shiki .sfrk1{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html pre.shiki code .sVAnh, html code.shiki .sVAnh{--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-default:#FDAEB7;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .so5gQ, html code.shiki .so5gQ{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F97583}html pre.shiki code .shcOC, html code.shiki .shcOC{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#B392F0}html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sQHwn, html code.shiki .sQHwn{--shiki-light:#E36209;--shiki-default:#FFAB70;--shiki-dark:#FFAB70}",{"title":211,"searchDepth":225,"depth":225,"links":1598},[1599,1603,1607,1610,1611,1612],{"id":398,"depth":225,"text":401,"children":1600},[1601,1602],{"id":576,"depth":242,"text":577},{"id":639,"depth":242,"text":640},{"id":704,"depth":225,"text":707,"children":1604},[1605,1606],{"id":788,"depth":242,"text":789},{"id":814,"depth":242,"text":815},{"id":872,"depth":225,"text":875,"children":1608},[1609],{"id":1395,"depth":242,"text":1396},{"id":1419,"depth":225,"text":1420},{"id":1466,"depth":225,"text":1467},{"id":1551,"depth":225,"text":1552},"md",{},{},{"title":45,"description":211},"ofHQF9NU2TuMQnhqzAEwcpEwoWbq8yFe9uNvcdTqo94",[1619,1620],{"title":41,"path":42,"stem":43,"description":211,"children":-1},{"title":49,"path":50,"stem":51,"description":211,"children":-1},1776888560030]