@sphereon/ssi-sdk.mdl-mdoc 0.37.2-next.34 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -119,16 +119,22 @@ declare const mdocSupportMethods: Array<string>;
119
119
  declare class MDLMdoc implements IAgentPlugin {
120
120
  readonly schema: any;
121
121
  readonly methods: ImDLMdoc;
122
- private readonly trustAnchors;
122
+ private readonly staticTrustAnchors;
123
+ private readonly trustAnchorProvider?;
124
+ private readonly blindlyTrustedAnchorProvider?;
123
125
  private opts;
124
126
  constructor(args?: {
125
127
  trustAnchors?: string[];
128
+ trustAnchorProvider?: () => string[];
129
+ blindlyTrustedAnchorProvider?: () => string[];
126
130
  opts?: {
127
131
  trustRootWhenNoAnchors?: boolean;
128
132
  allowSingleNoCAChainElement?: boolean;
129
133
  blindlyTrustedAnchors?: string[];
130
134
  };
131
135
  });
136
+ private get trustAnchors();
137
+ private get effectiveBlindlyTrustedAnchors();
132
138
  /**
133
139
  * Processes and verifies the provided mdoc, generates device response and presentation submission tokens.
134
140
  *
package/dist/index.d.ts CHANGED
@@ -119,16 +119,22 @@ declare const mdocSupportMethods: Array<string>;
119
119
  declare class MDLMdoc implements IAgentPlugin {
120
120
  readonly schema: any;
121
121
  readonly methods: ImDLMdoc;
122
- private readonly trustAnchors;
122
+ private readonly staticTrustAnchors;
123
+ private readonly trustAnchorProvider?;
124
+ private readonly blindlyTrustedAnchorProvider?;
123
125
  private opts;
124
126
  constructor(args?: {
125
127
  trustAnchors?: string[];
128
+ trustAnchorProvider?: () => string[];
129
+ blindlyTrustedAnchorProvider?: () => string[];
126
130
  opts?: {
127
131
  trustRootWhenNoAnchors?: boolean;
128
132
  allowSingleNoCAChainElement?: boolean;
129
133
  blindlyTrustedAnchors?: string[];
130
134
  };
131
135
  });
136
+ private get trustAnchors();
137
+ private get effectiveBlindlyTrustedAnchors();
132
138
  /**
133
139
  * Processes and verifies the provided mdoc, generates device response and presentation submission tokens.
134
140
  *
package/dist/index.js CHANGED
@@ -2056,15 +2056,315 @@ import { derToPEM, getCertificateInfo, getSubjectDN, pemOrDerToX509Certificate,
2056
2056
  import * as crypto from "crypto";
2057
2057
  import { CryptoEngine, setEngine } from "pkijs";
2058
2058
  import { fromString } from "uint8arrays/from-string";
2059
+ import { toString as u8aToString } from "uint8arrays/to-string";
2059
2060
  var { com } = mdocPkg;
2060
2061
  var CoseJoseKeyMappingService = com.sphereon.crypto.CoseJoseKeyMappingService;
2061
2062
  var KeyInfo = mdocPkg.com.sphereon.crypto.KeyInfo;
2062
2063
  var DateTimeUtils = mdocPkg.com.sphereon.kmp.DateTimeUtils;
2063
- var decodeFrom = mdocPkg.com.sphereon.kmp.decodeFrom;
2064
- var encodeTo = mdocPkg.com.sphereon.kmp.encodeTo;
2065
- var Encoding = mdocPkg.com.sphereon.kmp.Encoding;
2066
2064
  var SignatureAlgorithm = mdocPkg.com.sphereon.crypto.generic.SignatureAlgorithm;
2067
2065
  var DefaultCallbacks = mdocPkg.com.sphereon.crypto.DefaultCallbacks;
2066
+ function toU8(bytes) {
2067
+ if (bytes instanceof Uint8Array) return bytes;
2068
+ if (ArrayBuffer.isView(bytes)) {
2069
+ const v = bytes;
2070
+ return new Uint8Array(v.buffer, v.byteOffset, v.byteLength);
2071
+ }
2072
+ if (Array.isArray(bytes)) return Uint8Array.from(bytes.map((b) => b & 255));
2073
+ throw new Error("unsupported raw bytes type");
2074
+ }
2075
+ __name(toU8, "toU8");
2076
+ function extractIssuerAuthRawParts(rawInput) {
2077
+ const u8 = toU8(rawInput);
2078
+ let pos = 0;
2079
+ const readHead = /* @__PURE__ */ __name(() => {
2080
+ const b = u8[pos++];
2081
+ const mt = b >> 5;
2082
+ const info = b & 31;
2083
+ let len;
2084
+ if (info < 24) len = info;
2085
+ else if (info === 24) {
2086
+ len = u8[pos];
2087
+ pos += 1;
2088
+ } else if (info === 25) {
2089
+ len = u8[pos] << 8 | u8[pos + 1];
2090
+ pos += 2;
2091
+ } else if (info === 26) {
2092
+ len = u8[pos] * 16777216 + (u8[pos + 1] << 16) + (u8[pos + 2] << 8) + u8[pos + 3];
2093
+ pos += 4;
2094
+ } else throw new Error("unsupported cbor length info " + info);
2095
+ return {
2096
+ mt,
2097
+ len
2098
+ };
2099
+ }, "readHead");
2100
+ const skip = /* @__PURE__ */ __name(() => {
2101
+ const h = readHead();
2102
+ switch (h.mt) {
2103
+ case 0:
2104
+ case 1:
2105
+ case 7:
2106
+ return;
2107
+ case 2:
2108
+ case 3:
2109
+ pos += h.len;
2110
+ return;
2111
+ case 4:
2112
+ for (let i = 0; i < h.len; i++) skip();
2113
+ return;
2114
+ case 5:
2115
+ for (let i = 0; i < h.len * 2; i++) skip();
2116
+ return;
2117
+ case 6:
2118
+ skip();
2119
+ return;
2120
+ }
2121
+ }, "skip");
2122
+ const readBstr = /* @__PURE__ */ __name(() => {
2123
+ const h = readHead();
2124
+ if (h.mt !== 2) throw new Error("expected bstr, got mt " + h.mt);
2125
+ const out = u8.slice(pos, pos + h.len);
2126
+ pos += h.len;
2127
+ return out;
2128
+ }, "readBstr");
2129
+ const readTstr = /* @__PURE__ */ __name(() => {
2130
+ const h = readHead();
2131
+ if (h.mt !== 3) throw new Error("expected tstr, got mt " + h.mt);
2132
+ const out = new TextDecoder().decode(u8.slice(pos, pos + h.len));
2133
+ pos += h.len;
2134
+ return out;
2135
+ }, "readTstr");
2136
+ const outer = readHead();
2137
+ if (outer.mt !== 5) return void 0;
2138
+ for (let i = 0; i < outer.len; i++) {
2139
+ const key = readTstr();
2140
+ if (key === "issuerAuth") {
2141
+ const arr = readHead();
2142
+ if (arr.mt !== 4 || arr.len !== 4) throw new Error("issuerAuth is not a 4-element array");
2143
+ const protectedBytes = readBstr();
2144
+ skip();
2145
+ const payloadBytes = readBstr();
2146
+ return {
2147
+ protectedBytes,
2148
+ payloadBytes
2149
+ };
2150
+ }
2151
+ skip();
2152
+ }
2153
+ return void 0;
2154
+ }
2155
+ __name(extractIssuerAuthRawParts, "extractIssuerAuthRawParts");
2156
+ function encodeBstrHeader(len) {
2157
+ if (len < 24) return new Uint8Array([
2158
+ 64 | len
2159
+ ]);
2160
+ if (len < 256) return new Uint8Array([
2161
+ 88,
2162
+ len
2163
+ ]);
2164
+ if (len < 65536) return new Uint8Array([
2165
+ 89,
2166
+ len >> 8 & 255,
2167
+ len & 255
2168
+ ]);
2169
+ return new Uint8Array([
2170
+ 90,
2171
+ len >>> 24 & 255,
2172
+ len >> 16 & 255,
2173
+ len >> 8 & 255,
2174
+ len & 255
2175
+ ]);
2176
+ }
2177
+ __name(encodeBstrHeader, "encodeBstrHeader");
2178
+ function concatU8(parts) {
2179
+ let total = 0;
2180
+ for (const p of parts) total += p.length;
2181
+ const out = new Uint8Array(total);
2182
+ let off = 0;
2183
+ for (const p of parts) {
2184
+ out.set(p, off);
2185
+ off += p.length;
2186
+ }
2187
+ return out;
2188
+ }
2189
+ __name(concatU8, "concatU8");
2190
+ function buildSig1Structure(protectedBytes, payloadBytes) {
2191
+ const sig1Label = new Uint8Array([
2192
+ 106,
2193
+ 83,
2194
+ 105,
2195
+ 103,
2196
+ 110,
2197
+ 97,
2198
+ 116,
2199
+ 117,
2200
+ 114,
2201
+ 101,
2202
+ 49
2203
+ ]);
2204
+ return concatU8([
2205
+ new Uint8Array([
2206
+ 132
2207
+ ]),
2208
+ sig1Label,
2209
+ encodeBstrHeader(protectedBytes.length),
2210
+ protectedBytes,
2211
+ new Uint8Array([
2212
+ 64
2213
+ ]),
2214
+ encodeBstrHeader(payloadBytes.length),
2215
+ payloadBytes
2216
+ ]);
2217
+ }
2218
+ __name(buildSig1Structure, "buildSig1Structure");
2219
+ function derEcdsaToRaw(der, coordSize) {
2220
+ let offset = 0;
2221
+ if (der[offset++] !== 48) throw new Error("Invalid DER ECDSA signature: missing SEQUENCE tag");
2222
+ let seqLen = der[offset++];
2223
+ if (seqLen & 128) {
2224
+ const numBytes = seqLen & 127;
2225
+ seqLen = 0;
2226
+ for (let i = 0; i < numBytes; i++) seqLen = seqLen << 8 | der[offset++];
2227
+ }
2228
+ const readInt = /* @__PURE__ */ __name(() => {
2229
+ if (der[offset++] !== 2) throw new Error("Invalid DER ECDSA signature: missing INTEGER tag");
2230
+ const len = der[offset++];
2231
+ let val = der.slice(offset, offset + len);
2232
+ offset += len;
2233
+ let start = 0;
2234
+ while (start < val.length - 1 && val[start] === 0) start++;
2235
+ val = val.slice(start);
2236
+ if (val.length > coordSize) throw new Error(`Invalid DER ECDSA signature: integer (${val.length}) exceeds ${coordSize}`);
2237
+ const out = new Uint8Array(coordSize);
2238
+ out.set(val, coordSize - val.length);
2239
+ return out;
2240
+ }, "readInt");
2241
+ const r = readInt();
2242
+ const s = readInt();
2243
+ return concatU8([
2244
+ r,
2245
+ s
2246
+ ]);
2247
+ }
2248
+ __name(derEcdsaToRaw, "derEcdsaToRaw");
2249
+ function decodeKmsSignatureToRaw(signature, coordSize) {
2250
+ const normalized = signature.trim().replace(/\s+/g, "").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
2251
+ const bytes = fromString(normalized, "base64url");
2252
+ if (bytes.length > coordSize * 2 && bytes[0] === 48) {
2253
+ return derEcdsaToRaw(bytes, coordSize);
2254
+ }
2255
+ return bytes;
2256
+ }
2257
+ __name(decodeKmsSignatureToRaw, "decodeKmsSignatureToRaw");
2258
+ function cborHeader(buf, off) {
2259
+ const ib = buf[off];
2260
+ const major = ib >> 5;
2261
+ const ai = ib & 31;
2262
+ if (ai < 24) return {
2263
+ major,
2264
+ headerLen: 1,
2265
+ argument: ai
2266
+ };
2267
+ if (ai === 24) return {
2268
+ major,
2269
+ headerLen: 2,
2270
+ argument: buf[off + 1]
2271
+ };
2272
+ if (ai === 25) return {
2273
+ major,
2274
+ headerLen: 3,
2275
+ argument: buf[off + 1] << 8 | buf[off + 2]
2276
+ };
2277
+ if (ai === 26) return {
2278
+ major,
2279
+ headerLen: 5,
2280
+ argument: buf[off + 1] * 16777216 + (buf[off + 2] << 16) + (buf[off + 3] << 8) + buf[off + 4]
2281
+ };
2282
+ if (ai === 27) {
2283
+ let v = 0;
2284
+ for (let i = 1; i <= 8; i++) v = v * 256 + buf[off + i];
2285
+ return {
2286
+ major,
2287
+ headerLen: 9,
2288
+ argument: v
2289
+ };
2290
+ }
2291
+ throw new Error(`unsupported CBOR additional-info ${ai} at offset ${off}`);
2292
+ }
2293
+ __name(cborHeader, "cborHeader");
2294
+ function cborItemLen(buf, off) {
2295
+ const h = cborHeader(buf, off);
2296
+ let total = h.headerLen;
2297
+ switch (h.major) {
2298
+ case 0:
2299
+ case 1:
2300
+ case 7:
2301
+ break;
2302
+ case 2:
2303
+ case 3:
2304
+ total += h.argument;
2305
+ break;
2306
+ case 4:
2307
+ for (let i = 0; i < h.argument; i++) total += cborItemLen(buf, off + total);
2308
+ break;
2309
+ case 5:
2310
+ for (let i = 0; i < h.argument * 2; i++) total += cborItemLen(buf, off + total);
2311
+ break;
2312
+ case 6:
2313
+ total += cborItemLen(buf, off + total);
2314
+ break;
2315
+ default:
2316
+ throw new Error(`unsupported CBOR major type ${h.major}`);
2317
+ }
2318
+ return total;
2319
+ }
2320
+ __name(cborItemLen, "cborItemLen");
2321
+ function reconstructMdocDeviceAuthSigStructure(sig) {
2322
+ if (sig[0] !== 132) return sig;
2323
+ let off = 1;
2324
+ off += cborItemLen(sig, off);
2325
+ off += cborItemLen(sig, off);
2326
+ off += cborItemLen(sig, off);
2327
+ const payloadStart = off;
2328
+ const ph = cborHeader(sig, payloadStart);
2329
+ if (ph.major !== 2) return sig;
2330
+ const daStart = payloadStart + ph.headerLen;
2331
+ const da = sig.subarray(daStart, daStart + ph.argument);
2332
+ if (da[0] !== 132) return sig;
2333
+ let d = 1;
2334
+ d += cborItemLen(da, d);
2335
+ d += cborItemLen(da, d);
2336
+ d += cborItemLen(da, d);
2337
+ const e4 = da.subarray(d, d + cborItemLen(da, d));
2338
+ const e4Tagged = concatU8([
2339
+ new Uint8Array([
2340
+ 216,
2341
+ 24
2342
+ ]),
2343
+ encodeBstrHeader(e4.length),
2344
+ e4
2345
+ ]);
2346
+ const daCorrected = concatU8([
2347
+ da.subarray(0, d),
2348
+ e4Tagged
2349
+ ]);
2350
+ const deviceAuthBytes = concatU8([
2351
+ new Uint8Array([
2352
+ 216,
2353
+ 24
2354
+ ]),
2355
+ encodeBstrHeader(daCorrected.length),
2356
+ daCorrected
2357
+ ]);
2358
+ const newPayload = concatU8([
2359
+ encodeBstrHeader(deviceAuthBytes.length),
2360
+ deviceAuthBytes
2361
+ ]);
2362
+ return concatU8([
2363
+ sig.subarray(0, payloadStart),
2364
+ newPayload
2365
+ ]);
2366
+ }
2367
+ __name(reconstructMdocDeviceAuthSigStructure, "reconstructMdocDeviceAuthSigStructure");
2068
2368
  var CoseCryptoService = class {
2069
2369
  static {
2070
2370
  __name(this, "CoseCryptoService");
@@ -2081,7 +2381,21 @@ var CoseCryptoService = class {
2081
2381
  throw Error("No context provided. Please provide a context with the setContext method or constructor");
2082
2382
  }
2083
2383
  const { keyInfo, alg, value } = input;
2384
+ let toBeSigned = toU8(value);
2385
+ try {
2386
+ toBeSigned = reconstructMdocDeviceAuthSigStructure(toBeSigned);
2387
+ } catch (e) {
2388
+ console.log(`(mdl-mdoc:sign) Sig_structure tag-24 reconstruction failed, signing kmp original: ${e?.message}`);
2389
+ }
2390
+ try {
2391
+ let hex = "";
2392
+ for (let i = 0; i < toBeSigned.length; i++) hex += (toBeSigned[i] & 255).toString(16).padStart(2, "0");
2393
+ console.log(`(mdl-mdoc:sign) ToBeSigned len=${toBeSigned.length} hex=${hex}`);
2394
+ } catch (e) {
2395
+ console.log(`(mdl-mdoc:sign) ToBeSigned hex failed: ${e?.message}`);
2396
+ }
2084
2397
  let kmsKeyRef = keyInfo.kmsKeyRef ?? void 0;
2398
+ const fallbackKeyRefs = [];
2085
2399
  if (!kmsKeyRef) {
2086
2400
  const key = keyInfo.key;
2087
2401
  if (key == null) {
@@ -2089,21 +2403,49 @@ var CoseCryptoService = class {
2089
2403
  }
2090
2404
  const resolvedKeyInfo = com.sphereon.crypto.ResolvedKeyInfo.Static.fromKeyInfo(keyInfo, key);
2091
2405
  const jwkKeyInfo = CoseJoseKeyMappingService.toResolvedJwkKeyInfo(resolvedKeyInfo);
2092
- const kid = jwkKeyInfo.kid ?? calculateJwkThumbprint({
2406
+ const thumbprint = calculateJwkThumbprint({
2093
2407
  jwk: jwkKeyInfo.key.toJsonDTO()
2094
- }) ?? jwkKeyInfo.key.getKidAsString(true);
2408
+ });
2409
+ const kid = jwkKeyInfo.kid ?? thumbprint ?? jwkKeyInfo.key.getKidAsString(true);
2095
2410
  if (!kid) {
2096
2411
  return Promise.reject(Error("No kid present and not kmsKeyRef provided"));
2097
2412
  }
2098
2413
  kmsKeyRef = kid;
2414
+ if (thumbprint && thumbprint !== kid) {
2415
+ fallbackKeyRefs.push(thumbprint);
2416
+ }
2099
2417
  }
2100
- const result = await this.context.agent.keyManagerSign({
2418
+ const doSign = /* @__PURE__ */ __name((keyRef) => this.context.agent.keyManagerSign({
2101
2419
  algorithm: alg.jose.value,
2102
- data: encodeTo(value, Encoding.UTF8),
2103
- encoding: "utf-8",
2104
- keyRef: kmsKeyRef
2105
- });
2106
- return decodeFrom(result, Encoding.UTF8);
2420
+ // Pass the raw ToBeSigned (COSE Sig_structure) bytes as base64. The previous `encodeTo(value, UTF8)`
2421
+ // interpreted the binary CBOR as UTF-8 text, corrupting every non-ASCII byte before the KMS even saw it
2422
+ // (the MUSAP bridge then signed the mangled bytes -> verifier "Signature invalid"). base64 round-trips losslessly.
2423
+ data: u8aToString(toBeSigned, "base64"),
2424
+ encoding: "base64",
2425
+ keyRef
2426
+ }), "doSign");
2427
+ let result;
2428
+ try {
2429
+ result = await doSign(kmsKeyRef);
2430
+ } catch (error) {
2431
+ let signed;
2432
+ for (const ref of fallbackKeyRefs) {
2433
+ try {
2434
+ signed = await doSign(ref);
2435
+ break;
2436
+ } catch {
2437
+ }
2438
+ }
2439
+ if (signed === void 0) {
2440
+ throw error;
2441
+ }
2442
+ result = signed;
2443
+ }
2444
+ const joseAlg = alg.jose?.value;
2445
+ const coordSize = joseAlg === "ES512" ? 66 : joseAlg === "ES384" ? 48 : 32;
2446
+ const raw = decodeKmsSignatureToRaw(result, coordSize);
2447
+ console.log(`(mdl-mdoc:sign) signature decoded: alg=${joseAlg}, inputChars=${result.length}, rawLen=${raw.length} (expected ${coordSize * 2})`);
2448
+ return Int8Array.from(raw);
2107
2449
  }
2108
2450
  async verify1Async(input, keyInfo, requireX5Chain) {
2109
2451
  const getCertAndKey = /* @__PURE__ */ __name(async (x5c2) => {
@@ -2153,9 +2495,22 @@ var CoseCryptoService = class {
2153
2495
  const issuerCoseKeyInfo = new KeyInfo(kid, issuerCoseKey, coseKeyInfo.opts, coseKeyInfo.keyVisibility, issuerCoseKey.getSignatureAlgorithm() ?? coseKeyInfo.signatureAlgorithm, x5c, coseKeyInfo.kmsKeyRef, coseKeyInfo.kms, coseKeyInfo.keyType ?? issuerCoseKey.getKty());
2154
2496
  const recalculatedToBeSigned = input.toBeSignedJson(issuerCoseKeyInfo, SignatureAlgorithm.Static.fromCose(coseAlg));
2155
2497
  const key = CoseJoseKeyMappingService.toJoseJwk(issuerCoseKeyInfo.key).toJsonDTO();
2498
+ let data = fromString(recalculatedToBeSigned.base64UrlValue, "base64url");
2499
+ const signatureBytes = fromString(sign1Json.signature, "base64url");
2500
+ const rawMdocBytes = globalThis.__sphereon_mdoc_raw_bytes;
2501
+ if (rawMdocBytes) {
2502
+ try {
2503
+ const extracted = extractIssuerAuthRawParts(rawMdocBytes);
2504
+ if (extracted) {
2505
+ data = buildSig1Structure(extracted.protectedBytes, extracted.payloadBytes);
2506
+ }
2507
+ } catch (e) {
2508
+ console.warn("[mdl-mdoc verify] failed to reparse raw mdoc; falling back to kmp-computed Sig_structure:", e.message);
2509
+ }
2510
+ }
2156
2511
  const valid = await verifyRawSignature({
2157
- data: fromString(recalculatedToBeSigned.base64UrlValue, "base64url"),
2158
- signature: fromString(sign1Json.signature, "base64url"),
2512
+ data,
2513
+ signature: signatureBytes,
2159
2514
  key
2160
2515
  });
2161
2516
  return {
@@ -2276,9 +2631,9 @@ var CoseCryptoServiceJS = com2.sphereon.crypto.CoseCryptoServiceJS;
2276
2631
  var CoseJoseKeyMappingService2 = com2.sphereon.crypto.CoseJoseKeyMappingService;
2277
2632
  var KeyInfo2 = com2.sphereon.crypto.KeyInfo;
2278
2633
  var DateTimeUtils2 = com2.sphereon.kmp.DateTimeUtils;
2279
- var decodeFrom2 = com2.sphereon.kmp.decodeFrom;
2280
- var encodeTo2 = com2.sphereon.kmp.encodeTo;
2281
- var Encoding2 = com2.sphereon.kmp.Encoding;
2634
+ var decodeFrom = com2.sphereon.kmp.decodeFrom;
2635
+ var encodeTo = com2.sphereon.kmp.encodeTo;
2636
+ var Encoding = com2.sphereon.kmp.Encoding;
2282
2637
  var MdocValidations = com2.sphereon.mdoc.data.MdocValidations;
2283
2638
  var MdocOid4vpService = com2.sphereon.mdoc.oid4vp.MdocOid4vpServiceJs;
2284
2639
  var Jwk = com2.sphereon.crypto.jose.Jwk;
@@ -2305,14 +2660,31 @@ var MDLMdoc = class {
2305
2660
  mdocOid4vpHolderPresent: this.mdocOid4vpHolderPresent.bind(this),
2306
2661
  mdocOid4vpRPVerify: this.mdocOid4vpRPVerify.bind(this)
2307
2662
  };
2308
- trustAnchors;
2663
+ staticTrustAnchors;
2664
+ trustAnchorProvider;
2665
+ blindlyTrustedAnchorProvider;
2309
2666
  opts;
2310
2667
  constructor(args) {
2311
- this.trustAnchors = args?.trustAnchors ?? [];
2668
+ this.staticTrustAnchors = args?.trustAnchors ?? [];
2669
+ this.trustAnchorProvider = args?.trustAnchorProvider;
2670
+ this.blindlyTrustedAnchorProvider = args?.blindlyTrustedAnchorProvider;
2312
2671
  this.opts = args?.opts ?? {
2313
2672
  trustRootWhenNoAnchors: true
2314
2673
  };
2315
2674
  }
2675
+ // Live-merged anchors: static (constructor) + provider (runtime/user). Read on every verification.
2676
+ get trustAnchors() {
2677
+ return [
2678
+ ...this.staticTrustAnchors,
2679
+ ...this.trustAnchorProvider?.() ?? []
2680
+ ];
2681
+ }
2682
+ get effectiveBlindlyTrustedAnchors() {
2683
+ return [
2684
+ ...this.opts.blindlyTrustedAnchors ?? [],
2685
+ ...this.blindlyTrustedAnchorProvider?.() ?? []
2686
+ ];
2687
+ }
2316
2688
  /**
2317
2689
  * Processes and verifies the provided mdoc, generates device response and presentation submission tokens.
2318
2690
  *
@@ -2353,22 +2725,36 @@ var MDLMdoc = class {
2353
2725
  const result = await validate(match.document);
2354
2726
  if (!result.error || responseUri.includes("openid.net")) {
2355
2727
  try {
2356
- const cborKey = result.keyInfo?.key ? CoseKeyCbor.Static.fromDTO(result.keyInfo.key) : void 0;
2728
+ const matchDeviceKeyInfo = match.deviceKeyInfo;
2729
+ const deviceKeyInfoSource = matchDeviceKeyInfo ?? result.keyInfo;
2730
+ console.log(`(mdl-mdoc:deviceKey) amend: match.deviceKeyInfo present=${!!matchDeviceKeyInfo}, match.deviceKeyInfo.key present=${!!matchDeviceKeyInfo?.key}, result.keyInfo present=${!!result.keyInfo}, result.keyInfo.key present=${!!result.keyInfo?.key}, source=${matchDeviceKeyInfo ? "match.deviceKeyInfo" : "result.keyInfo"}`);
2731
+ const cborKey = deviceKeyInfoSource?.key ? CoseKeyCbor.Static.fromDTO(deviceKeyInfoSource.key) : void 0;
2357
2732
  if (!cborKey) {
2358
- throw Error("No key found in result");
2733
+ throw Error("No device (public) key found to amend: neither match.deviceKeyInfo.key nor result.keyInfo.key is populated. The mdoc MSO device public key is required to resolve the hardware-backed KMS key for signing.");
2359
2734
  }
2360
2735
  let jwk = CoseJoseKeyMappingService2.toJoseJwk(cborKey).toJsonDTO();
2361
- if (!result.keyInfo?.kmsKeyRef) {
2362
- const keyInfo = result.keyInfo;
2363
- const kid = jwk.kid ?? calculateJwkThumbprint2({
2736
+ if (!deviceKeyInfoSource?.kmsKeyRef) {
2737
+ const keyInfo = deviceKeyInfoSource;
2738
+ const thumbprint = calculateJwkThumbprint2({
2364
2739
  jwk
2365
2740
  });
2366
- const key = await _context.agent.keyManagerGet({
2367
- kid
2368
- });
2741
+ const kid = jwk.kid ?? thumbprint;
2742
+ console.log(`(mdl-mdoc:deviceKey) amend: resolved device public jwk kid=${jwk.kid}, thumbprint=${thumbprint}`);
2743
+ let key;
2744
+ try {
2745
+ key = await _context.agent.keyManagerGet({
2746
+ kid
2747
+ });
2748
+ } catch (e) {
2749
+ console.log(`(mdl-mdoc:deviceKey) amend: keyManagerGet by kid '${kid}' failed (${e?.message}); retrying by thumbprint '${thumbprint}'`);
2750
+ key = await _context.agent.keyManagerGet({
2751
+ kid: thumbprint
2752
+ });
2753
+ }
2369
2754
  const kms = key.kms;
2370
- const kmsKeyRef = key.meta?.kmsKeyRef;
2371
- const updateCborKey = cborKey.copy(false, cborKey.kty, cborKey.kid ?? new CborByteString(decodeFrom2(kid, Encoding2.UTF8)));
2755
+ const kmsKeyRef = key.meta?.kmsKeyRef ?? key.kid;
2756
+ console.log(`(mdl-mdoc:deviceKey) amend: resolved hardware KMS key kms=${kms}, kmsKeyRef=${kmsKeyRef}`);
2757
+ const updateCborKey = cborKey.copy(false, cborKey.kty, cborKey.kid ?? new CborByteString(decodeFrom(kid, Encoding.UTF8)));
2372
2758
  const deviceKeyInfo = KeyInfo2.Static.fromDTO(keyInfo).copy(kid, updateCborKey, keyInfo.opts, keyInfo.keyVisibility, keyInfo.signatureAlgorithm, keyInfo.x5c, kmsKeyRef, kms);
2373
2759
  const updateMatch = match.copy(match.inputDescriptor, match.document, match.documentError, deviceKeyInfo);
2374
2760
  match = updateMatch;
@@ -2388,9 +2774,74 @@ var MDLMdoc = class {
2388
2774
  }
2389
2775
  return Promise.reject(Error("No matching documents found"));
2390
2776
  }
2391
- const deviceResponse = await oid4vpService.createDeviceResponse(docsAndDescriptors, presentationDefinition, clientId, responseUri, authorizationRequestNonce);
2392
- const vp_token = encodeTo2(deviceResponse.cborEncode(), Encoding2.BASE64URL);
2393
- const presentation_submission = Oid4VPPresentationSubmission.Static.fromPresentationDefinition(presentationDefinition);
2777
+ try {
2778
+ console.log(`(mdl-mdoc:deviceResponse) args: clientId=${clientId}, responseUri=${responseUri}, authorizationRequestNonce=${authorizationRequestNonce}, docCount=${docsAndDescriptors.length}`);
2779
+ try {
2780
+ console.log(`(mdl-mdoc:deviceResponse) presentationDefinition=${JSON.stringify(presentationDefinition)}`);
2781
+ } catch (e) {
2782
+ console.log(`(mdl-mdoc:deviceResponse) presentationDefinition stringify failed: ${e?.message}`);
2783
+ }
2784
+ docsAndDescriptors.forEach((d, idx) => {
2785
+ const dk = d?.deviceKeyInfo;
2786
+ let docType = void 0;
2787
+ try {
2788
+ docType = d?.document?.docType?.value ?? d?.document?.MSO?.value?.docType?.value ?? d?.document?.getDocType?.();
2789
+ } catch {
2790
+ }
2791
+ console.log(`(mdl-mdoc:deviceResponse) doc[${idx}]: inputDescriptor.id=${d?.inputDescriptor?.id?.value ?? d?.inputDescriptor?.id}, docType=${docType}, document present=${!!d?.document}, documentError present=${!!d?.documentError}, deviceKeyInfo present=${!!dk}, deviceKeyInfo.key present=${!!dk?.key}, deviceKeyInfo.kid=${dk?.kid}, kmsKeyRef=${dk?.kmsKeyRef}, kms=${dk?.kms}, signatureAlgorithm=${dk?.signatureAlgorithm}, x5c present=${!!dk?.x5c}`);
2792
+ try {
2793
+ const dkJson = dk?.toJson ? dk.toJson() : dk;
2794
+ console.log(`(mdl-mdoc:deviceResponse) doc[${idx}] deviceKeyInfo=${JSON.stringify(dkJson)}`);
2795
+ } catch (e) {
2796
+ console.log(`(mdl-mdoc:deviceResponse) doc[${idx}] deviceKeyInfo serialize failed: ${e?.message}`);
2797
+ }
2798
+ try {
2799
+ const keyJson = dk?.key?.toJson ? dk.key.toJson() : dk?.key;
2800
+ console.log(`(mdl-mdoc:deviceResponse) doc[${idx}] deviceKeyInfo.key=${JSON.stringify(keyJson)}`);
2801
+ } catch (e) {
2802
+ console.log(`(mdl-mdoc:deviceResponse) doc[${idx}] deviceKeyInfo.key serialize failed: ${e?.message}`);
2803
+ }
2804
+ });
2805
+ } catch (e) {
2806
+ console.log(`(mdl-mdoc:deviceResponse) argument logging failed: ${e?.message}`);
2807
+ }
2808
+ let deviceResponse;
2809
+ try {
2810
+ deviceResponse = await oid4vpService.createDeviceResponse(docsAndDescriptors, presentationDefinition, clientId, responseUri, authorizationRequestNonce);
2811
+ } catch (e) {
2812
+ console.log(`(mdl-mdoc:deviceResponse) createDeviceResponse failed: ${e?.message}`);
2813
+ console.log(`(mdl-mdoc:deviceResponse) STACK: ${e?.stack}`);
2814
+ throw e;
2815
+ }
2816
+ try {
2817
+ console.log(`(mdl-mdoc:deviceResponse) createDeviceResponse returned: present=${!!deviceResponse}, type=${typeof deviceResponse}`);
2818
+ const dr = deviceResponse;
2819
+ try {
2820
+ const docs = dr?.documents ?? dr?.b3p_1 ?? void 0;
2821
+ console.log(`(mdl-mdoc:deviceResponse) deviceResponse.version present=${!!dr?.version}, status present=${dr?.status != null}, documents present=${!!docs}, documentsCount=${docs?.length ?? docs?.size ?? "n/a"}`);
2822
+ } catch (e) {
2823
+ console.log(`(mdl-mdoc:deviceResponse) deviceResponse structure probe failed: ${e?.message}`);
2824
+ }
2825
+ } catch {
2826
+ }
2827
+ let vp_token;
2828
+ try {
2829
+ const encoded = deviceResponse.cborEncode();
2830
+ console.log(`(mdl-mdoc:deviceResponse) cborEncode OK, byteLen=${encoded?.length}`);
2831
+ vp_token = encodeTo(encoded, Encoding.BASE64URL);
2832
+ } catch (e) {
2833
+ console.log(`(mdl-mdoc:deviceResponse) cborEncode failed: ${e?.message}`);
2834
+ console.log(`(mdl-mdoc:deviceResponse) cborEncode STACK: ${e?.stack}`);
2835
+ throw e;
2836
+ }
2837
+ let presentation_submission;
2838
+ try {
2839
+ presentation_submission = Oid4VPPresentationSubmission.Static.fromPresentationDefinition(presentationDefinition);
2840
+ } catch (e) {
2841
+ console.log(`(mdl-mdoc:deviceResponse) fromPresentationDefinition failed: ${e?.message}`);
2842
+ console.log(`(mdl-mdoc:deviceResponse) fromPresentationDefinition STACK: ${e?.stack}`);
2843
+ throw e;
2844
+ }
2394
2845
  return {
2395
2846
  vp_token,
2396
2847
  presentation_submission
@@ -2406,7 +2857,7 @@ var MDLMdoc = class {
2406
2857
  */
2407
2858
  async mdocOid4vpRPVerify(args, _context) {
2408
2859
  const { vp_token, presentation_submission, trustAnchors } = args;
2409
- const deviceResponse = com3.sphereon.mdoc.data.device.DeviceResponseCbor.Static.cborDecode(decodeFrom2(vp_token, Encoding2.BASE64URL));
2860
+ const deviceResponse = com3.sphereon.mdoc.data.device.DeviceResponseCbor.Static.cborDecode(decodeFrom(vp_token, Encoding.BASE64URL));
2410
2861
  if (!deviceResponse.documents) {
2411
2862
  return Promise.reject(Error(`No documents found in vp_token`));
2412
2863
  }
@@ -2492,7 +2943,8 @@ var MDLMdoc = class {
2492
2943
  trustAnchors: Array.from(trustAnchors),
2493
2944
  opts: {
2494
2945
  ...args?.opts,
2495
- ...this.opts
2946
+ ...this.opts,
2947
+ blindlyTrustedAnchors: this.effectiveBlindlyTrustedAnchors
2496
2948
  }
2497
2949
  });
2498
2950
  console.log(`x509 validation for ${validationResult.error ? "Error" : "Success"}. message: ${validationResult.message}, details: ${validationResult.detailMessage}`);
@@ -2526,7 +2978,7 @@ export {
2526
2978
  CoseJoseKeyMappingService2 as CoseJoseKeyMappingService,
2527
2979
  CoseKeyCbor,
2528
2980
  DateTimeUtils2 as DateTimeUtils,
2529
- Encoding2 as Encoding,
2981
+ Encoding,
2530
2982
  Jwk,
2531
2983
  KeyInfo2 as KeyInfo,
2532
2984
  MDLMdoc,
@@ -2534,8 +2986,8 @@ export {
2534
2986
  MdocValidations,
2535
2987
  Oid4VPPresentationSubmission,
2536
2988
  X509CallbackService,
2537
- decodeFrom2 as decodeFrom,
2538
- encodeTo2 as encodeTo,
2989
+ decodeFrom,
2990
+ encodeTo,
2539
2991
  logger,
2540
2992
  mdocSupportMethods,
2541
2993
  schema