@awiki/anp-typescript-sdk 0.2.0 → 0.9.3

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 CHANGED
@@ -7,6 +7,8 @@ var net = require('net');
7
7
  var canonicalize = require('canonicalize');
8
8
  var promises = require('fs/promises');
9
9
  var jose = require('jose');
10
+ var p256 = require('@noble/curves/p256');
11
+ var secp256k1 = require('@noble/curves/secp256k1');
10
12
  var path = require('path');
11
13
 
12
14
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -46,6 +48,13 @@ var ProofError = class extends ANPError {
46
48
  this.name = "ProofError";
47
49
  }
48
50
  };
51
+ var DeviceManifestError = class extends AuthenticationError {
52
+ constructor(message, cause) {
53
+ super(message, cause);
54
+ this.name = "DeviceManifestError";
55
+ Object.defineProperty(this, "code", { value: "DEVICE_MANIFEST_ERROR" });
56
+ }
57
+ };
49
58
  var NetworkError = class extends ANPError {
50
59
  constructor(message, statusCode, cause) {
51
60
  super(message, "NETWORK_ERROR", cause);
@@ -2063,6 +2072,750 @@ function selectAnpMessageService(didDocument, serviceId, serviceEndpoint) {
2063
2072
  );
2064
2073
  }
2065
2074
 
2075
+ // src/authentication/device-manifest.ts
2076
+ var device_manifest_exports = {};
2077
+ __export(device_manifest_exports, {
2078
+ DEVICE_MANIFEST_TYPE: () => DEVICE_MANIFEST_TYPE,
2079
+ DeviceManifest: () => DeviceManifest,
2080
+ DeviceManifestEntry: () => DeviceManifestEntry,
2081
+ PROFILE_CORE_BINDING_V1: () => PROFILE_CORE_BINDING_V1,
2082
+ PROFILE_CORE_BINDING_V2: () => PROFILE_CORE_BINDING_V2,
2083
+ PROFILE_DIRECT_BASE_V1: () => PROFILE_DIRECT_BASE_V1,
2084
+ PROFILE_DIRECT_BASE_V2: () => PROFILE_DIRECT_BASE_V2,
2085
+ PROFILE_DIRECT_E2EE_V2: () => PROFILE_DIRECT_E2EE_V2,
2086
+ PROFILE_GROUP_BASE_V1: () => PROFILE_GROUP_BASE_V1,
2087
+ PROFILE_GROUP_BASE_V2: () => PROFILE_GROUP_BASE_V2,
2088
+ PROFILE_GROUP_E2EE_V2: () => PROFILE_GROUP_E2EE_V2,
2089
+ PROFILE_IDENTITY_DISCOVERY_V1: () => PROFILE_IDENTITY_DISCOVERY_V1,
2090
+ PROFILE_IDENTITY_DISCOVERY_V2: () => PROFILE_IDENTITY_DISCOVERY_V2,
2091
+ addDeviceToDidDocument: () => addDeviceToDidDocument,
2092
+ buildVnextDidDocument: () => buildVnextDidDocument,
2093
+ findEligibleDevice: () => findEligibleDevice,
2094
+ parseDeviceManifest: () => parseDeviceManifest,
2095
+ removeDeviceFromDidDocument: () => removeDeviceFromDidDocument,
2096
+ updateDeviceInDidDocument: () => updateDeviceInDidDocument,
2097
+ validateDeviceManifest: () => validateDeviceManifest
2098
+ });
2099
+ var DEVICE_MANIFEST_TYPE = "ANPDeviceManifest";
2100
+ var PROFILE_CORE_BINDING_V1 = "anp.core.binding.v1";
2101
+ var PROFILE_IDENTITY_DISCOVERY_V1 = "anp.identity.discovery.v1";
2102
+ var PROFILE_DIRECT_BASE_V1 = "anp.direct.base.v1";
2103
+ var PROFILE_GROUP_BASE_V1 = "anp.group.base.v1";
2104
+ var PROFILE_DIRECT_E2EE_V2 = "anp.direct.e2ee.v2";
2105
+ var PROFILE_GROUP_E2EE_V2 = "anp.group.e2ee.v2";
2106
+ var PROFILE_CORE_BINDING_V2 = "anp.core.binding.v2";
2107
+ var PROFILE_IDENTITY_DISCOVERY_V2 = "anp.identity.discovery.v2";
2108
+ var PROFILE_DIRECT_BASE_V2 = "anp.direct.base.v2";
2109
+ var PROFILE_GROUP_BASE_V2 = "anp.group.base.v2";
2110
+ var MANIFEST_FIELDS = /* @__PURE__ */ new Set(["type", "devices"]);
2111
+ var ENTRY_FIELDS = /* @__PURE__ */ new Set(["device_id", "signing_key_id", "e2ee_key_id", "profiles"]);
2112
+ var P5_DEPENDENCIES = /* @__PURE__ */ new Set([
2113
+ PROFILE_CORE_BINDING_V1,
2114
+ PROFILE_IDENTITY_DISCOVERY_V1,
2115
+ PROFILE_DIRECT_BASE_V1,
2116
+ PROFILE_DIRECT_E2EE_V2
2117
+ ]);
2118
+ var P6_DEPENDENCIES = /* @__PURE__ */ new Set([
2119
+ PROFILE_CORE_BINDING_V1,
2120
+ PROFILE_IDENTITY_DISCOVERY_V1,
2121
+ PROFILE_GROUP_BASE_V1,
2122
+ PROFILE_GROUP_E2EE_V2
2123
+ ]);
2124
+ var P5_LEGACY_DRAFT_DEPENDENCIES = /* @__PURE__ */ new Set([
2125
+ PROFILE_CORE_BINDING_V2,
2126
+ PROFILE_IDENTITY_DISCOVERY_V2,
2127
+ PROFILE_DIRECT_BASE_V2,
2128
+ PROFILE_DIRECT_E2EE_V2
2129
+ ]);
2130
+ var P6_LEGACY_DRAFT_DEPENDENCIES = /* @__PURE__ */ new Set([
2131
+ PROFILE_CORE_BINDING_V2,
2132
+ PROFILE_IDENTITY_DISCOVERY_V2,
2133
+ PROFILE_GROUP_BASE_V2,
2134
+ PROFILE_GROUP_E2EE_V2
2135
+ ]);
2136
+ var LEGACY_DRAFT_FOUNDATION_PROFILES = /* @__PURE__ */ new Set([
2137
+ PROFILE_CORE_BINDING_V2,
2138
+ PROFILE_IDENTITY_DISCOVERY_V2,
2139
+ PROFILE_DIRECT_BASE_V2,
2140
+ PROFILE_GROUP_BASE_V2
2141
+ ]);
2142
+ var BASE64URL_RE = /^[A-Za-z0-9_-]+$/;
2143
+ var SIGNING_ALGORITHMS = /* @__PURE__ */ new Set(["Ed25519", "P-256", "secp256k1"]);
2144
+ var DeviceManifestEntry = class _DeviceManifestEntry {
2145
+ constructor(deviceId, signingKeyId, e2eeKeyId, profiles) {
2146
+ this.deviceId = deviceId;
2147
+ this.signingKeyId = signingKeyId;
2148
+ this.e2eeKeyId = e2eeKeyId;
2149
+ this.profiles = profiles;
2150
+ }
2151
+ static fromWire(value) {
2152
+ return new _DeviceManifestEntry(value.device_id, value.signing_key_id, value.e2ee_key_id, [
2153
+ ...value.profiles
2154
+ ]);
2155
+ }
2156
+ toDict() {
2157
+ return {
2158
+ device_id: this.deviceId,
2159
+ signing_key_id: this.signingKeyId,
2160
+ e2ee_key_id: this.e2eeKeyId,
2161
+ profiles: [...this.profiles]
2162
+ };
2163
+ }
2164
+ };
2165
+ var DeviceManifest = class {
2166
+ constructor(type, devices) {
2167
+ this.type = type;
2168
+ this.devices = devices;
2169
+ }
2170
+ toDict() {
2171
+ return {
2172
+ type: this.type,
2173
+ devices: this.devices.map((device) => device.toDict())
2174
+ };
2175
+ }
2176
+ };
2177
+ function parseDeviceManifest(didDocument) {
2178
+ if (!Object.prototype.hasOwnProperty.call(didDocument, "deviceManifest")) {
2179
+ return null;
2180
+ }
2181
+ const rawManifest = didDocument.deviceManifest;
2182
+ if (!isPlainObject(rawManifest)) {
2183
+ throw new DeviceManifestError("deviceManifest must be an object");
2184
+ }
2185
+ requireExactFields(rawManifest, MANIFEST_FIELDS, "deviceManifest");
2186
+ if (rawManifest.type !== DEVICE_MANIFEST_TYPE) {
2187
+ throw new DeviceManifestError("deviceManifest.type must equal ANPDeviceManifest");
2188
+ }
2189
+ const rawDevices = rawManifest.devices;
2190
+ if (!Array.isArray(rawDevices)) {
2191
+ throw new DeviceManifestError("deviceManifest.devices must be an array");
2192
+ }
2193
+ const devices = [];
2194
+ rawDevices.forEach((rawEntry, index) => {
2195
+ const subject = `deviceManifest.devices[${index}]`;
2196
+ if (!isPlainObject(rawEntry)) {
2197
+ throw new DeviceManifestError(`${subject} must be an object`);
2198
+ }
2199
+ requireExactFields(rawEntry, ENTRY_FIELDS, subject);
2200
+ const deviceId = requireString(rawEntry.device_id, `${subject}.device_id`);
2201
+ const signingKeyId = requireString(rawEntry.signing_key_id, `${subject}.signing_key_id`);
2202
+ const e2eeKeyId = requireString(rawEntry.e2ee_key_id, `${subject}.e2ee_key_id`);
2203
+ const rawProfiles = rawEntry.profiles;
2204
+ if (!Array.isArray(rawProfiles)) {
2205
+ throw new DeviceManifestError(`${subject}.profiles must be a string array`);
2206
+ }
2207
+ const profiles = rawProfiles.map((profile) => requireString(profile, `${subject}.profiles[]`));
2208
+ devices.push(new DeviceManifestEntry(deviceId, signingKeyId, e2eeKeyId, profiles));
2209
+ });
2210
+ return new DeviceManifest(DEVICE_MANIFEST_TYPE, devices);
2211
+ }
2212
+ function validateDeviceManifest(didDocument) {
2213
+ const manifest = parseDeviceManifest(didDocument);
2214
+ if (manifest === null) {
2215
+ return null;
2216
+ }
2217
+ const did = requireNonEmptyString(didDocument.id, "DID document id");
2218
+ const verificationMethods = didDocument.verificationMethod;
2219
+ if (!Array.isArray(verificationMethods)) {
2220
+ throw new DeviceManifestError("DID document verificationMethod must be an array");
2221
+ }
2222
+ const methodsById = /* @__PURE__ */ new Map();
2223
+ for (const method of verificationMethods) {
2224
+ if (!isPlainObject(method)) {
2225
+ continue;
2226
+ }
2227
+ const methodId = method.id;
2228
+ if (typeof methodId === "string") {
2229
+ const existing = methodsById.get(methodId) ?? [];
2230
+ existing.push(method);
2231
+ methodsById.set(methodId, existing);
2232
+ }
2233
+ }
2234
+ const seenDeviceIds = /* @__PURE__ */ new Set();
2235
+ const seenKeyIds = /* @__PURE__ */ new Set();
2236
+ for (const entry of manifest.devices) {
2237
+ requireNonEmptyString(entry.deviceId, "device_id");
2238
+ requireNonEmptyString(entry.signingKeyId, "signing_key_id");
2239
+ requireNonEmptyString(entry.e2eeKeyId, "e2ee_key_id");
2240
+ if (entry.profiles.length === 0) {
2241
+ throw new DeviceManifestError("profiles must be non-empty");
2242
+ }
2243
+ for (const profile of entry.profiles) {
2244
+ requireNonEmptyString(profile, "profile");
2245
+ }
2246
+ if (seenDeviceIds.has(entry.deviceId)) {
2247
+ throw new DeviceManifestError("device_id must be unique");
2248
+ }
2249
+ seenDeviceIds.add(entry.deviceId);
2250
+ if (entry.signingKeyId === entry.e2eeKeyId) {
2251
+ throw new DeviceManifestError("signing_key_id and e2ee_key_id must be distinct");
2252
+ }
2253
+ for (const keyId of [entry.signingKeyId, entry.e2eeKeyId]) {
2254
+ if (seenKeyIds.has(keyId)) {
2255
+ throw new DeviceManifestError("a verification method can belong to only one device entry");
2256
+ }
2257
+ seenKeyIds.add(keyId);
2258
+ validateSameDocumentMethod(did, keyId, methodsById);
2259
+ }
2260
+ const profileSet = new Set(entry.profiles);
2261
+ if (profileSet.has(PROFILE_DIRECT_E2EE_V2)) {
2262
+ requireDependencies(profileSet, P5_DEPENDENCIES, P5_LEGACY_DRAFT_DEPENDENCIES, "P5");
2263
+ requireRelationship(didDocument, "assertionMethod", entry.signingKeyId, "P5 signing key");
2264
+ }
2265
+ if (profileSet.has(PROFILE_GROUP_E2EE_V2)) {
2266
+ requireDependencies(profileSet, P6_DEPENDENCIES, P6_LEGACY_DRAFT_DEPENDENCIES, "P6");
2267
+ requireRelationship(didDocument, "assertionMethod", entry.signingKeyId, "P6 binding key");
2268
+ requireRelationship(didDocument, "authentication", entry.signingKeyId, "P6 origin-proof key");
2269
+ }
2270
+ requireRelationship(didDocument, "keyAgreement", entry.e2eeKeyId, "device E2EE key");
2271
+ }
2272
+ return manifest;
2273
+ }
2274
+ function findEligibleDevice(didDocument, deviceId, requiredProfile) {
2275
+ const manifest = validateDeviceManifest(didDocument);
2276
+ if (manifest === null) {
2277
+ return null;
2278
+ }
2279
+ if (requiredProfile !== PROFILE_DIRECT_E2EE_V2 && requiredProfile !== PROFILE_GROUP_E2EE_V2) {
2280
+ return null;
2281
+ }
2282
+ return manifest.devices.find(
2283
+ (entry) => entry.deviceId === deviceId && entry.profiles.includes(requiredProfile)
2284
+ ) ?? null;
2285
+ }
2286
+ function buildVnextDidDocument(baseDocument, rootKeyId, rootVerificationMethod, device, deviceSigningVerificationMethod, deviceE2eeVerificationMethod) {
2287
+ requireCanonicalWriteProfiles(device);
2288
+ const document = cloneDocument(baseDocument);
2289
+ for (const field of [
2290
+ "verificationMethod",
2291
+ "authentication",
2292
+ "assertionMethod",
2293
+ "keyAgreement",
2294
+ "deviceManifest",
2295
+ "proof"
2296
+ ]) {
2297
+ if (field in document) {
2298
+ throw new DeviceManifestError(`base DID document must not contain managed field ${field}`);
2299
+ }
2300
+ }
2301
+ const did = documentDid(document);
2302
+ validateRootMethod(did, rootKeyId, rootVerificationMethod);
2303
+ validateDeviceMethods(
2304
+ did,
2305
+ rootKeyId,
2306
+ device,
2307
+ deviceSigningVerificationMethod,
2308
+ deviceE2eeVerificationMethod
2309
+ );
2310
+ Object.assign(document, {
2311
+ verificationMethod: [
2312
+ structuredClone(rootVerificationMethod),
2313
+ structuredClone(deviceSigningVerificationMethod),
2314
+ structuredClone(deviceE2eeVerificationMethod)
2315
+ ],
2316
+ authentication: [device.signingKeyId],
2317
+ assertionMethod: [rootKeyId, device.signingKeyId],
2318
+ keyAgreement: [device.e2eeKeyId],
2319
+ deviceManifest: {
2320
+ type: DEVICE_MANIFEST_TYPE,
2321
+ devices: [device.toDict()]
2322
+ }
2323
+ });
2324
+ validateVnextDocument(document, rootKeyId);
2325
+ return document;
2326
+ }
2327
+ function addDeviceToDidDocument(didDocument, rootKeyId, device, deviceSigningVerificationMethod, deviceE2eeVerificationMethod, retiredDeviceIds) {
2328
+ requireCanonicalWriteProfiles(device);
2329
+ const document = prepareDocumentForMutation(didDocument, rootKeyId);
2330
+ const manifest = validateDeviceManifest(document);
2331
+ if (manifest === null) {
2332
+ throw new DeviceManifestError("deviceManifest is required for device update");
2333
+ }
2334
+ if (manifest.devices.some((entry) => entry.deviceId === device.deviceId)) {
2335
+ throw new DeviceManifestError("device_id already exists");
2336
+ }
2337
+ const retired = validateRetiredDeviceIds(retiredDeviceIds);
2338
+ if (retired.has(device.deviceId)) {
2339
+ throw new DeviceManifestError("retired device_id cannot be reused");
2340
+ }
2341
+ appendDeviceMaterial(
2342
+ document,
2343
+ rootKeyId,
2344
+ device,
2345
+ deviceSigningVerificationMethod,
2346
+ deviceE2eeVerificationMethod
2347
+ );
2348
+ validateVnextDocument(document, rootKeyId);
2349
+ return document;
2350
+ }
2351
+ function updateDeviceInDidDocument(didDocument, rootKeyId, device, deviceSigningVerificationMethod, deviceE2eeVerificationMethod) {
2352
+ requireCanonicalWriteProfiles(device);
2353
+ const document = prepareDocumentForMutation(didDocument, rootKeyId);
2354
+ const manifest = validateDeviceManifest(document);
2355
+ if (manifest === null) {
2356
+ throw new DeviceManifestError("deviceManifest is required for device update");
2357
+ }
2358
+ const oldEntry = manifest.devices.find((entry) => entry.deviceId === device.deviceId);
2359
+ if (oldEntry === void 0) {
2360
+ throw new DeviceManifestError("device_id does not exist");
2361
+ }
2362
+ removeDeviceMaterial(document, oldEntry);
2363
+ appendDeviceMaterial(
2364
+ document,
2365
+ rootKeyId,
2366
+ device,
2367
+ deviceSigningVerificationMethod,
2368
+ deviceE2eeVerificationMethod
2369
+ );
2370
+ validateVnextDocument(document, rootKeyId);
2371
+ return document;
2372
+ }
2373
+ function removeDeviceFromDidDocument(didDocument, rootKeyId, deviceId) {
2374
+ const document = prepareDocumentForMutation(didDocument, rootKeyId);
2375
+ const manifest = validateDeviceManifest(document);
2376
+ if (manifest === null) {
2377
+ throw new DeviceManifestError("deviceManifest is required for device update");
2378
+ }
2379
+ const oldEntry = manifest.devices.find((entry) => entry.deviceId === deviceId);
2380
+ if (oldEntry === void 0) {
2381
+ throw new DeviceManifestError("device_id does not exist");
2382
+ }
2383
+ removeDeviceMaterial(document, oldEntry);
2384
+ validateVnextDocument(document, rootKeyId);
2385
+ return document;
2386
+ }
2387
+ function cloneDocument(didDocument) {
2388
+ if (!isPlainObject(didDocument)) {
2389
+ throw new DeviceManifestError("DID document must be an object");
2390
+ }
2391
+ validateJsonValue(didDocument, "DID document");
2392
+ return structuredClone(didDocument);
2393
+ }
2394
+ function documentDid(didDocument) {
2395
+ return requireNonEmptyString(didDocument.id, "DID document id");
2396
+ }
2397
+ function prepareDocumentForMutation(didDocument, rootKeyId) {
2398
+ const document = cloneDocument(didDocument);
2399
+ validateVnextDocument(document, rootKeyId);
2400
+ const manifest = validateDeviceManifest(document);
2401
+ if (manifest === null) {
2402
+ throw new DeviceManifestError("deviceManifest is required");
2403
+ }
2404
+ for (const entry of manifest.devices) {
2405
+ requireCanonicalWriteProfiles(entry);
2406
+ }
2407
+ delete document.proof;
2408
+ return document;
2409
+ }
2410
+ function requireCanonicalWriteProfiles(device) {
2411
+ if (device.profiles.some((profile) => LEGACY_DRAFT_FOUNDATION_PROFILES.has(profile))) {
2412
+ throw new DeviceManifestError(
2413
+ "legacy draft foundation profiles are read-only and cannot be published"
2414
+ );
2415
+ }
2416
+ }
2417
+ function validateVnextDocument(didDocument, rootKeyId) {
2418
+ validateJsonValue(didDocument, "DID document");
2419
+ rejectPrivateKeyMaterial(didDocument, "DID document");
2420
+ const did = documentDid(didDocument);
2421
+ const methods = didDocument.verificationMethod;
2422
+ if (!Array.isArray(methods)) {
2423
+ throw new DeviceManifestError("DID document verificationMethod must be an array");
2424
+ }
2425
+ const rootMethods = methods.filter((method) => isPlainObject(method) && method.id === rootKeyId);
2426
+ if (rootMethods.length !== 1 || !isPlainObject(rootMethods[0])) {
2427
+ throw new DeviceManifestError("root key must resolve exactly once in verificationMethod");
2428
+ }
2429
+ const rootIdentity = validateRootMethod(did, rootKeyId, rootMethods[0]);
2430
+ requireRelationship(didDocument, "assertionMethod", rootKeyId, "DID root key");
2431
+ const manifest = validateDeviceManifest(didDocument);
2432
+ if (manifest === null) {
2433
+ throw new DeviceManifestError("deviceManifest is required");
2434
+ }
2435
+ const seenMaterial = /* @__PURE__ */ new Set([rootIdentity.rawPublicKey]);
2436
+ for (const entry of manifest.devices) {
2437
+ if (rootKeyId === entry.signingKeyId || rootKeyId === entry.e2eeKeyId) {
2438
+ throw new DeviceManifestError("DID root key cannot be a device key");
2439
+ }
2440
+ const signingMethod = uniqueMethod(didDocument, entry.signingKeyId);
2441
+ const e2eeMethod = uniqueMethod(didDocument, entry.e2eeKeyId);
2442
+ const [signingIdentity, e2eeIdentity] = validateDeviceMethods(
2443
+ did,
2444
+ rootKeyId,
2445
+ entry,
2446
+ signingMethod,
2447
+ e2eeMethod
2448
+ );
2449
+ requireRelationship(didDocument, "authentication", entry.signingKeyId, "device signing key");
2450
+ requireRelationship(didDocument, "assertionMethod", entry.signingKeyId, "device signing key");
2451
+ requireRelationship(didDocument, "keyAgreement", entry.e2eeKeyId, "device E2EE key");
2452
+ if (relationshipContains(didDocument, "keyAgreement", entry.signingKeyId)) {
2453
+ throw new DeviceManifestError("device signing key must not be in keyAgreement");
2454
+ }
2455
+ if (relationshipContains(didDocument, "authentication", entry.e2eeKeyId) || relationshipContains(didDocument, "assertionMethod", entry.e2eeKeyId)) {
2456
+ throw new DeviceManifestError("device E2EE key must not be a signing relationship");
2457
+ }
2458
+ for (const identity of [signingIdentity, e2eeIdentity]) {
2459
+ if (seenMaterial.has(identity.rawPublicKey)) {
2460
+ throw new DeviceManifestError("root and device public key material must be unique");
2461
+ }
2462
+ seenMaterial.add(identity.rawPublicKey);
2463
+ }
2464
+ }
2465
+ }
2466
+ function validateRootMethod(did, rootKeyId, verificationMethod) {
2467
+ return validatePublicMethod(
2468
+ did,
2469
+ rootKeyId,
2470
+ verificationMethod,
2471
+ SIGNING_ALGORITHMS,
2472
+ "DID root verification method"
2473
+ );
2474
+ }
2475
+ function validateDeviceMethods(did, rootKeyId, device, signingMethod, e2eeMethod) {
2476
+ if (rootKeyId === device.signingKeyId || rootKeyId === device.e2eeKeyId) {
2477
+ throw new DeviceManifestError("DID root key cannot be a device key");
2478
+ }
2479
+ const standardObjectProof = device.profiles.some(
2480
+ (profile) => profile === PROFILE_DIRECT_E2EE_V2 || profile === PROFILE_GROUP_E2EE_V2
2481
+ );
2482
+ const signingIdentity = validatePublicMethod(
2483
+ did,
2484
+ device.signingKeyId,
2485
+ signingMethod,
2486
+ standardObjectProof ? /* @__PURE__ */ new Set(["Ed25519"]) : SIGNING_ALGORITHMS,
2487
+ "device signing verification method"
2488
+ );
2489
+ const e2eeIdentity = validatePublicMethod(
2490
+ did,
2491
+ device.e2eeKeyId,
2492
+ e2eeMethod,
2493
+ /* @__PURE__ */ new Set(["X25519"]),
2494
+ "device E2EE verification method"
2495
+ );
2496
+ if (signingIdentity.rawPublicKey === e2eeIdentity.rawPublicKey) {
2497
+ throw new DeviceManifestError("device key material must be unique across roles");
2498
+ }
2499
+ return [signingIdentity, e2eeIdentity];
2500
+ }
2501
+ function validatePublicMethod(did, expectedKeyId, method, allowedAlgorithms, subject) {
2502
+ if (!isPlainObject(method)) {
2503
+ throw new DeviceManifestError(`${subject} must be an object`);
2504
+ }
2505
+ validateJsonValue(method, subject);
2506
+ if (method.id !== expectedKeyId) {
2507
+ throw new DeviceManifestError(`${subject} id does not match its role`);
2508
+ }
2509
+ if (method.controller !== did) {
2510
+ throw new DeviceManifestError(`${subject} controller must match the DID`);
2511
+ }
2512
+ validateSameDocumentKeyId(did, expectedKeyId);
2513
+ rejectPrivateKeyMaterial(method, subject);
2514
+ const methodType = requireNonEmptyString(method.type, `${subject}.type`);
2515
+ const materialFields = ["publicKeyJwk", "publicKeyMultibase", "publicKeyBase58"].filter(
2516
+ (field) => Object.prototype.hasOwnProperty.call(method, field)
2517
+ );
2518
+ if (materialFields.length !== 1) {
2519
+ throw new DeviceManifestError(`${subject} must contain exactly one supported public key field`);
2520
+ }
2521
+ const materialField = materialFields[0];
2522
+ let identity;
2523
+ if (materialField === "publicKeyJwk") {
2524
+ identity = decodePublicJwk(methodType, method[materialField], subject);
2525
+ } else if (materialField === "publicKeyMultibase") {
2526
+ identity = decodePublicMultikey(methodType, method[materialField], subject);
2527
+ } else {
2528
+ throw new DeviceManifestError(`${subject} publicKeyBase58 is not supported by vNext helpers`);
2529
+ }
2530
+ if (!allowedAlgorithms.has(identity.algorithm)) {
2531
+ throw new DeviceManifestError(`${subject} uses the wrong key algorithm`);
2532
+ }
2533
+ return identity;
2534
+ }
2535
+ function validateSameDocumentKeyId(did, keyId) {
2536
+ if (!keyId.startsWith(`${did}#`) || keyId === `${did}#`) {
2537
+ throw new DeviceManifestError("key id must be a DID URL in the same document");
2538
+ }
2539
+ }
2540
+ function decodePublicJwk(methodType, value, subject) {
2541
+ if (methodType !== "JsonWebKey2020" && methodType !== "EcdsaSecp256k1VerificationKey2019" && methodType !== "EcdsaSecp256r1VerificationKey2019") {
2542
+ throw new DeviceManifestError(`${subject} type is incompatible with publicKeyJwk`);
2543
+ }
2544
+ if (!isPlainObject(value)) {
2545
+ throw new DeviceManifestError(`${subject}.publicKeyJwk must be an object`);
2546
+ }
2547
+ const kty = value.kty;
2548
+ const curve = value.crv;
2549
+ if (kty === "OKP" && (curve === "Ed25519" || curve === "X25519")) {
2550
+ if (methodType !== "JsonWebKey2020") {
2551
+ throw new DeviceManifestError(`${subject} type contradicts its JWK`);
2552
+ }
2553
+ const raw = decodeCanonicalBase64url32(value.x, `${subject}.x`);
2554
+ return { algorithm: curve, rawPublicKey: encodeRaw(raw) };
2555
+ }
2556
+ if (kty === "EC" && (curve === "P-256" || curve === "secp256k1")) {
2557
+ const expectedType = curve === "P-256" ? "EcdsaSecp256r1VerificationKey2019" : "EcdsaSecp256k1VerificationKey2019";
2558
+ if (methodType !== "JsonWebKey2020" && methodType !== expectedType) {
2559
+ throw new DeviceManifestError(`${subject} type contradicts its JWK`);
2560
+ }
2561
+ const x = decodeCanonicalBase64url32(value.x, `${subject}.x`);
2562
+ const y = decodeCanonicalBase64url32(value.y, `${subject}.y`);
2563
+ validateEcPoint(curve, x, y, subject);
2564
+ return { algorithm: curve, rawPublicKey: encodeRaw(concatBytes(x, y)) };
2565
+ }
2566
+ throw new DeviceManifestError(`${subject} contains an unsupported public JWK`);
2567
+ }
2568
+ function decodePublicMultikey(methodType, value, subject) {
2569
+ if (methodType !== "Multikey" && methodType !== "X25519KeyAgreementKey2019") {
2570
+ throw new DeviceManifestError(`${subject} type is incompatible with publicKeyMultibase`);
2571
+ }
2572
+ if (typeof value !== "string" || !value.startsWith("z") || value.length === 1) {
2573
+ throw new DeviceManifestError(`${subject}.publicKeyMultibase must be base58btc`);
2574
+ }
2575
+ let decoded;
2576
+ try {
2577
+ decoded = bs58__default.default.decode(value.slice(1));
2578
+ } catch (error) {
2579
+ throw new DeviceManifestError(`${subject}.publicKeyMultibase is invalid`, error);
2580
+ }
2581
+ if (`z${bs58__default.default.encode(decoded)}` !== value) {
2582
+ throw new DeviceManifestError(`${subject}.publicKeyMultibase must be canonical`);
2583
+ }
2584
+ if (decoded.length !== 34) {
2585
+ throw new DeviceManifestError(`${subject}.publicKeyMultibase must contain a 32-byte key`);
2586
+ }
2587
+ const prefix = decoded[0] * 256 + decoded[1];
2588
+ let algorithm;
2589
+ if (prefix === 60673) {
2590
+ algorithm = "Ed25519";
2591
+ } else if (prefix === 60417) {
2592
+ algorithm = "X25519";
2593
+ } else {
2594
+ throw new DeviceManifestError(`${subject}.publicKeyMultibase uses an unsupported codec`);
2595
+ }
2596
+ if (methodType === "X25519KeyAgreementKey2019" && algorithm !== "X25519") {
2597
+ throw new DeviceManifestError(`${subject} type contradicts its Multikey`);
2598
+ }
2599
+ return { algorithm, rawPublicKey: encodeRaw(decoded.slice(2)) };
2600
+ }
2601
+ function decodeCanonicalBase64url32(value, subject) {
2602
+ if (typeof value !== "string" || !BASE64URL_RE.test(value)) {
2603
+ throw new DeviceManifestError(`${subject} must be unpadded base64url`);
2604
+ }
2605
+ let decoded;
2606
+ try {
2607
+ decoded = decodeBase64Url(value);
2608
+ } catch (error) {
2609
+ throw new DeviceManifestError(`${subject} is invalid base64url`, error);
2610
+ }
2611
+ const canonical = encodeBase64Url(decoded);
2612
+ if (decoded.length !== 32 || canonical !== value) {
2613
+ throw new DeviceManifestError(`${subject} must canonically encode 32 bytes`);
2614
+ }
2615
+ return decoded;
2616
+ }
2617
+ function validateEcPoint(curve, x, y, subject) {
2618
+ const uncompressed = new Uint8Array(65);
2619
+ uncompressed[0] = 4;
2620
+ uncompressed.set(x, 1);
2621
+ uncompressed.set(y, 33);
2622
+ try {
2623
+ if (curve === "P-256") {
2624
+ p256.p256.ProjectivePoint.fromHex(uncompressed);
2625
+ } else {
2626
+ secp256k1.secp256k1.ProjectivePoint.fromHex(uncompressed);
2627
+ }
2628
+ } catch (error) {
2629
+ throw new DeviceManifestError(`${subject} contains an invalid EC point`, error);
2630
+ }
2631
+ }
2632
+ function rejectPrivateKeyMaterial(value, subject) {
2633
+ if (isPlainObject(value)) {
2634
+ for (const [key, nested] of Object.entries(value)) {
2635
+ const normalizedKey = key.toLowerCase().replaceAll("_", "").replaceAll("-", "");
2636
+ if (normalizedKey.includes("privatekey") || key === "d" && "kty" in value) {
2637
+ throw new DeviceManifestError(`${subject} must not contain private key material`);
2638
+ }
2639
+ rejectPrivateKeyMaterial(nested, subject);
2640
+ }
2641
+ return;
2642
+ }
2643
+ if (Array.isArray(value)) {
2644
+ for (const nested of value) {
2645
+ rejectPrivateKeyMaterial(nested, subject);
2646
+ }
2647
+ }
2648
+ }
2649
+ function validateJsonValue(value, subject) {
2650
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
2651
+ return;
2652
+ }
2653
+ if (typeof value === "number") {
2654
+ if (!Number.isFinite(value)) {
2655
+ throw new DeviceManifestError(`${subject} contains a non-finite number`);
2656
+ }
2657
+ return;
2658
+ }
2659
+ if (Array.isArray(value)) {
2660
+ for (const nested of value) {
2661
+ validateJsonValue(nested, subject);
2662
+ }
2663
+ return;
2664
+ }
2665
+ if (isPlainObject(value)) {
2666
+ for (const [key, nested] of Object.entries(value)) {
2667
+ if (typeof key !== "string") {
2668
+ throw new DeviceManifestError(`${subject} contains a non-string object key`);
2669
+ }
2670
+ validateJsonValue(nested, subject);
2671
+ }
2672
+ return;
2673
+ }
2674
+ throw new DeviceManifestError(`${subject} contains a non-JSON value`);
2675
+ }
2676
+ function validateRetiredDeviceIds(retiredDeviceIds) {
2677
+ if (typeof retiredDeviceIds === "string") {
2678
+ throw new DeviceManifestError("retired_device_ids must be a string collection");
2679
+ }
2680
+ const values = [];
2681
+ try {
2682
+ for (const deviceId of retiredDeviceIds) {
2683
+ values.push(deviceId);
2684
+ }
2685
+ } catch (error) {
2686
+ throw new DeviceManifestError("retired_device_ids must be a string collection", error);
2687
+ }
2688
+ for (const deviceId of values) {
2689
+ requireNonEmptyString(deviceId, "retired device_id");
2690
+ }
2691
+ return new Set(values);
2692
+ }
2693
+ function uniqueMethod(didDocument, keyId) {
2694
+ const methods = didDocument.verificationMethod;
2695
+ if (!Array.isArray(methods)) {
2696
+ throw new DeviceManifestError("DID document verificationMethod must be an array");
2697
+ }
2698
+ const matches = methods.filter((method) => isPlainObject(method) && method.id === keyId);
2699
+ if (matches.length !== 1 || !isPlainObject(matches[0])) {
2700
+ throw new DeviceManifestError("key id must resolve exactly once in verificationMethod");
2701
+ }
2702
+ return matches[0];
2703
+ }
2704
+ function appendDeviceMaterial(document, rootKeyId, device, signingMethod, e2eeMethod) {
2705
+ const did = documentDid(document);
2706
+ validateDeviceMethods(did, rootKeyId, device, signingMethod, e2eeMethod);
2707
+ const methods = document.verificationMethod;
2708
+ const authentication2 = document.authentication;
2709
+ const assertionMethod = document.assertionMethod;
2710
+ const keyAgreement = document.keyAgreement;
2711
+ const manifest = document.deviceManifest;
2712
+ if (!Array.isArray(methods) || !Array.isArray(authentication2) || !Array.isArray(assertionMethod) || !Array.isArray(keyAgreement) || !isPlainObject(manifest) || !Array.isArray(manifest.devices)) {
2713
+ throw new DeviceManifestError("DID document relationships are invalid");
2714
+ }
2715
+ methods.push(structuredClone(signingMethod), structuredClone(e2eeMethod));
2716
+ authentication2.push(device.signingKeyId);
2717
+ assertionMethod.push(device.signingKeyId);
2718
+ keyAgreement.push(device.e2eeKeyId);
2719
+ manifest.devices.push(device.toDict());
2720
+ }
2721
+ function removeDeviceMaterial(document, device) {
2722
+ const keyIds = /* @__PURE__ */ new Set([device.signingKeyId, device.e2eeKeyId]);
2723
+ const methods = document.verificationMethod;
2724
+ if (!Array.isArray(methods)) {
2725
+ throw new DeviceManifestError("DID document verificationMethod must be an array");
2726
+ }
2727
+ document.verificationMethod = methods.filter(
2728
+ (method) => !(isPlainObject(method) && typeof method.id === "string" && keyIds.has(method.id))
2729
+ );
2730
+ for (const relationship of ["authentication", "assertionMethod", "keyAgreement"]) {
2731
+ const entries = document[relationship];
2732
+ if (!Array.isArray(entries)) {
2733
+ throw new DeviceManifestError(`${relationship} must be an array`);
2734
+ }
2735
+ document[relationship] = entries.filter(
2736
+ (entry) => ![...keyIds].some((keyId) => relationshipEntryIs(entry, keyId))
2737
+ );
2738
+ }
2739
+ const manifest = document.deviceManifest;
2740
+ if (!isPlainObject(manifest) || !Array.isArray(manifest.devices)) {
2741
+ throw new DeviceManifestError("deviceManifest.devices must be an array");
2742
+ }
2743
+ manifest.devices = manifest.devices.filter(
2744
+ (entry) => !(isPlainObject(entry) && entry.device_id === device.deviceId)
2745
+ );
2746
+ }
2747
+ function relationshipEntryIs(entry, keyId) {
2748
+ return entry === keyId || isPlainObject(entry) && entry.id === keyId;
2749
+ }
2750
+ function relationshipContains(didDocument, relationship, keyId) {
2751
+ const entries = didDocument[relationship];
2752
+ return Array.isArray(entries) && entries.some((entry) => relationshipEntryIs(entry, keyId));
2753
+ }
2754
+ function requireExactFields(value, expected, subject) {
2755
+ const actual = new Set(Object.keys(value));
2756
+ if (actual.size !== expected.size || [...expected].some((field) => !actual.has(field))) {
2757
+ throw new DeviceManifestError(
2758
+ `${subject} must contain exactly ${[...expected].sort().join(", ")}`
2759
+ );
2760
+ }
2761
+ }
2762
+ function requireString(value, subject) {
2763
+ if (typeof value !== "string") {
2764
+ throw new DeviceManifestError(`${subject} must be a string`);
2765
+ }
2766
+ return value;
2767
+ }
2768
+ function requireNonEmptyString(value, subject) {
2769
+ const result = requireString(value, subject);
2770
+ if (!result) {
2771
+ throw new DeviceManifestError(`${subject} must be a non-empty string`);
2772
+ }
2773
+ return result;
2774
+ }
2775
+ function validateSameDocumentMethod(did, keyId, methodsById) {
2776
+ if (!keyId.startsWith(`${did}#`) || keyId === `${did}#`) {
2777
+ throw new DeviceManifestError("device key IDs must be DID URLs in the same DID document");
2778
+ }
2779
+ const methods = methodsById.get(keyId) ?? [];
2780
+ if (methods.length !== 1) {
2781
+ throw new DeviceManifestError("device key ID must resolve exactly once in verificationMethod");
2782
+ }
2783
+ }
2784
+ function requireDependencies(profiles, required, legacyDraft, profileName) {
2785
+ const hasRequired = [...required].every((profile) => profiles.has(profile));
2786
+ const hasLegacy = [...legacyDraft].every((profile) => profiles.has(profile));
2787
+ if (!hasRequired && !hasLegacy) {
2788
+ throw new DeviceManifestError(`${profileName} device profile dependencies are incomplete`);
2789
+ }
2790
+ }
2791
+ function requireRelationship(didDocument, relationship, keyId, subject) {
2792
+ const entries = didDocument[relationship];
2793
+ if (!Array.isArray(entries)) {
2794
+ throw new DeviceManifestError(`${subject} requires ${relationship}`);
2795
+ }
2796
+ for (const entry of entries) {
2797
+ if (entry === keyId) {
2798
+ return;
2799
+ }
2800
+ if (isPlainObject(entry) && entry.id === keyId) {
2801
+ return;
2802
+ }
2803
+ }
2804
+ throw new DeviceManifestError(`${subject} is not authorized by ${relationship}`);
2805
+ }
2806
+ function isPlainObject(value) {
2807
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2808
+ }
2809
+ function encodeRaw(bytes) {
2810
+ return Buffer.from(bytes).toString("hex");
2811
+ }
2812
+ function concatBytes(left, right) {
2813
+ const output = new Uint8Array(left.length + right.length);
2814
+ output.set(left);
2815
+ output.set(right, left.length);
2816
+ return output;
2817
+ }
2818
+
2066
2819
  // src/authentication/index.ts
