Skip to content

feat: read did:webs (JsonWebKey) verification methods by relationship (VTI-KEY-003) - #429

Merged
stormer78 merged 1 commit into
mainfrom
feat/did-webs-keys
Nov 12, 2026
Merged

stormer78 merged 1 commit into
mainfrom
feat/did-webs-keys

Conversation

@stormer78

Copy link
Copy Markdown
Contributor

The VTI spec now requires every party to resolve did:webs (VTI-KEY-003). A did:webs document carries JsonWebKey verification methods, and a key-role VTA keeps a separate key for each relationship. This PR makes the plugin's own DID-document key reads handle that: keys are picked by verification relationship, never "any Ed25519" and never by fragment endsWith.

New: packages/core/src/did/vm-key.ts, a rule-for-rule port of vti-didcomm-js#39 (publicKeyOf, selectKey, x25519KeyAgreement).

  • It fails closed on a missing or unknown type, a wrong encoding for the type, an unsupported curve, a JWK with d, or a revoked method.
  • It is marked to be replaced by the library's verification-method export once a release includes it (R4.1).

Sites

  1. trust-tasks/verify.ts: the key comes from the required purpose (authentication for step-up, consent and replies; assertionMethod for record bodies and domain linkage), or else the proof's own proofPurpose. Both encodings are read and ids match exactly. Behaviour change: a proof whose key isn't listed under the purpose it claims no longer verifies.
  2. vta/tsp-vid.ts: the TSP signing key is the first Ed25519 authentication key (tsp-enablement D5), with no fallback. derefVm is gone, and a JWK with d is refused.
  3. vtc/directory-card.ts and vtc/domain-linkage.ts: assertion keys come through selectKey.
  4. did/verify.ts: knows did:webs; the host is checked before resolving (egress-guard.ts). derive-signing-key.ts has no verificationMethod[] fallback for did:webs. The extension's confirm screen shows "key event log verified".

Tests: packages/core/tests/did.webs-keys.mjs, using did:webs VTA and mediator fixtures with real signatures from vti-didcomm-js#39, plus a did:webvh regression and fail-closed cases for each site. tsp.vid.mjs is extended. Lint, build, tests, bundle assertions and the store package check all pass locally.

After vti-didcomm-js ships #38/#39:

… (VTI-KEY-003)

Every party must resolve did:webs (VTI-KEY-003). A did:webs document
carries JsonWebKey methods (publicKeyJwk, ids <did>#<CESR key>), and a
VTA with key roles (VTI-KEY-173) lists a different key under each
relationship: the attestation key under assertionMethod, the
operational key under authentication, and X25519 key agreement after
a P-256 one. The plugin's own DID-document key readers assumed
publicKeyMultibase, fell back to "any Ed25519 key", or matched ids by
fragment suffix — each of which picks the wrong key for that document.

One reader now serves every site: core/src/did/vm-key.ts (publicKeyOf,
selectKey, x25519KeyAgreement), a port of vti-didcomm-js #39's
verification-method module, to be replaced by that export when the
plugin moves to the release that ships it (R4.1). It fails closed on an
unknown or missing type, an encoding the type does not carry, both
encodings, an unsupported curve, a JWK carrying d, or a revoked method.

- trust-tasks/verify.ts: the proof key is read from the relationship
  the proof is for (the required purpose, else the proof's own
  proofPurpose), in either encoding; no endsWith fallback.
- vta/tsp-vid.ts: the VID signing key is the authentication key only
  (tsp-enablement D5); no "any Ed25519" fallback, exact dereference,
  type checks; rawFromOkpJwk refuses d.
- vtc/directory-card.ts assertionKeys and vtc/domain-linkage.ts
  assertionKey read assertionMethod through the same reader.
- did/verify.ts didMethod knows webs (didWebsDomain, host guarded before
  resolution); deriveSigningKeyId offers no bare verificationMethod ids
  for a did:webs.

Tests use vti-didcomm-js's did:webs party documents (VTA with key
roles, mediator), with a did:webvh regression and fail-closed cases at
each site.

Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
@stormer78
stormer78 merged commit 4118e44 into main Nov 12, 2026
4 checks passed
@stormer78
stormer78 deleted the feat/did-webs-keys branch November 12, 2026 09:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant