@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.cjs +488 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +488 -36
- package/dist/index.js.map +1 -1
- package/package.json +15 -15
- package/src/agent/mDLMdoc.ts +149 -21
- package/src/functions/index.ts +312 -13
package/dist/index.cjs
CHANGED
|
@@ -2076,7 +2076,7 @@ __export(index_exports, {
|
|
|
2076
2076
|
CoseJoseKeyMappingService: () => CoseJoseKeyMappingService2,
|
|
2077
2077
|
CoseKeyCbor: () => CoseKeyCbor,
|
|
2078
2078
|
DateTimeUtils: () => DateTimeUtils2,
|
|
2079
|
-
Encoding: () =>
|
|
2079
|
+
Encoding: () => Encoding,
|
|
2080
2080
|
Jwk: () => Jwk,
|
|
2081
2081
|
KeyInfo: () => KeyInfo2,
|
|
2082
2082
|
MDLMdoc: () => MDLMdoc,
|
|
@@ -2084,8 +2084,8 @@ __export(index_exports, {
|
|
|
2084
2084
|
MdocValidations: () => MdocValidations,
|
|
2085
2085
|
Oid4VPPresentationSubmission: () => Oid4VPPresentationSubmission,
|
|
2086
2086
|
X509CallbackService: () => X509CallbackService,
|
|
2087
|
-
decodeFrom: () =>
|
|
2088
|
-
encodeTo: () =>
|
|
2087
|
+
decodeFrom: () => decodeFrom,
|
|
2088
|
+
encodeTo: () => encodeTo,
|
|
2089
2089
|
logger: () => logger,
|
|
2090
2090
|
mdocSupportMethods: () => mdocSupportMethods,
|
|
2091
2091
|
schema: () => schema
|
|
@@ -2105,15 +2105,315 @@ var import_ssi_sdk_ext2 = require("@sphereon/ssi-sdk-ext.x509-utils");
|
|
|
2105
2105
|
var crypto = __toESM(require("crypto"), 1);
|
|
2106
2106
|
var import_pkijs = require("pkijs");
|
|
2107
2107
|
var import_from_string = require("uint8arrays/from-string");
|
|
2108
|
+
var import_to_string = require("uint8arrays/to-string");
|
|
2108
2109
|
var { com } = import_kmp_mdoc_core.default;
|
|
2109
2110
|
var CoseJoseKeyMappingService = com.sphereon.crypto.CoseJoseKeyMappingService;
|
|
2110
2111
|
var KeyInfo = import_kmp_mdoc_core.default.com.sphereon.crypto.KeyInfo;
|
|
2111
2112
|
var DateTimeUtils = import_kmp_mdoc_core.default.com.sphereon.kmp.DateTimeUtils;
|
|
2112
|
-
var decodeFrom = import_kmp_mdoc_core.default.com.sphereon.kmp.decodeFrom;
|
|
2113
|
-
var encodeTo = import_kmp_mdoc_core.default.com.sphereon.kmp.encodeTo;
|
|
2114
|
-
var Encoding = import_kmp_mdoc_core.default.com.sphereon.kmp.Encoding;
|
|
2115
2113
|
var SignatureAlgorithm = import_kmp_mdoc_core.default.com.sphereon.crypto.generic.SignatureAlgorithm;
|
|
2116
2114
|
var DefaultCallbacks = import_kmp_mdoc_core.default.com.sphereon.crypto.DefaultCallbacks;
|
|
2115
|
+
function toU8(bytes) {
|
|
2116
|
+
if (bytes instanceof Uint8Array) return bytes;
|
|
2117
|
+
if (ArrayBuffer.isView(bytes)) {
|
|
2118
|
+
const v = bytes;
|
|
2119
|
+
return new Uint8Array(v.buffer, v.byteOffset, v.byteLength);
|
|
2120
|
+
}
|
|
2121
|
+
if (Array.isArray(bytes)) return Uint8Array.from(bytes.map((b) => b & 255));
|
|
2122
|
+
throw new Error("unsupported raw bytes type");
|
|
2123
|
+
}
|
|
2124
|
+
__name(toU8, "toU8");
|
|
2125
|
+
function extractIssuerAuthRawParts(rawInput) {
|
|
2126
|
+
const u8 = toU8(rawInput);
|
|
2127
|
+
let pos = 0;
|
|
2128
|
+
const readHead = /* @__PURE__ */ __name(() => {
|
|
2129
|
+
const b = u8[pos++];
|
|
2130
|
+
const mt = b >> 5;
|
|
2131
|
+
const info = b & 31;
|
|
2132
|
+
let len;
|
|
2133
|
+
if (info < 24) len = info;
|
|
2134
|
+
else if (info === 24) {
|
|
2135
|
+
len = u8[pos];
|
|
2136
|
+
pos += 1;
|
|
2137
|
+
} else if (info === 25) {
|
|
2138
|
+
len = u8[pos] << 8 | u8[pos + 1];
|
|
2139
|
+
pos += 2;
|
|
2140
|
+
} else if (info === 26) {
|
|
2141
|
+
len = u8[pos] * 16777216 + (u8[pos + 1] << 16) + (u8[pos + 2] << 8) + u8[pos + 3];
|
|
2142
|
+
pos += 4;
|
|
2143
|
+
} else throw new Error("unsupported cbor length info " + info);
|
|
2144
|
+
return {
|
|
2145
|
+
mt,
|
|
2146
|
+
len
|
|
2147
|
+
};
|
|
2148
|
+
}, "readHead");
|
|
2149
|
+
const skip = /* @__PURE__ */ __name(() => {
|
|
2150
|
+
const h = readHead();
|
|
2151
|
+
switch (h.mt) {
|
|
2152
|
+
case 0:
|
|
2153
|
+
case 1:
|
|
2154
|
+
case 7:
|
|
2155
|
+
return;
|
|
2156
|
+
case 2:
|
|
2157
|
+
case 3:
|
|
2158
|
+
pos += h.len;
|
|
2159
|
+
return;
|
|
2160
|
+
case 4:
|
|
2161
|
+
for (let i = 0; i < h.len; i++) skip();
|
|
2162
|
+
return;
|
|
2163
|
+
case 5:
|
|
2164
|
+
for (let i = 0; i < h.len * 2; i++) skip();
|
|
2165
|
+
return;
|
|
2166
|
+
case 6:
|
|
2167
|
+
skip();
|
|
2168
|
+
return;
|
|
2169
|
+
}
|
|
2170
|
+
}, "skip");
|
|
2171
|
+
const readBstr = /* @__PURE__ */ __name(() => {
|
|
2172
|
+
const h = readHead();
|
|
2173
|
+
if (h.mt !== 2) throw new Error("expected bstr, got mt " + h.mt);
|
|
2174
|
+
const out = u8.slice(pos, pos + h.len);
|
|
2175
|
+
pos += h.len;
|
|
2176
|
+
return out;
|
|
2177
|
+
}, "readBstr");
|
|
2178
|
+
const readTstr = /* @__PURE__ */ __name(() => {
|
|
2179
|
+
const h = readHead();
|
|
2180
|
+
if (h.mt !== 3) throw new Error("expected tstr, got mt " + h.mt);
|
|
2181
|
+
const out = new TextDecoder().decode(u8.slice(pos, pos + h.len));
|
|
2182
|
+
pos += h.len;
|
|
2183
|
+
return out;
|
|
2184
|
+
}, "readTstr");
|
|
2185
|
+
const outer = readHead();
|
|
2186
|
+
if (outer.mt !== 5) return void 0;
|
|
2187
|
+
for (let i = 0; i < outer.len; i++) {
|
|
2188
|
+
const key = readTstr();
|
|
2189
|
+
if (key === "issuerAuth") {
|
|
2190
|
+
const arr = readHead();
|
|
2191
|
+
if (arr.mt !== 4 || arr.len !== 4) throw new Error("issuerAuth is not a 4-element array");
|
|
2192
|
+
const protectedBytes = readBstr();
|
|
2193
|
+
skip();
|
|
2194
|
+
const payloadBytes = readBstr();
|
|
2195
|
+
return {
|
|
2196
|
+
protectedBytes,
|
|
2197
|
+
payloadBytes
|
|
2198
|
+
};
|
|
2199
|
+
}
|
|
2200
|
+
skip();
|
|
2201
|
+
}
|
|
2202
|
+
return void 0;
|
|
2203
|
+
}
|
|
2204
|
+
__name(extractIssuerAuthRawParts, "extractIssuerAuthRawParts");
|
|
2205
|
+
function encodeBstrHeader(len) {
|
|
2206
|
+
if (len < 24) return new Uint8Array([
|
|
2207
|
+
64 | len
|
|
2208
|
+
]);
|
|
2209
|
+
if (len < 256) return new Uint8Array([
|
|
2210
|
+
88,
|
|
2211
|
+
len
|
|
2212
|
+
]);
|
|
2213
|
+
if (len < 65536) return new Uint8Array([
|
|
2214
|
+
89,
|
|
2215
|
+
len >> 8 & 255,
|
|
2216
|
+
len & 255
|
|
2217
|
+
]);
|
|
2218
|
+
return new Uint8Array([
|
|
2219
|
+
90,
|
|
2220
|
+
len >>> 24 & 255,
|
|
2221
|
+
len >> 16 & 255,
|
|
2222
|
+
len >> 8 & 255,
|
|
2223
|
+
len & 255
|
|
2224
|
+
]);
|
|
2225
|
+
}
|
|
2226
|
+
__name(encodeBstrHeader, "encodeBstrHeader");
|
|
2227
|
+
function concatU8(parts) {
|
|
2228
|
+
let total = 0;
|
|
2229
|
+
for (const p of parts) total += p.length;
|
|
2230
|
+
const out = new Uint8Array(total);
|
|
2231
|
+
let off = 0;
|
|
2232
|
+
for (const p of parts) {
|
|
2233
|
+
out.set(p, off);
|
|
2234
|
+
off += p.length;
|
|
2235
|
+
}
|
|
2236
|
+
return out;
|
|
2237
|
+
}
|
|
2238
|
+
__name(concatU8, "concatU8");
|
|
2239
|
+
function buildSig1Structure(protectedBytes, payloadBytes) {
|
|
2240
|
+
const sig1Label = new Uint8Array([
|
|
2241
|
+
106,
|
|
2242
|
+
83,
|
|
2243
|
+
105,
|
|
2244
|
+
103,
|
|
2245
|
+
110,
|
|
2246
|
+
97,
|
|
2247
|
+
116,
|
|
2248
|
+
117,
|
|
2249
|
+
114,
|
|
2250
|
+
101,
|
|
2251
|
+
49
|
|
2252
|
+
]);
|
|
2253
|
+
return concatU8([
|
|
2254
|
+
new Uint8Array([
|
|
2255
|
+
132
|
|
2256
|
+
]),
|
|
2257
|
+
sig1Label,
|
|
2258
|
+
encodeBstrHeader(protectedBytes.length),
|
|
2259
|
+
protectedBytes,
|
|
2260
|
+
new Uint8Array([
|
|
2261
|
+
64
|
|
2262
|
+
]),
|
|
2263
|
+
encodeBstrHeader(payloadBytes.length),
|
|
2264
|
+
payloadBytes
|
|
2265
|
+
]);
|
|
2266
|
+
}
|
|
2267
|
+
__name(buildSig1Structure, "buildSig1Structure");
|
|
2268
|
+
function derEcdsaToRaw(der, coordSize) {
|
|
2269
|
+
let offset = 0;
|
|
2270
|
+
if (der[offset++] !== 48) throw new Error("Invalid DER ECDSA signature: missing SEQUENCE tag");
|
|
2271
|
+
let seqLen = der[offset++];
|
|
2272
|
+
if (seqLen & 128) {
|
|
2273
|
+
const numBytes = seqLen & 127;
|
|
2274
|
+
seqLen = 0;
|
|
2275
|
+
for (let i = 0; i < numBytes; i++) seqLen = seqLen << 8 | der[offset++];
|
|
2276
|
+
}
|
|
2277
|
+
const readInt = /* @__PURE__ */ __name(() => {
|
|
2278
|
+
if (der[offset++] !== 2) throw new Error("Invalid DER ECDSA signature: missing INTEGER tag");
|
|
2279
|
+
const len = der[offset++];
|
|
2280
|
+
let val = der.slice(offset, offset + len);
|
|
2281
|
+
offset += len;
|
|
2282
|
+
let start = 0;
|
|
2283
|
+
while (start < val.length - 1 && val[start] === 0) start++;
|
|
2284
|
+
val = val.slice(start);
|
|
2285
|
+
if (val.length > coordSize) throw new Error(`Invalid DER ECDSA signature: integer (${val.length}) exceeds ${coordSize}`);
|
|
2286
|
+
const out = new Uint8Array(coordSize);
|
|
2287
|
+
out.set(val, coordSize - val.length);
|
|
2288
|
+
return out;
|
|
2289
|
+
}, "readInt");
|
|
2290
|
+
const r = readInt();
|
|
2291
|
+
const s = readInt();
|
|
2292
|
+
return concatU8([
|
|
2293
|
+
r,
|
|
2294
|
+
s
|
|
2295
|
+
]);
|
|
2296
|
+
}
|
|
2297
|
+
__name(derEcdsaToRaw, "derEcdsaToRaw");
|
|
2298
|
+
function decodeKmsSignatureToRaw(signature, coordSize) {
|
|
2299
|
+
const normalized = signature.trim().replace(/\s+/g, "").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
2300
|
+
const bytes = (0, import_from_string.fromString)(normalized, "base64url");
|
|
2301
|
+
if (bytes.length > coordSize * 2 && bytes[0] === 48) {
|
|
2302
|
+
return derEcdsaToRaw(bytes, coordSize);
|
|
2303
|
+
}
|
|
2304
|
+
return bytes;
|
|
2305
|
+
}
|
|
2306
|
+
__name(decodeKmsSignatureToRaw, "decodeKmsSignatureToRaw");
|
|
2307
|
+
function cborHeader(buf, off) {
|
|
2308
|
+
const ib = buf[off];
|
|
2309
|
+
const major = ib >> 5;
|
|
2310
|
+
const ai = ib & 31;
|
|
2311
|
+
if (ai < 24) return {
|
|
2312
|
+
major,
|
|
2313
|
+
headerLen: 1,
|
|
2314
|
+
argument: ai
|
|
2315
|
+
};
|
|
2316
|
+
if (ai === 24) return {
|
|
2317
|
+
major,
|
|
2318
|
+
headerLen: 2,
|
|
2319
|
+
argument: buf[off + 1]
|
|
2320
|
+
};
|
|
2321
|
+
if (ai === 25) return {
|
|
2322
|
+
major,
|
|
2323
|
+
headerLen: 3,
|
|
2324
|
+
argument: buf[off + 1] << 8 | buf[off + 2]
|
|
2325
|
+
};
|
|
2326
|
+
if (ai === 26) return {
|
|
2327
|
+
major,
|
|
2328
|
+
headerLen: 5,
|
|
2329
|
+
argument: buf[off + 1] * 16777216 + (buf[off + 2] << 16) + (buf[off + 3] << 8) + buf[off + 4]
|
|
2330
|
+
};
|
|
2331
|
+
if (ai === 27) {
|
|
2332
|
+
let v = 0;
|
|
2333
|
+
for (let i = 1; i <= 8; i++) v = v * 256 + buf[off + i];
|
|
2334
|
+
return {
|
|
2335
|
+
major,
|
|
2336
|
+
headerLen: 9,
|
|
2337
|
+
argument: v
|
|
2338
|
+
};
|
|
2339
|
+
}
|
|
2340
|
+
throw new Error(`unsupported CBOR additional-info ${ai} at offset ${off}`);
|
|
2341
|
+
}
|
|
2342
|
+
__name(cborHeader, "cborHeader");
|
|
2343
|
+
function cborItemLen(buf, off) {
|
|
2344
|
+
const h = cborHeader(buf, off);
|
|
2345
|
+
let total = h.headerLen;
|
|
2346
|
+
switch (h.major) {
|
|
2347
|
+
case 0:
|
|
2348
|
+
case 1:
|
|
2349
|
+
case 7:
|
|
2350
|
+
break;
|
|
2351
|
+
case 2:
|
|
2352
|
+
case 3:
|
|
2353
|
+
total += h.argument;
|
|
2354
|
+
break;
|
|
2355
|
+
case 4:
|
|
2356
|
+
for (let i = 0; i < h.argument; i++) total += cborItemLen(buf, off + total);
|
|
2357
|
+
break;
|
|
2358
|
+
case 5:
|
|
2359
|
+
for (let i = 0; i < h.argument * 2; i++) total += cborItemLen(buf, off + total);
|
|
2360
|
+
break;
|
|
2361
|
+
case 6:
|
|
2362
|
+
total += cborItemLen(buf, off + total);
|
|
2363
|
+
break;
|
|
2364
|
+
default:
|
|
2365
|
+
throw new Error(`unsupported CBOR major type ${h.major}`);
|
|
2366
|
+
}
|
|
2367
|
+
return total;
|
|
2368
|
+
}
|
|
2369
|
+
__name(cborItemLen, "cborItemLen");
|
|
2370
|
+
function reconstructMdocDeviceAuthSigStructure(sig) {
|
|
2371
|
+
if (sig[0] !== 132) return sig;
|
|
2372
|
+
let off = 1;
|
|
2373
|
+
off += cborItemLen(sig, off);
|
|
2374
|
+
off += cborItemLen(sig, off);
|
|
2375
|
+
off += cborItemLen(sig, off);
|
|
2376
|
+
const payloadStart = off;
|
|
2377
|
+
const ph = cborHeader(sig, payloadStart);
|
|
2378
|
+
if (ph.major !== 2) return sig;
|
|
2379
|
+
const daStart = payloadStart + ph.headerLen;
|
|
2380
|
+
const da = sig.subarray(daStart, daStart + ph.argument);
|
|
2381
|
+
if (da[0] !== 132) return sig;
|
|
2382
|
+
let d = 1;
|
|
2383
|
+
d += cborItemLen(da, d);
|
|
2384
|
+
d += cborItemLen(da, d);
|
|
2385
|
+
d += cborItemLen(da, d);
|
|
2386
|
+
const e4 = da.subarray(d, d + cborItemLen(da, d));
|
|
2387
|
+
const e4Tagged = concatU8([
|
|
2388
|
+
new Uint8Array([
|
|
2389
|
+
216,
|
|
2390
|
+
24
|
|
2391
|
+
]),
|
|
2392
|
+
encodeBstrHeader(e4.length),
|
|
2393
|
+
e4
|
|
2394
|
+
]);
|
|
2395
|
+
const daCorrected = concatU8([
|
|
2396
|
+
da.subarray(0, d),
|
|
2397
|
+
e4Tagged
|
|
2398
|
+
]);
|
|
2399
|
+
const deviceAuthBytes = concatU8([
|
|
2400
|
+
new Uint8Array([
|
|
2401
|
+
216,
|
|
2402
|
+
24
|
|
2403
|
+
]),
|
|
2404
|
+
encodeBstrHeader(daCorrected.length),
|
|
2405
|
+
daCorrected
|
|
2406
|
+
]);
|
|
2407
|
+
const newPayload = concatU8([
|
|
2408
|
+
encodeBstrHeader(deviceAuthBytes.length),
|
|
2409
|
+
deviceAuthBytes
|
|
2410
|
+
]);
|
|
2411
|
+
return concatU8([
|
|
2412
|
+
sig.subarray(0, payloadStart),
|
|
2413
|
+
newPayload
|
|
2414
|
+
]);
|
|
2415
|
+
}
|
|
2416
|
+
__name(reconstructMdocDeviceAuthSigStructure, "reconstructMdocDeviceAuthSigStructure");
|
|
2117
2417
|
var CoseCryptoService = class {
|
|
2118
2418
|
static {
|
|
2119
2419
|
__name(this, "CoseCryptoService");
|
|
@@ -2130,7 +2430,21 @@ var CoseCryptoService = class {
|
|
|
2130
2430
|
throw Error("No context provided. Please provide a context with the setContext method or constructor");
|
|
2131
2431
|
}
|
|
2132
2432
|
const { keyInfo, alg, value } = input;
|
|
2433
|
+
let toBeSigned = toU8(value);
|
|
2434
|
+
try {
|
|
2435
|
+
toBeSigned = reconstructMdocDeviceAuthSigStructure(toBeSigned);
|
|
2436
|
+
} catch (e) {
|
|
2437
|
+
console.log(`(mdl-mdoc:sign) Sig_structure tag-24 reconstruction failed, signing kmp original: ${e?.message}`);
|
|
2438
|
+
}
|
|
2439
|
+
try {
|
|
2440
|
+
let hex = "";
|
|
2441
|
+
for (let i = 0; i < toBeSigned.length; i++) hex += (toBeSigned[i] & 255).toString(16).padStart(2, "0");
|
|
2442
|
+
console.log(`(mdl-mdoc:sign) ToBeSigned len=${toBeSigned.length} hex=${hex}`);
|
|
2443
|
+
} catch (e) {
|
|
2444
|
+
console.log(`(mdl-mdoc:sign) ToBeSigned hex failed: ${e?.message}`);
|
|
2445
|
+
}
|
|
2133
2446
|
let kmsKeyRef = keyInfo.kmsKeyRef ?? void 0;
|
|
2447
|
+
const fallbackKeyRefs = [];
|
|
2134
2448
|
if (!kmsKeyRef) {
|
|
2135
2449
|
const key = keyInfo.key;
|
|
2136
2450
|
if (key == null) {
|
|
@@ -2138,21 +2452,49 @@ var CoseCryptoService = class {
|
|
|
2138
2452
|
}
|
|
2139
2453
|
const resolvedKeyInfo = com.sphereon.crypto.ResolvedKeyInfo.Static.fromKeyInfo(keyInfo, key);
|
|
2140
2454
|
const jwkKeyInfo = CoseJoseKeyMappingService.toResolvedJwkKeyInfo(resolvedKeyInfo);
|
|
2141
|
-
const
|
|
2455
|
+
const thumbprint = (0, import_ssi_sdk_ext.calculateJwkThumbprint)({
|
|
2142
2456
|
jwk: jwkKeyInfo.key.toJsonDTO()
|
|
2143
|
-
})
|
|
2457
|
+
});
|
|
2458
|
+
const kid = jwkKeyInfo.kid ?? thumbprint ?? jwkKeyInfo.key.getKidAsString(true);
|
|
2144
2459
|
if (!kid) {
|
|
2145
2460
|
return Promise.reject(Error("No kid present and not kmsKeyRef provided"));
|
|
2146
2461
|
}
|
|
2147
2462
|
kmsKeyRef = kid;
|
|
2463
|
+
if (thumbprint && thumbprint !== kid) {
|
|
2464
|
+
fallbackKeyRefs.push(thumbprint);
|
|
2465
|
+
}
|
|
2148
2466
|
}
|
|
2149
|
-
const
|
|
2467
|
+
const doSign = /* @__PURE__ */ __name((keyRef) => this.context.agent.keyManagerSign({
|
|
2150
2468
|
algorithm: alg.jose.value,
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2469
|
+
// Pass the raw ToBeSigned (COSE Sig_structure) bytes as base64. The previous `encodeTo(value, UTF8)`
|
|
2470
|
+
// interpreted the binary CBOR as UTF-8 text, corrupting every non-ASCII byte before the KMS even saw it
|
|
2471
|
+
// (the MUSAP bridge then signed the mangled bytes -> verifier "Signature invalid"). base64 round-trips losslessly.
|
|
2472
|
+
data: (0, import_to_string.toString)(toBeSigned, "base64"),
|
|
2473
|
+
encoding: "base64",
|
|
2474
|
+
keyRef
|
|
2475
|
+
}), "doSign");
|
|
2476
|
+
let result;
|
|
2477
|
+
try {
|
|
2478
|
+
result = await doSign(kmsKeyRef);
|
|
2479
|
+
} catch (error) {
|
|
2480
|
+
let signed;
|
|
2481
|
+
for (const ref of fallbackKeyRefs) {
|
|
2482
|
+
try {
|
|
2483
|
+
signed = await doSign(ref);
|
|
2484
|
+
break;
|
|
2485
|
+
} catch {
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
if (signed === void 0) {
|
|
2489
|
+
throw error;
|
|
2490
|
+
}
|
|
2491
|
+
result = signed;
|
|
2492
|
+
}
|
|
2493
|
+
const joseAlg = alg.jose?.value;
|
|
2494
|
+
const coordSize = joseAlg === "ES512" ? 66 : joseAlg === "ES384" ? 48 : 32;
|
|
2495
|
+
const raw = decodeKmsSignatureToRaw(result, coordSize);
|
|
2496
|
+
console.log(`(mdl-mdoc:sign) signature decoded: alg=${joseAlg}, inputChars=${result.length}, rawLen=${raw.length} (expected ${coordSize * 2})`);
|
|
2497
|
+
return Int8Array.from(raw);
|
|
2156
2498
|
}
|
|
2157
2499
|
async verify1Async(input, keyInfo, requireX5Chain) {
|
|
2158
2500
|
const getCertAndKey = /* @__PURE__ */ __name(async (x5c2) => {
|
|
@@ -2202,9 +2544,22 @@ var CoseCryptoService = class {
|
|
|
2202
2544
|
const issuerCoseKeyInfo = new KeyInfo(kid, issuerCoseKey, coseKeyInfo.opts, coseKeyInfo.keyVisibility, issuerCoseKey.getSignatureAlgorithm() ?? coseKeyInfo.signatureAlgorithm, x5c, coseKeyInfo.kmsKeyRef, coseKeyInfo.kms, coseKeyInfo.keyType ?? issuerCoseKey.getKty());
|
|
2203
2545
|
const recalculatedToBeSigned = input.toBeSignedJson(issuerCoseKeyInfo, SignatureAlgorithm.Static.fromCose(coseAlg));
|
|
2204
2546
|
const key = CoseJoseKeyMappingService.toJoseJwk(issuerCoseKeyInfo.key).toJsonDTO();
|
|
2547
|
+
let data = (0, import_from_string.fromString)(recalculatedToBeSigned.base64UrlValue, "base64url");
|
|
2548
|
+
const signatureBytes = (0, import_from_string.fromString)(sign1Json.signature, "base64url");
|
|
2549
|
+
const rawMdocBytes = globalThis.__sphereon_mdoc_raw_bytes;
|
|
2550
|
+
if (rawMdocBytes) {
|
|
2551
|
+
try {
|
|
2552
|
+
const extracted = extractIssuerAuthRawParts(rawMdocBytes);
|
|
2553
|
+
if (extracted) {
|
|
2554
|
+
data = buildSig1Structure(extracted.protectedBytes, extracted.payloadBytes);
|
|
2555
|
+
}
|
|
2556
|
+
} catch (e) {
|
|
2557
|
+
console.warn("[mdl-mdoc verify] failed to reparse raw mdoc; falling back to kmp-computed Sig_structure:", e.message);
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2205
2560
|
const valid = await (0, import_ssi_sdk_ext.verifyRawSignature)({
|
|
2206
|
-
data
|
|
2207
|
-
signature:
|
|
2561
|
+
data,
|
|
2562
|
+
signature: signatureBytes,
|
|
2208
2563
|
key
|
|
2209
2564
|
});
|
|
2210
2565
|
return {
|
|
@@ -2325,9 +2680,9 @@ var CoseCryptoServiceJS = com2.sphereon.crypto.CoseCryptoServiceJS;
|
|
|
2325
2680
|
var CoseJoseKeyMappingService2 = com2.sphereon.crypto.CoseJoseKeyMappingService;
|
|
2326
2681
|
var KeyInfo2 = com2.sphereon.crypto.KeyInfo;
|
|
2327
2682
|
var DateTimeUtils2 = com2.sphereon.kmp.DateTimeUtils;
|
|
2328
|
-
var
|
|
2329
|
-
var
|
|
2330
|
-
var
|
|
2683
|
+
var decodeFrom = com2.sphereon.kmp.decodeFrom;
|
|
2684
|
+
var encodeTo = com2.sphereon.kmp.encodeTo;
|
|
2685
|
+
var Encoding = com2.sphereon.kmp.Encoding;
|
|
2331
2686
|
var MdocValidations = com2.sphereon.mdoc.data.MdocValidations;
|
|
2332
2687
|
var MdocOid4vpService = com2.sphereon.mdoc.oid4vp.MdocOid4vpServiceJs;
|
|
2333
2688
|
var Jwk = com2.sphereon.crypto.jose.Jwk;
|
|
@@ -2354,14 +2709,31 @@ var MDLMdoc = class {
|
|
|
2354
2709
|
mdocOid4vpHolderPresent: this.mdocOid4vpHolderPresent.bind(this),
|
|
2355
2710
|
mdocOid4vpRPVerify: this.mdocOid4vpRPVerify.bind(this)
|
|
2356
2711
|
};
|
|
2357
|
-
|
|
2712
|
+
staticTrustAnchors;
|
|
2713
|
+
trustAnchorProvider;
|
|
2714
|
+
blindlyTrustedAnchorProvider;
|
|
2358
2715
|
opts;
|
|
2359
2716
|
constructor(args) {
|
|
2360
|
-
this.
|
|
2717
|
+
this.staticTrustAnchors = args?.trustAnchors ?? [];
|
|
2718
|
+
this.trustAnchorProvider = args?.trustAnchorProvider;
|
|
2719
|
+
this.blindlyTrustedAnchorProvider = args?.blindlyTrustedAnchorProvider;
|
|
2361
2720
|
this.opts = args?.opts ?? {
|
|
2362
2721
|
trustRootWhenNoAnchors: true
|
|
2363
2722
|
};
|
|
2364
2723
|
}
|
|
2724
|
+
// Live-merged anchors: static (constructor) + provider (runtime/user). Read on every verification.
|
|
2725
|
+
get trustAnchors() {
|
|
2726
|
+
return [
|
|
2727
|
+
...this.staticTrustAnchors,
|
|
2728
|
+
...this.trustAnchorProvider?.() ?? []
|
|
2729
|
+
];
|
|
2730
|
+
}
|
|
2731
|
+
get effectiveBlindlyTrustedAnchors() {
|
|
2732
|
+
return [
|
|
2733
|
+
...this.opts.blindlyTrustedAnchors ?? [],
|
|
2734
|
+
...this.blindlyTrustedAnchorProvider?.() ?? []
|
|
2735
|
+
];
|
|
2736
|
+
}
|
|
2365
2737
|
/**
|
|
2366
2738
|
* Processes and verifies the provided mdoc, generates device response and presentation submission tokens.
|
|
2367
2739
|
*
|
|
@@ -2402,22 +2774,36 @@ var MDLMdoc = class {
|
|
|
2402
2774
|
const result = await validate(match.document);
|
|
2403
2775
|
if (!result.error || responseUri.includes("openid.net")) {
|
|
2404
2776
|
try {
|
|
2405
|
-
const
|
|
2777
|
+
const matchDeviceKeyInfo = match.deviceKeyInfo;
|
|
2778
|
+
const deviceKeyInfoSource = matchDeviceKeyInfo ?? result.keyInfo;
|
|
2779
|
+
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"}`);
|
|
2780
|
+
const cborKey = deviceKeyInfoSource?.key ? CoseKeyCbor.Static.fromDTO(deviceKeyInfoSource.key) : void 0;
|
|
2406
2781
|
if (!cborKey) {
|
|
2407
|
-
throw Error("No key found
|
|
2782
|
+
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.");
|
|
2408
2783
|
}
|
|
2409
2784
|
let jwk = CoseJoseKeyMappingService2.toJoseJwk(cborKey).toJsonDTO();
|
|
2410
|
-
if (!
|
|
2411
|
-
const keyInfo =
|
|
2412
|
-
const
|
|
2785
|
+
if (!deviceKeyInfoSource?.kmsKeyRef) {
|
|
2786
|
+
const keyInfo = deviceKeyInfoSource;
|
|
2787
|
+
const thumbprint = (0, import_ssi_sdk_ext3.calculateJwkThumbprint)({
|
|
2413
2788
|
jwk
|
|
2414
2789
|
});
|
|
2415
|
-
const
|
|
2416
|
-
|
|
2417
|
-
|
|
2790
|
+
const kid = jwk.kid ?? thumbprint;
|
|
2791
|
+
console.log(`(mdl-mdoc:deviceKey) amend: resolved device public jwk kid=${jwk.kid}, thumbprint=${thumbprint}`);
|
|
2792
|
+
let key;
|
|
2793
|
+
try {
|
|
2794
|
+
key = await _context.agent.keyManagerGet({
|
|
2795
|
+
kid
|
|
2796
|
+
});
|
|
2797
|
+
} catch (e) {
|
|
2798
|
+
console.log(`(mdl-mdoc:deviceKey) amend: keyManagerGet by kid '${kid}' failed (${e?.message}); retrying by thumbprint '${thumbprint}'`);
|
|
2799
|
+
key = await _context.agent.keyManagerGet({
|
|
2800
|
+
kid: thumbprint
|
|
2801
|
+
});
|
|
2802
|
+
}
|
|
2418
2803
|
const kms = key.kms;
|
|
2419
|
-
const kmsKeyRef = key.meta?.kmsKeyRef;
|
|
2420
|
-
|
|
2804
|
+
const kmsKeyRef = key.meta?.kmsKeyRef ?? key.kid;
|
|
2805
|
+
console.log(`(mdl-mdoc:deviceKey) amend: resolved hardware KMS key kms=${kms}, kmsKeyRef=${kmsKeyRef}`);
|
|
2806
|
+
const updateCborKey = cborKey.copy(false, cborKey.kty, cborKey.kid ?? new CborByteString(decodeFrom(kid, Encoding.UTF8)));
|
|
2421
2807
|
const deviceKeyInfo = KeyInfo2.Static.fromDTO(keyInfo).copy(kid, updateCborKey, keyInfo.opts, keyInfo.keyVisibility, keyInfo.signatureAlgorithm, keyInfo.x5c, kmsKeyRef, kms);
|
|
2422
2808
|
const updateMatch = match.copy(match.inputDescriptor, match.document, match.documentError, deviceKeyInfo);
|
|
2423
2809
|
match = updateMatch;
|
|
@@ -2437,9 +2823,74 @@ var MDLMdoc = class {
|
|
|
2437
2823
|
}
|
|
2438
2824
|
return Promise.reject(Error("No matching documents found"));
|
|
2439
2825
|
}
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2826
|
+
try {
|
|
2827
|
+
console.log(`(mdl-mdoc:deviceResponse) args: clientId=${clientId}, responseUri=${responseUri}, authorizationRequestNonce=${authorizationRequestNonce}, docCount=${docsAndDescriptors.length}`);
|
|
2828
|
+
try {
|
|
2829
|
+
console.log(`(mdl-mdoc:deviceResponse) presentationDefinition=${JSON.stringify(presentationDefinition)}`);
|
|
2830
|
+
} catch (e) {
|
|
2831
|
+
console.log(`(mdl-mdoc:deviceResponse) presentationDefinition stringify failed: ${e?.message}`);
|
|
2832
|
+
}
|
|
2833
|
+
docsAndDescriptors.forEach((d, idx) => {
|
|
2834
|
+
const dk = d?.deviceKeyInfo;
|
|
2835
|
+
let docType = void 0;
|
|
2836
|
+
try {
|
|
2837
|
+
docType = d?.document?.docType?.value ?? d?.document?.MSO?.value?.docType?.value ?? d?.document?.getDocType?.();
|
|
2838
|
+
} catch {
|
|
2839
|
+
}
|
|
2840
|
+
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}`);
|
|
2841
|
+
try {
|
|
2842
|
+
const dkJson = dk?.toJson ? dk.toJson() : dk;
|
|
2843
|
+
console.log(`(mdl-mdoc:deviceResponse) doc[${idx}] deviceKeyInfo=${JSON.stringify(dkJson)}`);
|
|
2844
|
+
} catch (e) {
|
|
2845
|
+
console.log(`(mdl-mdoc:deviceResponse) doc[${idx}] deviceKeyInfo serialize failed: ${e?.message}`);
|
|
2846
|
+
}
|
|
2847
|
+
try {
|
|
2848
|
+
const keyJson = dk?.key?.toJson ? dk.key.toJson() : dk?.key;
|
|
2849
|
+
console.log(`(mdl-mdoc:deviceResponse) doc[${idx}] deviceKeyInfo.key=${JSON.stringify(keyJson)}`);
|
|
2850
|
+
} catch (e) {
|
|
2851
|
+
console.log(`(mdl-mdoc:deviceResponse) doc[${idx}] deviceKeyInfo.key serialize failed: ${e?.message}`);
|
|
2852
|
+
}
|
|
2853
|
+
});
|
|
2854
|
+
} catch (e) {
|
|
2855
|
+
console.log(`(mdl-mdoc:deviceResponse) argument logging failed: ${e?.message}`);
|
|
2856
|
+
}
|
|
2857
|
+
let deviceResponse;
|
|
2858
|
+
try {
|
|
2859
|
+
deviceResponse = await oid4vpService.createDeviceResponse(docsAndDescriptors, presentationDefinition, clientId, responseUri, authorizationRequestNonce);
|
|
2860
|
+
} catch (e) {
|
|
2861
|
+
console.log(`(mdl-mdoc:deviceResponse) createDeviceResponse failed: ${e?.message}`);
|
|
2862
|
+
console.log(`(mdl-mdoc:deviceResponse) STACK: ${e?.stack}`);
|
|
2863
|
+
throw e;
|
|
2864
|
+
}
|
|
2865
|
+
try {
|
|
2866
|
+
console.log(`(mdl-mdoc:deviceResponse) createDeviceResponse returned: present=${!!deviceResponse}, type=${typeof deviceResponse}`);
|
|
2867
|
+
const dr = deviceResponse;
|
|
2868
|
+
try {
|
|
2869
|
+
const docs = dr?.documents ?? dr?.b3p_1 ?? void 0;
|
|
2870
|
+
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"}`);
|
|
2871
|
+
} catch (e) {
|
|
2872
|
+
console.log(`(mdl-mdoc:deviceResponse) deviceResponse structure probe failed: ${e?.message}`);
|
|
2873
|
+
}
|
|
2874
|
+
} catch {
|
|
2875
|
+
}
|
|
2876
|
+
let vp_token;
|
|
2877
|
+
try {
|
|
2878
|
+
const encoded = deviceResponse.cborEncode();
|
|
2879
|
+
console.log(`(mdl-mdoc:deviceResponse) cborEncode OK, byteLen=${encoded?.length}`);
|
|
2880
|
+
vp_token = encodeTo(encoded, Encoding.BASE64URL);
|
|
2881
|
+
} catch (e) {
|
|
2882
|
+
console.log(`(mdl-mdoc:deviceResponse) cborEncode failed: ${e?.message}`);
|
|
2883
|
+
console.log(`(mdl-mdoc:deviceResponse) cborEncode STACK: ${e?.stack}`);
|
|
2884
|
+
throw e;
|
|
2885
|
+
}
|
|
2886
|
+
let presentation_submission;
|
|
2887
|
+
try {
|
|
2888
|
+
presentation_submission = Oid4VPPresentationSubmission.Static.fromPresentationDefinition(presentationDefinition);
|
|
2889
|
+
} catch (e) {
|
|
2890
|
+
console.log(`(mdl-mdoc:deviceResponse) fromPresentationDefinition failed: ${e?.message}`);
|
|
2891
|
+
console.log(`(mdl-mdoc:deviceResponse) fromPresentationDefinition STACK: ${e?.stack}`);
|
|
2892
|
+
throw e;
|
|
2893
|
+
}
|
|
2443
2894
|
return {
|
|
2444
2895
|
vp_token,
|
|
2445
2896
|
presentation_submission
|
|
@@ -2455,7 +2906,7 @@ var MDLMdoc = class {
|
|
|
2455
2906
|
*/
|
|
2456
2907
|
async mdocOid4vpRPVerify(args, _context) {
|
|
2457
2908
|
const { vp_token, presentation_submission, trustAnchors } = args;
|
|
2458
|
-
const deviceResponse = com3.sphereon.mdoc.data.device.DeviceResponseCbor.Static.cborDecode(
|
|
2909
|
+
const deviceResponse = com3.sphereon.mdoc.data.device.DeviceResponseCbor.Static.cborDecode(decodeFrom(vp_token, Encoding.BASE64URL));
|
|
2459
2910
|
if (!deviceResponse.documents) {
|
|
2460
2911
|
return Promise.reject(Error(`No documents found in vp_token`));
|
|
2461
2912
|
}
|
|
@@ -2541,7 +2992,8 @@ var MDLMdoc = class {
|
|
|
2541
2992
|
trustAnchors: Array.from(trustAnchors),
|
|
2542
2993
|
opts: {
|
|
2543
2994
|
...args?.opts,
|
|
2544
|
-
...this.opts
|
|
2995
|
+
...this.opts,
|
|
2996
|
+
blindlyTrustedAnchors: this.effectiveBlindlyTrustedAnchors
|
|
2545
2997
|
}
|
|
2546
2998
|
});
|
|
2547
2999
|
console.log(`x509 validation for ${validationResult.error ? "Error" : "Success"}. message: ${validationResult.message}, details: ${validationResult.detailMessage}`);
|