@openvtc/pnm-core 0.1.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.
Files changed (250) hide show
  1. package/README.md +129 -0
  2. package/dist/did/derive-signing-key.d.ts +19 -0
  3. package/dist/did/derive-signing-key.d.ts.map +1 -0
  4. package/dist/did/derive-signing-key.js +96 -0
  5. package/dist/did/derive-signing-key.js.map +1 -0
  6. package/dist/did/index.d.ts +5 -0
  7. package/dist/did/index.d.ts.map +1 -0
  8. package/dist/did/index.js +5 -0
  9. package/dist/did/index.js.map +1 -0
  10. package/dist/did/peer.d.ts +37 -0
  11. package/dist/did/peer.d.ts.map +1 -0
  12. package/dist/did/peer.js +49 -0
  13. package/dist/did/peer.js.map +1 -0
  14. package/dist/did/verification-method.d.ts +43 -0
  15. package/dist/did/verification-method.d.ts.map +1 -0
  16. package/dist/did/verification-method.js +32 -0
  17. package/dist/did/verification-method.js.map +1 -0
  18. package/dist/did/verify.d.ts +49 -0
  19. package/dist/did/verify.d.ts.map +1 -0
  20. package/dist/did/verify.js +89 -0
  21. package/dist/did/verify.js.map +1 -0
  22. package/dist/didcomm/index.d.ts +235 -0
  23. package/dist/didcomm/index.d.ts.map +1 -0
  24. package/dist/didcomm/index.js +415 -0
  25. package/dist/didcomm/index.js.map +1 -0
  26. package/dist/inbound/confirm.d.ts +50 -0
  27. package/dist/inbound/confirm.d.ts.map +1 -0
  28. package/dist/inbound/confirm.js +64 -0
  29. package/dist/inbound/confirm.js.map +1 -0
  30. package/dist/inbound/dedup.d.ts +9 -0
  31. package/dist/inbound/dedup.d.ts.map +1 -0
  32. package/dist/inbound/dedup.js +31 -0
  33. package/dist/inbound/dedup.js.map +1 -0
  34. package/dist/inbound/index.d.ts +3 -0
  35. package/dist/inbound/index.d.ts.map +1 -0
  36. package/dist/inbound/index.js +3 -0
  37. package/dist/inbound/index.js.map +1 -0
  38. package/dist/index.d.ts +14 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +14 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/onboarding/index.d.ts +2 -0
  43. package/dist/onboarding/index.d.ts.map +1 -0
  44. package/dist/onboarding/index.js +2 -0
  45. package/dist/onboarding/index.js.map +1 -0
  46. package/dist/onboarding/swap.d.ts +60 -0
  47. package/dist/onboarding/swap.d.ts.map +1 -0
  48. package/dist/onboarding/swap.js +148 -0
  49. package/dist/onboarding/swap.js.map +1 -0
  50. package/dist/provision/adopt.d.ts +31 -0
  51. package/dist/provision/adopt.d.ts.map +1 -0
  52. package/dist/provision/adopt.js +114 -0
  53. package/dist/provision/adopt.js.map +1 -0
  54. package/dist/provision/armor.d.ts +19 -0
  55. package/dist/provision/armor.d.ts.map +1 -0
  56. package/dist/provision/armor.js +243 -0
  57. package/dist/provision/armor.js.map +1 -0
  58. package/dist/provision/crc24.d.ts +5 -0
  59. package/dist/provision/crc24.d.ts.map +1 -0
  60. package/dist/provision/crc24.js +30 -0
  61. package/dist/provision/crc24.js.map +1 -0
  62. package/dist/provision/hpke.d.ts +17 -0
  63. package/dist/provision/hpke.d.ts.map +1 -0
  64. package/dist/provision/hpke.js +60 -0
  65. package/dist/provision/hpke.js.map +1 -0
  66. package/dist/provision/index.d.ts +10 -0
  67. package/dist/provision/index.d.ts.map +1 -0
  68. package/dist/provision/index.js +16 -0
  69. package/dist/provision/index.js.map +1 -0
  70. package/dist/provision/open.d.ts +28 -0
  71. package/dist/provision/open.d.ts.map +1 -0
  72. package/dist/provision/open.js +224 -0
  73. package/dist/provision/open.js.map +1 -0
  74. package/dist/provision/request.d.ts +65 -0
  75. package/dist/provision/request.d.ts.map +1 -0
  76. package/dist/provision/request.js +53 -0
  77. package/dist/provision/request.js.map +1 -0
  78. package/dist/provision/run.d.ts +76 -0
  79. package/dist/provision/run.d.ts.map +1 -0
  80. package/dist/provision/run.js +110 -0
  81. package/dist/provision/run.js.map +1 -0
  82. package/dist/provision/send.d.ts +85 -0
  83. package/dist/provision/send.d.ts.map +1 -0
  84. package/dist/provision/send.js +87 -0
  85. package/dist/provision/send.js.map +1 -0
  86. package/dist/provision/types.d.ts +110 -0
  87. package/dist/provision/types.d.ts.map +1 -0
  88. package/dist/provision/types.js +17 -0
  89. package/dist/provision/types.js.map +1 -0
  90. package/dist/rp-login/didcomm.d.ts +34 -0
  91. package/dist/rp-login/didcomm.d.ts.map +1 -0
  92. package/dist/rp-login/didcomm.js +72 -0
  93. package/dist/rp-login/didcomm.js.map +1 -0
  94. package/dist/rp-login/index.d.ts +3 -0
  95. package/dist/rp-login/index.d.ts.map +1 -0
  96. package/dist/rp-login/index.js +3 -0
  97. package/dist/rp-login/index.js.map +1 -0
  98. package/dist/rp-login/step-up.d.ts +43 -0
  99. package/dist/rp-login/step-up.d.ts.map +1 -0
  100. package/dist/rp-login/step-up.js +118 -0
  101. package/dist/rp-login/step-up.js.map +1 -0
  102. package/dist/siop/index.d.ts +3 -0
  103. package/dist/siop/index.d.ts.map +1 -0
  104. package/dist/siop/index.js +3 -0
  105. package/dist/siop/index.js.map +1 -0
  106. package/dist/siop/login-client.d.ts +29 -0
  107. package/dist/siop/login-client.d.ts.map +1 -0
  108. package/dist/siop/login-client.js +79 -0
  109. package/dist/siop/login-client.js.map +1 -0
  110. package/dist/siop/self-issued.d.ts +96 -0
  111. package/dist/siop/self-issued.d.ts.map +1 -0
  112. package/dist/siop/self-issued.js +162 -0
  113. package/dist/siop/self-issued.js.map +1 -0
  114. package/dist/store/holder-identity.d.ts +241 -0
  115. package/dist/store/holder-identity.d.ts.map +1 -0
  116. package/dist/store/holder-identity.js +441 -0
  117. package/dist/store/holder-identity.js.map +1 -0
  118. package/dist/store/index.d.ts +4 -0
  119. package/dist/store/index.d.ts.map +1 -0
  120. package/dist/store/index.js +4 -0
  121. package/dist/store/index.js.map +1 -0
  122. package/dist/store/kv-store.d.ts +51 -0
  123. package/dist/store/kv-store.d.ts.map +1 -0
  124. package/dist/store/kv-store.js +100 -0
  125. package/dist/store/kv-store.js.map +1 -0
  126. package/dist/store/secret-wrap.d.ts +109 -0
  127. package/dist/store/secret-wrap.d.ts.map +1 -0
  128. package/dist/store/secret-wrap.js +85 -0
  129. package/dist/store/secret-wrap.js.map +1 -0
  130. package/dist/trust-tasks/index.d.ts +2 -0
  131. package/dist/trust-tasks/index.d.ts.map +1 -0
  132. package/dist/trust-tasks/index.js +2 -0
  133. package/dist/trust-tasks/index.js.map +1 -0
  134. package/dist/trust-tasks/sign.d.ts +31 -0
  135. package/dist/trust-tasks/sign.d.ts.map +1 -0
  136. package/dist/trust-tasks/sign.js +141 -0
  137. package/dist/trust-tasks/sign.js.map +1 -0
  138. package/dist/util/timing.d.ts +14 -0
  139. package/dist/util/timing.d.ts.map +1 -0
  140. package/dist/util/timing.js +20 -0
  141. package/dist/util/timing.js.map +1 -0
  142. package/dist/vault/delete.d.ts +19 -0
  143. package/dist/vault/delete.d.ts.map +1 -0
  144. package/dist/vault/delete.js +35 -0
  145. package/dist/vault/delete.js.map +1 -0
  146. package/dist/vault/index.d.ts +8 -0
  147. package/dist/vault/index.d.ts.map +1 -0
  148. package/dist/vault/index.js +7 -0
  149. package/dist/vault/index.js.map +1 -0
  150. package/dist/vault/list.d.ts +96 -0
  151. package/dist/vault/list.d.ts.map +1 -0
  152. package/dist/vault/list.js +106 -0
  153. package/dist/vault/list.js.map +1 -0
  154. package/dist/vault/proxy-login.d.ts +100 -0
  155. package/dist/vault/proxy-login.d.ts.map +1 -0
  156. package/dist/vault/proxy-login.js +106 -0
  157. package/dist/vault/proxy-login.js.map +1 -0
  158. package/dist/vault/release.d.ts +33 -0
  159. package/dist/vault/release.d.ts.map +1 -0
  160. package/dist/vault/release.js +83 -0
  161. package/dist/vault/release.js.map +1 -0
  162. package/dist/vault/sign-trust-task.d.ts +26 -0
  163. package/dist/vault/sign-trust-task.d.ts.map +1 -0
  164. package/dist/vault/sign-trust-task.js +53 -0
  165. package/dist/vault/sign-trust-task.js.map +1 -0
  166. package/dist/vault/transport.d.ts +50 -0
  167. package/dist/vault/transport.d.ts.map +1 -0
  168. package/dist/vault/transport.js +118 -0
  169. package/dist/vault/transport.js.map +1 -0
  170. package/dist/vault/upsert.d.ts +102 -0
  171. package/dist/vault/upsert.d.ts.map +1 -0
  172. package/dist/vault/upsert.js +92 -0
  173. package/dist/vault/upsert.js.map +1 -0
  174. package/dist/vta/bridge-mediator-session.d.ts +26 -0
  175. package/dist/vta/bridge-mediator-session.d.ts.map +1 -0
  176. package/dist/vta/bridge-mediator-session.js +37 -0
  177. package/dist/vta/bridge-mediator-session.js.map +1 -0
  178. package/dist/vta/bridge-memory.d.ts +80 -0
  179. package/dist/vta/bridge-memory.d.ts.map +1 -0
  180. package/dist/vta/bridge-memory.js +162 -0
  181. package/dist/vta/bridge-memory.js.map +1 -0
  182. package/dist/vta/client.d.ts +40 -0
  183. package/dist/vta/client.d.ts.map +1 -0
  184. package/dist/vta/client.js +91 -0
  185. package/dist/vta/client.js.map +1 -0
  186. package/dist/vta/contexts.d.ts +60 -0
  187. package/dist/vta/contexts.d.ts.map +1 -0
  188. package/dist/vta/contexts.js +118 -0
  189. package/dist/vta/contexts.js.map +1 -0
  190. package/dist/vta/didcomm.d.ts +57 -0
  191. package/dist/vta/didcomm.d.ts.map +1 -0
  192. package/dist/vta/didcomm.js +138 -0
  193. package/dist/vta/didcomm.js.map +1 -0
  194. package/dist/vta/errors.d.ts +20 -0
  195. package/dist/vta/errors.d.ts.map +1 -0
  196. package/dist/vta/errors.js +64 -0
  197. package/dist/vta/errors.js.map +1 -0
  198. package/dist/vta/index.d.ts +15 -0
  199. package/dist/vta/index.d.ts.map +1 -0
  200. package/dist/vta/index.js +15 -0
  201. package/dist/vta/index.js.map +1 -0
  202. package/dist/vta/mediation.d.ts +80 -0
  203. package/dist/vta/mediation.d.ts.map +1 -0
  204. package/dist/vta/mediation.js +29 -0
  205. package/dist/vta/mediation.js.map +1 -0
  206. package/dist/vta/mediator-client.d.ts +66 -0
  207. package/dist/vta/mediator-client.d.ts.map +1 -0
  208. package/dist/vta/mediator-client.js +139 -0
  209. package/dist/vta/mediator-client.js.map +1 -0
  210. package/dist/vta/pickup.d.ts +81 -0
  211. package/dist/vta/pickup.d.ts.map +1 -0
  212. package/dist/vta/pickup.js +30 -0
  213. package/dist/vta/pickup.js.map +1 -0
  214. package/dist/vta/protocol.d.ts +76 -0
  215. package/dist/vta/protocol.d.ts.map +1 -0
  216. package/dist/vta/protocol.js +30 -0
  217. package/dist/vta/protocol.js.map +1 -0
  218. package/dist/vta/smoke.d.ts +59 -0
  219. package/dist/vta/smoke.d.ts.map +1 -0
  220. package/dist/vta/smoke.js +408 -0
  221. package/dist/vta/smoke.js.map +1 -0
  222. package/dist/vta/transport.d.ts +55 -0
  223. package/dist/vta/transport.d.ts.map +1 -0
  224. package/dist/vta/transport.js +2 -0
  225. package/dist/vta/transport.js.map +1 -0
  226. package/dist/vta/types.d.ts +50 -0
  227. package/dist/vta/types.d.ts.map +1 -0
  228. package/dist/vta/types.js +2 -0
  229. package/dist/vta/types.js.map +1 -0
  230. package/dist/vta/wallet-session.d.ts +87 -0
  231. package/dist/vta/wallet-session.d.ts.map +1 -0
  232. package/dist/vta/wallet-session.js +106 -0
  233. package/dist/vta/wallet-session.js.map +1 -0
  234. package/dist/webauthn/base64url.d.ts +3 -0
  235. package/dist/webauthn/base64url.d.ts.map +1 -0
  236. package/dist/webauthn/base64url.js +17 -0
  237. package/dist/webauthn/base64url.js.map +1 -0
  238. package/dist/webauthn/index.d.ts +4 -0
  239. package/dist/webauthn/index.d.ts.map +1 -0
  240. package/dist/webauthn/index.js +4 -0
  241. package/dist/webauthn/index.js.map +1 -0
  242. package/dist/webauthn/multikey.d.ts +26 -0
  243. package/dist/webauthn/multikey.d.ts.map +1 -0
  244. package/dist/webauthn/multikey.js +91 -0
  245. package/dist/webauthn/multikey.js.map +1 -0
  246. package/dist/webauthn/register.d.ts +36 -0
  247. package/dist/webauthn/register.d.ts.map +1 -0
  248. package/dist/webauthn/register.js +77 -0
  249. package/dist/webauthn/register.js.map +1 -0
  250. package/package.json +56 -0
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # @openvtc/pnm-core
2
+
3
+ Browser-side bridge between **WebAuthn passkeys** and **VTA-managed
4
+ DIDs**. Lets a relying party prove the user controls a DID hosted in
5
+ a remote Verifiable Trust Agent (VTA) by performing a passkey
6
+ ceremony in the browser — no DID private keys ever leave the VTA,
7
+ and no long-lived bearer token sits in browser storage. Speaks both
8
+ REST and **full DIDComm v2** to the VTA, including when the VTA is
9
+ private-network and only reachable via a mediator.
10
+
11
+ This package is the shared TypeScript library that backs the
12
+ [Personal Network Manager browser
13
+ plugin](https://github.com/OpenVTC/vta-browser-plugin): both the
14
+ [PWA](https://github.com/OpenVTC/vta-browser-plugin/tree/main/packages/pwa)
15
+ and the
16
+ [Manifest v3 extension](https://github.com/OpenVTC/vta-browser-plugin/tree/main/packages/extension)
17
+ are thin shells over it. External consumers can use it directly to
18
+ build mobile companions, desktop wallets, or RP-side integrations
19
+ that need the same flows without the bundled UI.
20
+
21
+ ## Install
22
+
23
+ ```sh
24
+ npm install @openvtc/pnm-core
25
+ ```
26
+
27
+ ## What it gives you
28
+
29
+ | Sub-module | Surface |
30
+ |---|---|
31
+ | **`@openvtc/pnm-core/webauthn`** | Passkey enrol / login ceremonies, COSE-key extraction, DID `verificationMethod` builder, PRF-derived secret-wrap helpers. |
32
+ | **`@openvtc/pnm-core/did`** | Multikey ↔ JWK conversion, DID-URL parsing, did:webvh log resolution. |
33
+ | **`@openvtc/pnm-core/vta`** | Typed REST + DIDComm transports against a VTA daemon. Mirrors the [`vta-sdk`](https://crates.io/crates/vta-sdk) Rust client's surface. |
34
+ | Plus modules for | SIOPv2 / OpenID4VP RP-side helpers, sealed-bootstrap provisioning, vault proxy-login flows, Trust-Task envelope construction, indexed-DB key/value persistence. |
35
+
36
+ The package's [`src/index.ts`](https://github.com/OpenVTC/vta-browser-plugin/blob/main/packages/core/src/index.ts)
37
+ re-exports everything from a single entry; the slash-suffixed
38
+ sub-entries above are an optional convenience for callers who only
39
+ want a slice of the surface.
40
+
41
+ ## Minimal example — passkey enrolment
42
+
43
+ ```ts
44
+ import {
45
+ beginEnrolment,
46
+ finishEnrolment,
47
+ type WebauthnEnrolmentChallenge,
48
+ } from "@openvtc/pnm-core";
49
+
50
+ // 1. Ask the VTA for an enrolment challenge for the named DID.
51
+ const challenge: WebauthnEnrolmentChallenge = await vtaClient.enrolBegin({
52
+ did: "did:webvh:example.com:alice",
53
+ });
54
+
55
+ // 2. Run the WebAuthn create() ceremony in the browser.
56
+ const credential = await beginEnrolment(challenge);
57
+
58
+ // 3. Submit the assertion. The VTA verifies it, appends the COSE
59
+ // public key as a `verificationMethod` on the WebVH log, and
60
+ // publishes the new DID-document revision.
61
+ const result = await finishEnrolment(credential, challenge.session_id);
62
+ ```
63
+
64
+ ## Wire compatibility
65
+
66
+ This package is byte-compatible with:
67
+
68
+ - The Rust [`vta-sdk`](https://crates.io/crates/vta-sdk) — typed VTA client used by the `pnm` CLI and other server-side consumers.
69
+ - The Rust [`did-hosting-client`](https://github.com/affinidi/affinidi-webvh-service/tree/main/did-hosting-client) — typed WebVH hosting client.
70
+ - The TypeScript [`@openvtc/vti-didcomm-js`](https://www.npmjs.com/package/@openvtc/vti-didcomm-js) — DIDComm v2 framing helpers (a runtime dependency of this package).
71
+ - The TypeScript [`@openvtc/trust-tasks`](https://www.npmjs.com/package/@openvtc/trust-tasks) — generated payload types for the [Trust Tasks framework](https://trusttasks.org).
72
+
73
+ A change to the wire surface is made in [`dtgwg-trust-tasks-tf`](https://github.com/trustoverip/dtgwg-trust-tasks-tf)
74
+ first, regenerates the Rust + TS bindings, and only then lands in
75
+ this package — see the project's spec-first development discipline.
76
+
77
+ ## Architecture
78
+
79
+ ```
80
+ ┌──────────────┐ WebAuthn ┌────────────────┐
81
+ │ Browser │ ───────────────▶ │ Authenticator │ (Touch ID,
82
+ │ (PWA / ext) │ ◀─────────────── │ / Passkey │ Windows Hello,
83
+ └──────┬───────┘ pubkey + sig └────────────────┘ YubiKey, …)
84
+
85
+ │ enrol(passkey_pubkey) verify(assertion)
86
+ ▼ ▲
87
+ ┌──────────────┐ ┌───────┴────────┐
88
+ │ VTA │ ── WebVH update ─────▶│ Public DID doc │
89
+ │ (remote) │ │ (resolvable by │
90
+ └──────────────┘ │ any verifier) │
91
+ └────────────────┘
92
+ ```
93
+
94
+ A passkey is enrolled as a `verificationMethod` (purpose:
95
+ `authentication`) in the DID document the VTA publishes via WebVH.
96
+ Any verifier that resolves the DID can then validate a WebAuthn
97
+ assertion against the embedded public key without ever talking to
98
+ the VTA — the DID document *is* the trust anchor.
99
+
100
+ ## Browser / runtime support
101
+
102
+ - Modern browsers with WebAuthn level 2 + WebCrypto (Chrome 108+,
103
+ Safari 17+, Firefox 122+).
104
+ - Node 20+ for server-side use (the WebAuthn-specific entry points
105
+ are no-ops in non-browser contexts; the DID / VTA / DIDComm
106
+ transports work everywhere).
107
+
108
+ ESM-only — no CommonJS build.
109
+
110
+ ## Versioning
111
+
112
+ Pre-1.0 (`0.x`) — breaking changes may land in minor bumps. The
113
+ internal contract this package depends on (`@openvtc/vti-didcomm-js`,
114
+ `@openvtc/trust-tasks`) follows the same cadence. Once the
115
+ underlying `SPEC.md` reaches 1.0 this package will follow.
116
+
117
+ ## License
118
+
119
+ Apache-2.0. See [LICENSE](https://github.com/OpenVTC/vta-browser-plugin/blob/main/LICENSE)
120
+ at the repo root.
121
+
122
+ ## Contributing
123
+
124
+ Source lives in
125
+ [`OpenVTC/vta-browser-plugin`](https://github.com/OpenVTC/vta-browser-plugin)
126
+ under `packages/core/`. See the
127
+ [root README](https://github.com/OpenVTC/vta-browser-plugin#readme)
128
+ for the workspace layout, development setup, and the smoke-test
129
+ harness.
@@ -0,0 +1,19 @@
1
+ export interface DeriveSigningKeyIdResult {
2
+ /** The DID the caller asked us to derive for. Echoed for symmetry. */
3
+ did: string;
4
+ /** Plausible verification-method ids the holder could sign with.
5
+ * Empty when resolution failed; one entry for the trivial case
6
+ * (did:key or single-key DIDs); multiple for DIDs with several
7
+ * authentication keys. The popup auto-fills only on
8
+ * `candidates.length === 1`. */
9
+ candidates: string[];
10
+ /** Human-readable resolution error (network / structural / hash
11
+ * chain), if any. Surfaces to the operator so they know whether
12
+ * to type the kid by hand or fix the DID. */
13
+ error?: string;
14
+ }
15
+ /** Derive the verification-method id (`signingKeyId`) candidates from
16
+ * the given DID. Never throws — failures land as `candidates: []` +
17
+ * an `error` string. */
18
+ export declare function deriveSigningKeyId(did: string): Promise<DeriveSigningKeyIdResult>;
19
+ //# sourceMappingURL=derive-signing-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derive-signing-key.d.ts","sourceRoot":"","sources":["../../src/did/derive-signing-key.ts"],"names":[],"mappings":"AAkCA,MAAM,WAAW,wBAAwB;IACvC,sEAAsE;IACtE,GAAG,EAAE,MAAM,CAAC;IACZ;;;;qCAIiC;IACjC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB;;kDAE8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;yBAEyB;AACzB,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAkDvF"}
@@ -0,0 +1,96 @@
1
+ // Derive a candidate `signingKeyId` (verification-method id) from a
2
+ // DID. Used by the popup's AddEntryForm to auto-fill the field when
3
+ // the operator types a principal DID — saves them looking up
4
+ // `<did>#key-0` style fragments by hand.
5
+ //
6
+ // Resolution strategy per method:
7
+ //
8
+ // - **did:key**: lexical. `did:key:zXxx` decomposes to
9
+ // `did:key:zXxx#zXxx` — the multibase tag IS the verification-
10
+ // method fragment. No network round-trip.
11
+ //
12
+ // - **did:peer:2**: self-resolving from the DID identifier
13
+ // itself; the keys are inline-encoded. The wallet's existing
14
+ // resolver in `vti-didcomm-js` handles this offline.
15
+ //
16
+ // - **did:webvh** / **did:web**: requires resolving the DID
17
+ // document over the network. The resolver in `vti-didcomm-js`
18
+ // walks the webvh log + verifies every Data Integrity proof,
19
+ // so a successful resolve is a real attestation.
20
+ //
21
+ // Selection: when the resolved DID document has a single
22
+ // `authentication` (or `assertionMethod`) entry, return its id and
23
+ // `candidates.length === 1` so the popup can auto-fill the field.
24
+ // When multiple are present, return them all so the popup can offer
25
+ // a picker — the operator picks which key signs.
26
+ //
27
+ // `verifyDid` already exists for the consent-prompt's DID resolution
28
+ // path; this file is a parallel surface focused on extracting the
29
+ // VM id rather than just validating resolution.
30
+ import { resolve as vtiResolve } from "@openvtc/vti-didcomm-js";
31
+ import { didMethod } from "./verify.js";
32
+ /** Derive the verification-method id (`signingKeyId`) candidates from
33
+ * the given DID. Never throws — failures land as `candidates: []` +
34
+ * an `error` string. */
35
+ export async function deriveSigningKeyId(did) {
36
+ const method = didMethod(did);
37
+ if (method === "key") {
38
+ // did:key:zXxx → did:key:zXxx#zXxx. The multibase tag (after
39
+ // `did:key:`) IS the fragment by convention.
40
+ const mb = did.slice("did:key:".length);
41
+ if (!mb.startsWith("z")) {
42
+ return { did, candidates: [], error: "did:key identifier is not base58btc multibase" };
43
+ }
44
+ return { did, candidates: [`${did}#${mb}`] };
45
+ }
46
+ if (method === "unknown") {
47
+ return { did, candidates: [], error: "Unrecognised DID method" };
48
+ }
49
+ // did:peer, did:webvh: full resolution. did:peer is offline; webvh
50
+ // hits the network and verifies the log.
51
+ try {
52
+ const resolution = (await vtiResolve(did, {}));
53
+ const resolverError = resolution.didResolutionMetadata?.error;
54
+ if (resolverError) {
55
+ return { did, candidates: [], error: resolverError };
56
+ }
57
+ const doc = resolution.didDocument;
58
+ if (!doc) {
59
+ return { did, candidates: [], error: "Resolver returned no DID document" };
60
+ }
61
+ // Prefer `authentication` (the signing-purpose-correct list for
62
+ // SIOP-style id_tokens). Fall back to `assertionMethod` if absent.
63
+ // Final fallback: enumerate `verificationMethod` ids — better to
64
+ // give the operator something than nothing.
65
+ const candidates = collectVmIds(doc.authentication) ||
66
+ collectVmIds(doc.assertionMethod) ||
67
+ collectVmIds(doc.verificationMethod) ||
68
+ [];
69
+ if (candidates.length === 0) {
70
+ return { did, candidates: [], error: "DID document has no usable verification methods" };
71
+ }
72
+ return { did, candidates };
73
+ }
74
+ catch (e) {
75
+ return { did, candidates: [], error: e instanceof Error ? e.message : String(e) };
76
+ }
77
+ }
78
+ /** Extract the `id` string of every verification-method reference,
79
+ * whether stored as a bare URL string or an embedded VM object.
80
+ * Returns `null` (not `[]`) when the input is `undefined` so the
81
+ * caller can short-circuit the `||` chain to the next purpose
82
+ * rather than landing on an empty list it would otherwise treat as
83
+ * authoritative. */
84
+ function collectVmIds(vms) {
85
+ if (!vms || vms.length === 0)
86
+ return null;
87
+ const out = [];
88
+ for (const entry of vms) {
89
+ if (typeof entry === "string")
90
+ out.push(entry);
91
+ else if (entry && typeof entry === "object" && typeof entry.id === "string")
92
+ out.push(entry.id);
93
+ }
94
+ return out.length > 0 ? out : null;
95
+ }
96
+ //# sourceMappingURL=derive-signing-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derive-signing-key.js","sourceRoot":"","sources":["../../src/did/derive-signing-key.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export * from "./derive-signing-key.js";
2
+ export * from "./verification-method.js";
3
+ export * from "./peer.js";
4
+ export * from "./verify.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/did/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from "./derive-signing-key.js";
2
+ export * from "./verification-method.js";
3
+ export * from "./peer.js";
4
+ export * from "./verify.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/did/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,37 @@
1
+ /** Abbreviated DIDComm service for a `did:peer:2` `S` segment. The
2
+ * abbreviation (`t`/`s`/`r`/`a`) is the did:peer:2 convention the resolver
3
+ * decodes back to a `DIDCommMessaging` service. */
4
+ export interface DidPeerService {
5
+ /** Service type. `"dm"` abbreviates `DIDCommMessaging` (the default). */
6
+ type?: string;
7
+ /** serviceEndpoint URI — for mediator-routed delivery this is the
8
+ * mediator's DID. */
9
+ serviceEndpoint: string;
10
+ /** Optional routing keys. */
11
+ routingKeys?: string[];
12
+ /** Accepted profiles (default `["didcomm/v2"]`). */
13
+ accept?: string[];
14
+ }
15
+ export interface DidPeer2 {
16
+ /** The full `did:peer:2` string. */
17
+ did: string;
18
+ /** Ed25519 authentication VM id — `<did>#key-2`. The SIOP `id_token` `kid`. */
19
+ authKid: string;
20
+ /** X25519 keyAgreement VM id — `<did>#key-1`. Used for DIDComm authcrypt. */
21
+ keyAgreementKid: string;
22
+ }
23
+ export interface CreateDidPeer2Args {
24
+ /** Ed25519 public key (authentication / signing). */
25
+ ed25519PublicKey: Uint8Array;
26
+ /** X25519 public key (keyAgreement / authcrypt). */
27
+ x25519PublicKey: Uint8Array;
28
+ /** Optional DIDComm service to advertise (e.g. the wallet's mediator). */
29
+ service?: DidPeerService;
30
+ }
31
+ /**
32
+ * Build a `did:peer:2` from an Ed25519 (auth) + X25519 (keyAgreement) key
33
+ * pair and an optional DIDComm service. Returns the DID plus the
34
+ * deterministic VM ids (`#key-1` = keyAgreement, `#key-2` = authentication).
35
+ */
36
+ export declare function createDidPeer2(args: CreateDidPeer2Args): DidPeer2;
37
+ //# sourceMappingURL=peer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peer.d.ts","sourceRoot":"","sources":["../../src/did/peer.ts"],"names":[],"mappings":"AAqBA;;oDAEoD;AACpD,MAAM,WAAW,cAAc;IAC7B,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;0BACsB;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,qDAAqD;IACrD,gBAAgB,EAAE,UAAU,CAAC;IAC7B,oDAAoD;IACpD,eAAe,EAAE,UAAU,CAAC;IAC5B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,QAAQ,CA2BjE"}
@@ -0,0 +1,49 @@
1
+ // did:peer:2 (numalgo 2) generation for the wallet's holder identity.
2
+ //
3
+ // Unlike `did:key`, a `did:peer:2` can encode a service endpoint inline, so
4
+ // the wallet can advertise its mediator and be *reachable* for inbound
5
+ // DIDComm (RP-initiated confirm/approve requests) — see the RP→wallet
6
+ // trigger design. The DID is self-contained and resolves with no network.
7
+ //
8
+ // Segment order is FIXED — keyAgreement (`E`, X25519) first, authentication
9
+ // (`V`, Ed25519) second, service (`S`) last — because resolvers number
10
+ // verification methods **positionally** (`#key-1`, `#key-2`, …) in the order
11
+ // segments appear. Verified against the affinidi `DIDCacheClient` (the RP's
12
+ // resolver): for `did:peer:2.E….V….S…` it emits `#key-1` = the X25519 KA
13
+ // key and `#key-2` = the Ed25519 auth key, as `Multikey`/`publicKeyMultibase`.
14
+ // So the SIOP `id_token` `kid` is `<did>#key-2` and the authcrypt
15
+ // keyAgreement kid is `<did>#key-1`.
16
+ import { base64url, multibase } from "@openvtc/vti-didcomm-js";
17
+ const X25519_PUB = multibase.MULTICODEC.X25519_PUB;
18
+ const ED25519_PUB = multibase.MULTICODEC.ED25519_PUB;
19
+ /**
20
+ * Build a `did:peer:2` from an Ed25519 (auth) + X25519 (keyAgreement) key
21
+ * pair and an optional DIDComm service. Returns the DID plus the
22
+ * deterministic VM ids (`#key-1` = keyAgreement, `#key-2` = authentication).
23
+ */
24
+ export function createDidPeer2(args) {
25
+ // E (keyAgreement, X25519) first → #key-1; V (authentication, Ed25519)
26
+ // second → #key-2. Order is load-bearing (positional VM numbering).
27
+ const kaMultibase = multibase.encodeMultikey(X25519_PUB, args.x25519PublicKey);
28
+ const authMultibase = multibase.encodeMultikey(ED25519_PUB, args.ed25519PublicKey);
29
+ let did = `did:peer:2.E${kaMultibase}.V${authMultibase}`;
30
+ if (args.service) {
31
+ const s = args.service;
32
+ // Abbreviated DIDComm service; key insertion order t,s,r,a matches the
33
+ // did:peer:2 convention. `r` omitted when there are no routing keys.
34
+ const abbreviated = {
35
+ t: s.type ?? "dm",
36
+ s: s.serviceEndpoint,
37
+ ...(s.routingKeys && s.routingKeys.length > 0 ? { r: s.routingKeys } : {}),
38
+ a: s.accept ?? ["didcomm/v2"],
39
+ };
40
+ const encoded = base64url.encode(new TextEncoder().encode(JSON.stringify(abbreviated)));
41
+ did += `.S${encoded}`;
42
+ }
43
+ return {
44
+ did,
45
+ authKid: `${did}#key-2`,
46
+ keyAgreementKid: `${did}#key-1`,
47
+ };
48
+ }
49
+ //# sourceMappingURL=peer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peer.js","sourceRoot":"","sources":["../../src/did/peer.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,EAAE;AACF,4EAA4E;AAC5E,uEAAuE;AACvE,sEAAsE;AACtE,0EAA0E;AAC1E,EAAE;AACF,4EAA4E;AAC5E,uEAAuE;AACvE,6EAA6E;AAC7E,4EAA4E;AAC5E,yEAAyE;AACzE,+EAA+E;AAC/E,kEAAkE;AAClE,qCAAqC;AAErC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAE/D,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC;AACnD,MAAM,WAAW,GAAG,SAAS,CAAC,UAAU,CAAC,WAAW,CAAC;AAmCrD;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAwB;IACrD,uEAAuE;IACvE,oEAAoE;IACpE,MAAM,WAAW,GAAG,SAAS,CAAC,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;IAC/E,MAAM,aAAa,GAAG,SAAS,CAAC,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAEnF,IAAI,GAAG,GAAG,eAAe,WAAW,KAAK,aAAa,EAAE,CAAC;IAEzD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;QACvB,uEAAuE;QACvE,qEAAqE;QACrE,MAAM,WAAW,GAA4B;YAC3C,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI;YACjB,CAAC,EAAE,CAAC,CAAC,eAAe;YACpB,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1E,CAAC,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC;SAC9B,CAAC;QACF,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACxF,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC;IACxB,CAAC;IAED,OAAO;QACL,GAAG;QACH,OAAO,EAAE,GAAG,GAAG,QAAQ;QACvB,eAAe,EAAE,GAAG,GAAG,QAAQ;KAChC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * A `verificationMethod` entry, in the shape we want appended to the
3
+ * VTA-managed DID document. Type `Multikey` is the W3C-recommended
4
+ * representation; `publicKeyMultibase` carries the base58btc-encoded
5
+ * multicodec-prefixed key.
6
+ *
7
+ * The `webauthn*` extensions are non-core but explicit: any verifier
8
+ * resolving the DID can find the VM by `credentialId` hash and verify
9
+ * a WebAuthn assertion against `publicKeyMultibase` directly — no
10
+ * round-trip to the VTA required.
11
+ */
12
+ export interface PasskeyVerificationMethod {
13
+ id: string;
14
+ type: "Multikey";
15
+ controller: string;
16
+ publicKeyMultibase: string;
17
+ /** WebAuthn credential id, base64url-encoded. */
18
+ webauthnCredentialId: string;
19
+ /** Transport hints the authenticator reported (e.g. "internal", "hybrid"). */
20
+ webauthnTransports?: AuthenticatorTransport[];
21
+ /**
22
+ * Optional friendly label set by the operator (e.g. "MacBook Touch
23
+ * ID", "YubiKey 5C"). Surfaced in UI; not used for verification.
24
+ */
25
+ label?: string;
26
+ }
27
+ export interface BuildVerificationMethodArgs {
28
+ did: string;
29
+ credentialId: string;
30
+ credentialIdBytes: Uint8Array;
31
+ publicKeyMultikey: string;
32
+ transports?: AuthenticatorTransport[];
33
+ label?: string;
34
+ }
35
+ /**
36
+ * Derive the VM fragment from the credential id. SHA-256 keeps the
37
+ * fragment short and stable while still being deterministic — a
38
+ * verifier given a WebAuthn assertion can recompute the fragment
39
+ * from `credential.id` and look it up in the DID document.
40
+ */
41
+ export declare function passkeyVerificationMethodFragment(credentialIdBytes: Uint8Array): Promise<string>;
42
+ export declare function buildPasskeyVerificationMethod(args: BuildVerificationMethodArgs): Promise<PasskeyVerificationMethod>;
43
+ //# sourceMappingURL=verification-method.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification-method.d.ts","sourceRoot":"","sources":["../../src/did/verification-method.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,8EAA8E;IAC9E,kBAAkB,CAAC,EAAE,sBAAsB,EAAE,CAAC;IAC9C;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,UAAU,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;;;;GAKG;AACH,wBAAsB,iCAAiC,CACrD,iBAAiB,EAAE,UAAU,GAC5B,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED,wBAAsB,8BAA8B,CAClD,IAAI,EAAE,2BAA2B,GAChC,OAAO,CAAC,yBAAyB,CAAC,CAgBpC"}
@@ -0,0 +1,32 @@
1
+ import { bytesToBase64url } from "../webauthn/base64url.js";
2
+ async function sha256(bytes) {
3
+ return new Uint8Array(await crypto.subtle.digest("SHA-256", bytes));
4
+ }
5
+ /**
6
+ * Derive the VM fragment from the credential id. SHA-256 keeps the
7
+ * fragment short and stable while still being deterministic — a
8
+ * verifier given a WebAuthn assertion can recompute the fragment
9
+ * from `credential.id` and look it up in the DID document.
10
+ */
11
+ export async function passkeyVerificationMethodFragment(credentialIdBytes) {
12
+ const hash = await sha256(credentialIdBytes);
13
+ return `passkey-${bytesToBase64url(hash)}`;
14
+ }
15
+ export async function buildPasskeyVerificationMethod(args) {
16
+ const fragment = await passkeyVerificationMethodFragment(args.credentialIdBytes);
17
+ const vm = {
18
+ id: `${args.did}#${fragment}`,
19
+ type: "Multikey",
20
+ controller: args.did,
21
+ publicKeyMultibase: args.publicKeyMultikey,
22
+ webauthnCredentialId: args.credentialId,
23
+ };
24
+ if (args.transports && args.transports.length > 0) {
25
+ vm.webauthnTransports = args.transports;
26
+ }
27
+ if (args.label) {
28
+ vm.label = args.label;
29
+ }
30
+ return vm;
31
+ }
32
+ //# sourceMappingURL=verification-method.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification-method.js","sourceRoot":"","sources":["../../src/did/verification-method.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAsC5D,KAAK,UAAU,MAAM,CAAC,KAAiB;IACrC,OAAO,IAAI,UAAU,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,KAAqB,CAAC,CAAC,CAAC;AACtF,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACrD,iBAA6B;IAE7B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAC7C,OAAO,WAAW,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,IAAiC;IAEjC,MAAM,QAAQ,GAAG,MAAM,iCAAiC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACjF,MAAM,EAAE,GAA8B;QACpC,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,QAAQ,EAAE;QAC7B,IAAI,EAAE,UAAU;QAChB,UAAU,EAAE,IAAI,CAAC,GAAG;QACpB,kBAAkB,EAAE,IAAI,CAAC,iBAAiB;QAC1C,oBAAoB,EAAE,IAAI,CAAC,YAAY;KACxC,CAAC;IACF,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClD,EAAE,CAAC,kBAAkB,GAAG,IAAI,CAAC,UAAU,CAAC;IAC1C,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACxB,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,49 @@
1
+ export type DidMethod = "webvh" | "peer" | "key" | "unknown";
2
+ export interface VerifyDidResult {
3
+ /** Canonical DID under verification. */
4
+ did: string;
5
+ /** Parsed DID method. `unknown` if the input is not a recognisable DID. */
6
+ method: DidMethod;
7
+ /** True if resolution succeeded. For did:webvh this implies the SCID + log
8
+ * hash chain + every Data Integrity proof verified. For did:peer/did:key
9
+ * it implies the identifier was structurally valid. */
10
+ resolved: boolean;
11
+ /** For did:webvh — the host the DID identifies (extracted from the DID,
12
+ * not the resolved document, so the operator sees what the wallet asked
13
+ * for). The DID is `did:webvh:<scid>:<host>[:<path>...]`. */
14
+ domain?: string;
15
+ /** Human-readable error if resolution failed. */
16
+ error?: string;
17
+ }
18
+ /**
19
+ * Parse the method of a DID string. Cheap, structural — does not resolve.
20
+ */
21
+ export declare function didMethod(did: string): DidMethod;
22
+ /**
23
+ * Extract the host portion of a `did:webvh:<scid>:<host>[:path:...]`. Returns
24
+ * `undefined` for non-webvh inputs. The path-style segments after the host
25
+ * are intentionally discarded — the operator-facing display only needs the
26
+ * host to compare against the page origin.
27
+ *
28
+ * webvh's wire format percent-encodes the host's `:` and `/`; we leave them
29
+ * encoded because the consent UI only matches on hostname (which never
30
+ * contains either).
31
+ */
32
+ export declare function didWebvhDomain(did: string): string | undefined;
33
+ /**
34
+ * Resolve and validate an RP DID. Never throws — failures are returned via
35
+ * `resolved: false` and `error`, because the consent UI wants to *render*
36
+ * the error rather than crash.
37
+ */
38
+ export declare function verifyDid(did: string): Promise<VerifyDidResult>;
39
+ /**
40
+ * Decide whether a page origin's hostname is consistent with a did:webvh
41
+ * domain. Exact match or proper subdomain count as consistent. Anything
42
+ * else (sibling subdomain, unrelated host, etc.) is flagged.
43
+ *
44
+ * For non-webvh DIDs this returns `"not-applicable"` — there's no domain
45
+ * encoded in the DID, so the wallet has nothing to compare against.
46
+ */
47
+ export type OriginMatch = "match" | "subdomain" | "mismatch" | "not-applicable";
48
+ export declare function compareOriginToDidDomain(originHost: string | undefined, didDomain: string | undefined): OriginMatch;
49
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/did/verify.ts"],"names":[],"mappings":"AAkBA,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,MAAM,EAAE,SAAS,CAAC;IAClB;;4DAEwD;IACxD,QAAQ,EAAE,OAAO,CAAC;IAClB;;kEAE8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAKhD;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK9D;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA4BrE;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,gBAAgB,CAAC;AAEhF,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,WAAW,CAMb"}
@@ -0,0 +1,89 @@
1
+ // DID verification for the consent prompt.
2
+ //
3
+ // Before the wallet logs into an RP, the consent popup wants to tell the
4
+ // operator whether the rpDid actually resolves — and, for did:webvh, whether
5
+ // its declared domain is consistent with the page origin the request came
6
+ // from. This is the operator-facing complement to origin pinning: pinning
7
+ // catches "this site swapped which RP it points at"; verification catches
8
+ // "this site is pointing at an RP whose DID does not resolve" or "claims an
9
+ // RP whose domain has nothing to do with the page".
10
+ //
11
+ // did:webvh resolution is cryptographic (the library walks the log, verifies
12
+ // the SCID/hash chain, and verifies every Data Integrity proof on each entry)
13
+ // — a successful resolve is a real attestation, not just "fetch returned 200".
14
+ // did:peer / did:key are self-certifying (the keys are encoded in the id), so
15
+ // resolution is purely structural validation.
16
+ import { resolve as vtiResolve } from "@openvtc/vti-didcomm-js";
17
+ /**
18
+ * Parse the method of a DID string. Cheap, structural — does not resolve.
19
+ */
20
+ export function didMethod(did) {
21
+ if (did.startsWith("did:webvh:"))
22
+ return "webvh";
23
+ if (did.startsWith("did:peer:"))
24
+ return "peer";
25
+ if (did.startsWith("did:key:"))
26
+ return "key";
27
+ return "unknown";
28
+ }
29
+ /**
30
+ * Extract the host portion of a `did:webvh:<scid>:<host>[:path:...]`. Returns
31
+ * `undefined` for non-webvh inputs. The path-style segments after the host
32
+ * are intentionally discarded — the operator-facing display only needs the
33
+ * host to compare against the page origin.
34
+ *
35
+ * webvh's wire format percent-encodes the host's `:` and `/`; we leave them
36
+ * encoded because the consent UI only matches on hostname (which never
37
+ * contains either).
38
+ */
39
+ export function didWebvhDomain(did) {
40
+ if (!did.startsWith("did:webvh:"))
41
+ return undefined;
42
+ const parts = did.split(":");
43
+ // ["did", "webvh", "<scid>", "<host>", ...path]
44
+ return parts[3];
45
+ }
46
+ /**
47
+ * Resolve and validate an RP DID. Never throws — failures are returned via
48
+ * `resolved: false` and `error`, because the consent UI wants to *render*
49
+ * the error rather than crash.
50
+ */
51
+ export async function verifyDid(did) {
52
+ const method = didMethod(did);
53
+ const domain = method === "webvh" ? didWebvhDomain(did) : undefined;
54
+ const base = {
55
+ did,
56
+ method,
57
+ resolved: false,
58
+ ...(domain ? { domain } : {}),
59
+ };
60
+ if (method === "unknown") {
61
+ return { ...base, error: "Unrecognised DID method" };
62
+ }
63
+ try {
64
+ const resolution = (await vtiResolve(did, {}));
65
+ const resolverError = resolution.didResolutionMetadata?.error;
66
+ if (resolverError) {
67
+ return { ...base, error: resolverError };
68
+ }
69
+ if (!resolution.didDocument?.id) {
70
+ return { ...base, error: "Resolver returned no DID document" };
71
+ }
72
+ return { ...base, resolved: true };
73
+ }
74
+ catch (e) {
75
+ return { ...base, error: e instanceof Error ? e.message : String(e) };
76
+ }
77
+ }
78
+ export function compareOriginToDidDomain(originHost, didDomain) {
79
+ if (!didDomain)
80
+ return "not-applicable";
81
+ if (!originHost)
82
+ return "mismatch";
83
+ if (originHost === didDomain)
84
+ return "match";
85
+ if (originHost.endsWith(`.${didDomain}`))
86
+ return "subdomain";
87
+ return "mismatch";
88
+ }
89
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/did/verify.ts"],"names":[],"mappings":"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"}