2067
2820
  var didDocuments = {
2068
2821
  ANP_MESSAGE_SERVICE_TYPE,
@@ -2093,6 +2846,7 @@ var authentication = {
2093
2846
  didDocuments,
2094
2847
  legacyAuth,
2095
2848
  httpSignatures,
2849
+ deviceManifest: device_manifest_exports,
2096
2850
  federation: {
2097
2851
  verifyRequest: verifyFederatedHttpRequest
2098
2852
  },
@@ -2271,12 +3025,206 @@ function isVerificationMethodAuthorized2(didDocument, verificationMethodId, veri
2271
3025
  throw new ProofError(`unsupported verification relationship: ${verificationRelationship}`);
2272
3026
  }
2273
3027
 
3028
+ // src/proof/rfc9421-origin.ts
3029
+ var rfc9421_origin_exports = {};
3030
+ __export(rfc9421_origin_exports, {
3031
+ RFC9421_ORIGIN_PROOF_DEFAULT_COMPONENTS: () => RFC9421_ORIGIN_PROOF_DEFAULT_COMPONENTS,
3032
+ RFC9421_ORIGIN_PROOF_DEFAULT_LABEL: () => RFC9421_ORIGIN_PROOF_DEFAULT_LABEL,
3033
+ Rfc9421OriginProofError: () => Rfc9421OriginProofError,
3034
+ TARGET_KIND_AGENT: () => TARGET_KIND_AGENT,
3035
+ TARGET_KIND_GROUP: () => TARGET_KIND_GROUP,
3036
+ TARGET_KIND_SERVICE: () => TARGET_KIND_SERVICE,
3037
+ buildLogicalTargetUri: () => buildLogicalTargetUri,
3038
+ buildRfc9421OriginSignatureBase: () => buildRfc9421OriginSignatureBase,
3039
+ buildSignedRequestObject: () => buildSignedRequestObject,
3040
+ canonicalizeSignedRequestObject: () => canonicalizeSignedRequestObject,
3041
+ generateRfc9421OriginProof: () => generateRfc9421OriginProof,
3042
+ quoteRfc3986Unreserved: () => quoteRfc3986Unreserved,
3043
+ verifyRfc9421OriginProof: () => verifyRfc9421OriginProof
3044
+ });
3045
+ var RFC9421_ORIGIN_PROOF_DEFAULT_LABEL = "sig1";
3046
+ var RFC9421_ORIGIN_PROOF_DEFAULT_COMPONENTS = IM_PROOF_DEFAULT_COMPONENTS;
3047
+ var TARGET_KIND_AGENT = "agent";
3048
+ var TARGET_KIND_GROUP = "group";
3049
+ var TARGET_KIND_SERVICE = "service";
3050
+ var ALLOWED_TARGET_KINDS = /* @__PURE__ */ new Set([TARGET_KIND_AGENT, TARGET_KIND_GROUP, TARGET_KIND_SERVICE]);
3051
+ var Rfc9421OriginProofError = class extends ProofError {
3052
+ constructor(message, cause) {
3053
+ super(message, cause);
3054
+ this.name = "Rfc9421OriginProofError";
3055
+ }
3056
+ };
3057
+ function buildSignedRequestObject(method, meta, body) {
3058
+ if (typeof method !== "string" || !method.trim()) {
3059
+ throw new Rfc9421OriginProofError("method is required");
3060
+ }
3061
+ if (!isPlainObject2(meta)) {
3062
+ throw new Rfc9421OriginProofError("meta must be an object");
3063
+ }
3064
+ if (!isPlainObject2(body)) {
3065
+ throw new Rfc9421OriginProofError("body must be an object");
3066
+ }
3067
+ return {
3068
+ method,
3069
+ meta: cloneJson(meta),
3070
+ body: cloneJson(body)
3071
+ };
3072
+ }
3073
+ function canonicalizeSignedRequestObject(signedRequestObject) {
3074
+ const keys = Object.keys(signedRequestObject);
3075
+ if (keys.length !== 3 || !keys.includes("method") || !keys.includes("meta") || !keys.includes("body")) {
3076
+ throw new Rfc9421OriginProofError(
3077
+ "signed request object must contain only method, meta, and body"
3078
+ );
3079
+ }
3080
+ return canonicalizeJson({
3081
+ method: signedRequestObject.method,
3082
+ meta: signedRequestObject.meta,
3083
+ body: signedRequestObject.body
3084
+ });
3085
+ }
3086
+ function buildLogicalTargetUri(targetKind, targetDid) {
3087
+ const normalizedKind = String(targetKind).trim();
3088
+ if (!ALLOWED_TARGET_KINDS.has(normalizedKind)) {
3089
+ throw new Rfc9421OriginProofError(`unsupported target kind: ${targetKind}`);
3090
+ }
3091
+ const normalizedDid = String(targetDid).trim();
3092
+ if (!normalizedDid) {
3093
+ throw new Rfc9421OriginProofError("target did is required");
3094
+ }
3095
+ return `anp://${normalizedKind}/${quoteRfc3986Unreserved(normalizedDid)}`;
3096
+ }
3097
+ function buildRfc9421OriginSignatureBase(method, logicalTargetUri, contentDigest, signatureInput) {
3098
+ if (typeof method !== "string" || !method.trim()) {
3099
+ throw new Rfc9421OriginProofError("method is required");
3100
+ }
3101
+ if (typeof logicalTargetUri !== "string" || !logicalTargetUri.trim()) {
3102
+ throw new Rfc9421OriginProofError("logical_target_uri is required");
3103
+ }
3104
+ if (typeof contentDigest !== "string" || !contentDigest.trim()) {
3105
+ throw new Rfc9421OriginProofError("content_digest is required");
3106
+ }
3107
+ const parsed = parseImSignatureInput(signatureInput);
3108
+ validateParsedSignatureInput(parsed.label, parsed.components);
3109
+ const componentValues = {
3110
+ "@method": method,
3111
+ "@target-uri": logicalTargetUri,
3112
+ "content-digest": contentDigest
3113
+ };
3114
+ const lines = parsed.components.map(
3115
+ (component) => `"${component}": ${componentValues[component]}`
3116
+ );
3117
+ lines.push(`"@signature-params": ${parsed.signatureParams}`);
3118
+ return new TextEncoder().encode(lines.join("\n"));
3119
+ }
3120
+ function generateRfc9421OriginProof(method, meta, body, privateKey, keyId, options = {}) {
3121
+ const label = options.label ?? RFC9421_ORIGIN_PROOF_DEFAULT_LABEL;
3122
+ validateLabel(label);
3123
+ const signedRequestObject = buildSignedRequestObject(method, meta, body);
3124
+ const canonicalRequest = canonicalizeSignedRequestObject(signedRequestObject);
3125
+ const logicalTargetUri = buildLogicalTargetUriFromMeta(signedRequestObject.meta);
3126
+ const contentDigest = buildImContentDigest(canonicalRequest);
3127
+ const signatureInput = buildImSignatureInput(keyId, {
3128
+ components: [...RFC9421_ORIGIN_PROOF_DEFAULT_COMPONENTS],
3129
+ label,
3130
+ created: options.created,
3131
+ expires: options.expires,
3132
+ nonce: options.nonce
3133
+ });
3134
+ const signatureBase = buildRfc9421OriginSignatureBase(
3135
+ method,
3136
+ logicalTargetUri,
3137
+ contentDigest,
3138
+ signatureInput
3139
+ );
3140
+ const proof2 = generateImProof(canonicalRequest, signatureBase, privateKey, keyId, {
3141
+ components: [...RFC9421_ORIGIN_PROOF_DEFAULT_COMPONENTS],
3142
+ label,
3143
+ created: options.created,
3144
+ expires: options.expires,
3145
+ nonce: options.nonce
3146
+ });
3147
+ const parsed = parseImSignatureInput(proof2.signatureInput);
3148
+ validateParsedSignatureInput(parsed.label, parsed.components);
3149
+ return proof2;
3150
+ }
3151
+ function verifyRfc9421OriginProof(originProof, method, meta, body, verification = {}) {
3152
+ const signedRequestObject = buildSignedRequestObject(method, meta, body);
3153
+ const canonicalRequest = canonicalizeSignedRequestObject(signedRequestObject);
3154
+ const logicalTargetUri = buildLogicalTargetUriFromMeta(signedRequestObject.meta);
3155
+ const signatureInput = requireProofField(originProof, "signatureInput");
3156
+ const parsed = parseImSignatureInput(signatureInput);
3157
+ validateParsedSignatureInput(parsed.label, parsed.components);
3158
+ const signatureBase = buildRfc9421OriginSignatureBase(
3159
+ method,
3160
+ logicalTargetUri,
3161
+ requireProofField(originProof, "contentDigest"),
3162
+ signatureInput
3163
+ );
3164
+ return verifyImProof(
3165
+ originProof,
3166
+ canonicalRequest,
3167
+ signatureBase,
3168
+ {
3169
+ didDocument: verification.didDocument,
3170
+ verificationMethod: verification.verificationMethod,
3171
+ verificationRelationship: IM_PROOF_RELATION_AUTHENTICATION
3172
+ },
3173
+ verification.options?.expectedSignerDid
3174
+ );
3175
+ }
3176
+ function buildLogicalTargetUriFromMeta(meta) {
3177
+ const target = meta.target;
3178
+ if (!isPlainObject2(target)) {
3179
+ throw new Rfc9421OriginProofError("meta.target is required");
3180
+ }
3181
+ return buildLogicalTargetUri(String(target.kind), String(target.did));
3182
+ }
3183
+ function validateLabel(label) {
3184
+ if (label !== RFC9421_ORIGIN_PROOF_DEFAULT_LABEL) {
3185
+ throw new Rfc9421OriginProofError("RFC 9421 origin proof requires signature label sig1");
3186
+ }
3187
+ }
3188
+ function validateParsedSignatureInput(label, components) {
3189
+ validateLabel(label);
3190
+ const expected = [...RFC9421_ORIGIN_PROOF_DEFAULT_COMPONENTS];
3191
+ if (components.length !== expected.length || components.some((value, index) => value !== expected[index])) {
3192
+ throw new Rfc9421OriginProofError(
3193
+ 'RFC 9421 origin proof requires covered components ("@method" "@target-uri" "content-digest")'
3194
+ );
3195
+ }
3196
+ }
3197
+ function requireProofField(proof2, field) {
3198
+ const value = proof2[field];
3199
+ if (!value) {
3200
+ throw new Rfc9421OriginProofError(`missing proof field: ${field}`);
3201
+ }
3202
+ return value;
3203
+ }
3204
+ function isPlainObject2(value) {
3205
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3206
+ }
3207
+ function quoteRfc3986Unreserved(value) {
3208
+ let output = "";
3209
+ for (const char of value) {
3210
+ if (/[A-Za-z0-9\-._~]/.test(char)) {
3211
+ output += char;
3212
+ continue;
3213
+ }
3214
+ for (const byte of new TextEncoder().encode(char)) {
3215
+ output += `%${byte.toString(16).toUpperCase().padStart(2, "0")}`;
3216
+ }
3217
+ }
3218
+ return output;
3219
+ }
3220
+
2274
3221
  // src/proof/index.ts
2275
3222
  var proof = {
2276
3223
  create: generateW3cProof,
2277
3224
  verify: verifyW3cProof,
2278
3225
  verifyDetailed: verifyW3cProofDetailed,
2279
- im: im_exports
3226
+ im: im_exports,
3227
+ rfc9421: rfc9421_origin_exports
2280
3228
  };
2281
3229
 
2282
3230
  // src/wns/types.ts
@@ -4879,7 +5827,11 @@ exports.AwikiImError = AwikiImError;
4879
5827
  exports.CRYPTOSUITE_DIDWBA_SECP256K1_2025 = CRYPTOSUITE_DIDWBA_SECP256K1_2025;
4880
5828
  exports.CRYPTOSUITE_EDDSA_JCS_2022 = CRYPTOSUITE_EDDSA_JCS_2022;
4881
5829
  exports.CryptoError = CryptoError;
5830
+ exports.DEVICE_MANIFEST_TYPE = DEVICE_MANIFEST_TYPE;
4882
5831
  exports.DIDWbaAuthHeader = DIDWbaAuthHeader;
5832
+ exports.DeviceManifest = DeviceManifest;
5833
+ exports.DeviceManifestEntry = DeviceManifestEntry;
5834
+ exports.DeviceManifestError = DeviceManifestError;
4883
5835
  exports.DidAuthHeaders = DIDWbaAuthHeader;
4884
5836
  exports.DidProfile = DidProfile;
4885
5837
  exports.DidWbaVerifier = DidWbaVerifier;
@@ -4895,19 +5847,36 @@ exports.IM_PROOF_DEFAULT_COMPONENTS = IM_PROOF_DEFAULT_COMPONENTS;
4895
5847
  exports.IM_PROOF_RELATION_ASSERTION_METHOD = IM_PROOF_RELATION_ASSERTION_METHOD;
4896
5848
  exports.IM_PROOF_RELATION_AUTHENTICATION = IM_PROOF_RELATION_AUTHENTICATION;
4897
5849
  exports.NetworkError = NetworkError;
5850
+ exports.PROFILE_CORE_BINDING_V1 = PROFILE_CORE_BINDING_V1;
5851
+ exports.PROFILE_CORE_BINDING_V2 = PROFILE_CORE_BINDING_V2;
5852
+ exports.PROFILE_DIRECT_BASE_V1 = PROFILE_DIRECT_BASE_V1;
5853
+ exports.PROFILE_DIRECT_BASE_V2 = PROFILE_DIRECT_BASE_V2;
5854
+ exports.PROFILE_DIRECT_E2EE_V2 = PROFILE_DIRECT_E2EE_V2;
5855
+ exports.PROFILE_GROUP_BASE_V1 = PROFILE_GROUP_BASE_V1;
5856
+ exports.PROFILE_GROUP_BASE_V2 = PROFILE_GROUP_BASE_V2;
5857
+ exports.PROFILE_GROUP_E2EE_V2 = PROFILE_GROUP_E2EE_V2;
5858
+ exports.PROFILE_IDENTITY_DISCOVERY_V1 = PROFILE_IDENTITY_DISCOVERY_V1;
5859
+ exports.PROFILE_IDENTITY_DISCOVERY_V2 = PROFILE_IDENTITY_DISCOVERY_V2;
4898
5860
  exports.PROOF_TYPE_DATA_INTEGRITY = PROOF_TYPE_DATA_INTEGRITY;
4899
5861
  exports.PROOF_TYPE_ED25519 = PROOF_TYPE_ED25519;
4900
5862
  exports.PROOF_TYPE_SECP256K1 = PROOF_TYPE_SECP256K1;
4901
5863
  exports.ProofError = ProofError;
5864
+ exports.RFC9421_ORIGIN_PROOF_DEFAULT_COMPONENTS = RFC9421_ORIGIN_PROOF_DEFAULT_COMPONENTS;
5865
+ exports.RFC9421_ORIGIN_PROOF_DEFAULT_LABEL = RFC9421_ORIGIN_PROOF_DEFAULT_LABEL;
4902
5866
  exports.RequestVerifier = DidWbaVerifier;
4903
5867
  exports.RequestVerifierError = DidWbaVerifierError;
5868
+ exports.Rfc9421OriginProofError = Rfc9421OriginProofError;
4904
5869
  exports.SubjectType = SubjectType;
5870
+ exports.TARGET_KIND_AGENT = TARGET_KIND_AGENT;
5871
+ exports.TARGET_KIND_GROUP = TARGET_KIND_GROUP;
5872
+ exports.TARGET_KIND_SERVICE = TARGET_KIND_SERVICE;
4905
5873
  exports.VM_KEY_AUTH = VM_KEY_AUTH;
4906
5874
  exports.VM_KEY_E2EE_AGREEMENT = VM_KEY_E2EE_AGREEMENT;
4907
5875
  exports.VM_KEY_E2EE_SIGNING = VM_KEY_E2EE_SIGNING;
4908
5876
  exports.VerificationMethod = VerificationMethod;
4909
5877
  exports.WbaUriParseError = WbaUriParseError;
4910
5878
  exports.WnsError = WnsError;
5879
+ exports.addDeviceToDidDocument = addDeviceToDidDocument;
4911
5880
  exports.authentication = authentication;
4912
5881
  exports.buildAgentMessageService = buildAgentMessageService;
4913
5882
  exports.buildAnpMessageService = buildAnpMessageService;
@@ -4916,10 +5885,15 @@ exports.buildGroupMessageService = buildGroupMessageService;
4916
5885
  exports.buildHandleServiceEntry = buildHandleServiceEntry;
4917
5886
  exports.buildImContentDigest = buildImContentDigest;
4918
5887
  exports.buildImSignatureInput = buildImSignatureInput;
5888
+ exports.buildLogicalTargetUri = buildLogicalTargetUri;
4919
5889
  exports.buildResolutionUrl = buildResolutionUrl;
5890
+ exports.buildRfc9421OriginSignatureBase = buildRfc9421OriginSignatureBase;
5891
+ exports.buildSignedRequestObject = buildSignedRequestObject;
4920
5892
  exports.buildUri = buildWbaUri;
5893
+ exports.buildVnextDidDocument = buildVnextDidDocument;
4921
5894
  exports.buildWbaUri = buildWbaUri;
4922
5895
  exports.canonicalizeBindingGeneration = canonicalizeBindingGeneration;
5896
+ exports.canonicalizeSignedRequestObject = canonicalizeSignedRequestObject;
4923
5897
  exports.compareBindingGenerations = compareBindingGenerations;
4924
5898
  exports.computeJwkFingerprint = computeJwkFingerprint;
4925
5899
  exports.computeMultikeyFingerprint = computeMultikeyFingerprint;
@@ -4942,28 +5916,35 @@ exports.extractHandleServiceFromDidDocument = extractHandleServiceFromDidDocumen
4942
5916
  exports.extractHandleServices = extractHandleServiceFromDidDocument;
4943
5917
  exports.extractPublicKey = extractPublicKey;
4944
5918
  exports.extractSignatureMetadata = extractSignatureMetadata;
5919
+ exports.findEligibleDevice = findEligibleDevice;
4945
5920
  exports.findVerificationMethod = findVerificationMethod;
4946
5921
  exports.generateAuthHeader = generateAuthHeader;
4947
5922
  exports.generateAuthJson = generateAuthJson;
4948
5923
  exports.generateHttpSignatureHeaders = generateHttpSignatureHeaders;
4949
5924
  exports.generateImProof = generateImProof;
5925
+ exports.generateRfc9421OriginProof = generateRfc9421OriginProof;
4950
5926
  exports.generateW3cProof = generateW3cProof;
4951
5927
  exports.httpSignatures = httpSignatures;
4952
5928
  exports.isAssertionMethodAuthorized = isAssertionMethodAuthorized;
4953
5929
  exports.isAuthenticationAuthorized = isAuthenticationAuthorized;
4954
5930
  exports.legacyAuth = legacyAuth;
4955
5931
  exports.normalizeHandle = normalizeHandle;
5932
+ exports.parseDeviceManifest = parseDeviceManifest;
4956
5933
  exports.parseImSignatureInput = parseImSignatureInput;
4957
5934
  exports.parseLegacyAuthHeader = extractAuthHeaderParts;
4958
5935
  exports.parseSignatureMetadata = extractSignatureMetadata;
4959
5936
  exports.parseUri = parseWbaUri;
4960
5937
  exports.parseWbaUri = parseWbaUri;
4961
5938
  exports.proof = proof;
5939
+ exports.quoteRfc3986Unreserved = quoteRfc3986Unreserved;
5940
+ exports.removeDeviceFromDidDocument = removeDeviceFromDidDocument;
4962
5941
  exports.resolveDidDocument = resolveDidDocument;
4963
5942
  exports.resolveDidWbaDocument = resolveDidWbaDocument;
4964
5943
  exports.resolveHandle = resolveHandle;
4965
5944
  exports.resolveHandleFromUri = resolveHandleFromUri;
4966
5945
  exports.resolveUri = resolveHandleFromUri;
5946
+ exports.updateDeviceInDidDocument = updateDeviceInDidDocument;
5947
+ exports.validateDeviceManifest = validateDeviceManifest;
4967
5948
  exports.validateDidBinding = validateDidDocumentBinding;
4968
5949
  exports.validateDidDocumentBinding = validateDidDocumentBinding;
4969
5950
  exports.validateHandle = validateHandle;
@@ -4983,6 +5964,7 @@ exports.verifyLegacyAuthHeader = verifyAuthHeaderSignature;
4983
5964
  exports.verifyLegacyAuthPayload = verifyAuthJsonSignature;
4984
5965
  exports.verifyProof = verifyW3cProof;
4985
5966
  exports.verifyProofDetailed = verifyW3cProofDetailed;
5967
+ exports.verifyRfc9421OriginProof = verifyRfc9421OriginProof;
4986
5968
  exports.verifySignatureHeaders = verifyHttpMessageSignature;
4987
5969
  exports.verifyW3cProof = verifyW3cProof;
4988
5970
  exports.verifyW3cProofDetailed = verifyW3cProofDetailed;