@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.
- package/README.md +129 -0
- package/dist/did/derive-signing-key.d.ts +19 -0
- package/dist/did/derive-signing-key.d.ts.map +1 -0
- package/dist/did/derive-signing-key.js +96 -0
- package/dist/did/derive-signing-key.js.map +1 -0
- package/dist/did/index.d.ts +5 -0
- package/dist/did/index.d.ts.map +1 -0
- package/dist/did/index.js +5 -0
- package/dist/did/index.js.map +1 -0
- package/dist/did/peer.d.ts +37 -0
- package/dist/did/peer.d.ts.map +1 -0
- package/dist/did/peer.js +49 -0
- package/dist/did/peer.js.map +1 -0
- package/dist/did/verification-method.d.ts +43 -0
- package/dist/did/verification-method.d.ts.map +1 -0
- package/dist/did/verification-method.js +32 -0
- package/dist/did/verification-method.js.map +1 -0
- package/dist/did/verify.d.ts +49 -0
- package/dist/did/verify.d.ts.map +1 -0
- package/dist/did/verify.js +89 -0
- package/dist/did/verify.js.map +1 -0
- package/dist/didcomm/index.d.ts +235 -0
- package/dist/didcomm/index.d.ts.map +1 -0
- package/dist/didcomm/index.js +415 -0
- package/dist/didcomm/index.js.map +1 -0
- package/dist/inbound/confirm.d.ts +50 -0
- package/dist/inbound/confirm.d.ts.map +1 -0
- package/dist/inbound/confirm.js +64 -0
- package/dist/inbound/confirm.js.map +1 -0
- package/dist/inbound/dedup.d.ts +9 -0
- package/dist/inbound/dedup.d.ts.map +1 -0
- package/dist/inbound/dedup.js +31 -0
- package/dist/inbound/dedup.js.map +1 -0
- package/dist/inbound/index.d.ts +3 -0
- package/dist/inbound/index.d.ts.map +1 -0
- package/dist/inbound/index.js +3 -0
- package/dist/inbound/index.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/onboarding/index.d.ts +2 -0
- package/dist/onboarding/index.d.ts.map +1 -0
- package/dist/onboarding/index.js +2 -0
- package/dist/onboarding/index.js.map +1 -0
- package/dist/onboarding/swap.d.ts +60 -0
- package/dist/onboarding/swap.d.ts.map +1 -0
- package/dist/onboarding/swap.js +148 -0
- package/dist/onboarding/swap.js.map +1 -0
- package/dist/provision/adopt.d.ts +31 -0
- package/dist/provision/adopt.d.ts.map +1 -0
- package/dist/provision/adopt.js +114 -0
- package/dist/provision/adopt.js.map +1 -0
- package/dist/provision/armor.d.ts +19 -0
- package/dist/provision/armor.d.ts.map +1 -0
- package/dist/provision/armor.js +243 -0
- package/dist/provision/armor.js.map +1 -0
- package/dist/provision/crc24.d.ts +5 -0
- package/dist/provision/crc24.d.ts.map +1 -0
- package/dist/provision/crc24.js +30 -0
- package/dist/provision/crc24.js.map +1 -0
- package/dist/provision/hpke.d.ts +17 -0
- package/dist/provision/hpke.d.ts.map +1 -0
- package/dist/provision/hpke.js +60 -0
- package/dist/provision/hpke.js.map +1 -0
- package/dist/provision/index.d.ts +10 -0
- package/dist/provision/index.d.ts.map +1 -0
- package/dist/provision/index.js +16 -0
- package/dist/provision/index.js.map +1 -0
- package/dist/provision/open.d.ts +28 -0
- package/dist/provision/open.d.ts.map +1 -0
- package/dist/provision/open.js +224 -0
- package/dist/provision/open.js.map +1 -0
- package/dist/provision/request.d.ts +65 -0
- package/dist/provision/request.d.ts.map +1 -0
- package/dist/provision/request.js +53 -0
- package/dist/provision/request.js.map +1 -0
- package/dist/provision/run.d.ts +76 -0
- package/dist/provision/run.d.ts.map +1 -0
- package/dist/provision/run.js +110 -0
- package/dist/provision/run.js.map +1 -0
- package/dist/provision/send.d.ts +85 -0
- package/dist/provision/send.d.ts.map +1 -0
- package/dist/provision/send.js +87 -0
- package/dist/provision/send.js.map +1 -0
- package/dist/provision/types.d.ts +110 -0
- package/dist/provision/types.d.ts.map +1 -0
- package/dist/provision/types.js +17 -0
- package/dist/provision/types.js.map +1 -0
- package/dist/rp-login/didcomm.d.ts +34 -0
- package/dist/rp-login/didcomm.d.ts.map +1 -0
- package/dist/rp-login/didcomm.js +72 -0
- package/dist/rp-login/didcomm.js.map +1 -0
- package/dist/rp-login/index.d.ts +3 -0
- package/dist/rp-login/index.d.ts.map +1 -0
- package/dist/rp-login/index.js +3 -0
- package/dist/rp-login/index.js.map +1 -0
- package/dist/rp-login/step-up.d.ts +43 -0
- package/dist/rp-login/step-up.d.ts.map +1 -0
- package/dist/rp-login/step-up.js +118 -0
- package/dist/rp-login/step-up.js.map +1 -0
- package/dist/siop/index.d.ts +3 -0
- package/dist/siop/index.d.ts.map +1 -0
- package/dist/siop/index.js +3 -0
- package/dist/siop/index.js.map +1 -0
- package/dist/siop/login-client.d.ts +29 -0
- package/dist/siop/login-client.d.ts.map +1 -0
- package/dist/siop/login-client.js +79 -0
- package/dist/siop/login-client.js.map +1 -0
- package/dist/siop/self-issued.d.ts +96 -0
- package/dist/siop/self-issued.d.ts.map +1 -0
- package/dist/siop/self-issued.js +162 -0
- package/dist/siop/self-issued.js.map +1 -0
- package/dist/store/holder-identity.d.ts +241 -0
- package/dist/store/holder-identity.d.ts.map +1 -0
- package/dist/store/holder-identity.js +441 -0
- package/dist/store/holder-identity.js.map +1 -0
- package/dist/store/index.d.ts +4 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +4 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/kv-store.d.ts +51 -0
- package/dist/store/kv-store.d.ts.map +1 -0
- package/dist/store/kv-store.js +100 -0
- package/dist/store/kv-store.js.map +1 -0
- package/dist/store/secret-wrap.d.ts +109 -0
- package/dist/store/secret-wrap.d.ts.map +1 -0
- package/dist/store/secret-wrap.js +85 -0
- package/dist/store/secret-wrap.js.map +1 -0
- package/dist/trust-tasks/index.d.ts +2 -0
- package/dist/trust-tasks/index.d.ts.map +1 -0
- package/dist/trust-tasks/index.js +2 -0
- package/dist/trust-tasks/index.js.map +1 -0
- package/dist/trust-tasks/sign.d.ts +31 -0
- package/dist/trust-tasks/sign.d.ts.map +1 -0
- package/dist/trust-tasks/sign.js +141 -0
- package/dist/trust-tasks/sign.js.map +1 -0
- package/dist/util/timing.d.ts +14 -0
- package/dist/util/timing.d.ts.map +1 -0
- package/dist/util/timing.js +20 -0
- package/dist/util/timing.js.map +1 -0
- package/dist/vault/delete.d.ts +19 -0
- package/dist/vault/delete.d.ts.map +1 -0
- package/dist/vault/delete.js +35 -0
- package/dist/vault/delete.js.map +1 -0
- package/dist/vault/index.d.ts +8 -0
- package/dist/vault/index.d.ts.map +1 -0
- package/dist/vault/index.js +7 -0
- package/dist/vault/index.js.map +1 -0
- package/dist/vault/list.d.ts +96 -0
- package/dist/vault/list.d.ts.map +1 -0
- package/dist/vault/list.js +106 -0
- package/dist/vault/list.js.map +1 -0
- package/dist/vault/proxy-login.d.ts +100 -0
- package/dist/vault/proxy-login.d.ts.map +1 -0
- package/dist/vault/proxy-login.js +106 -0
- package/dist/vault/proxy-login.js.map +1 -0
- package/dist/vault/release.d.ts +33 -0
- package/dist/vault/release.d.ts.map +1 -0
- package/dist/vault/release.js +83 -0
- package/dist/vault/release.js.map +1 -0
- package/dist/vault/sign-trust-task.d.ts +26 -0
- package/dist/vault/sign-trust-task.d.ts.map +1 -0
- package/dist/vault/sign-trust-task.js +53 -0
- package/dist/vault/sign-trust-task.js.map +1 -0
- package/dist/vault/transport.d.ts +50 -0
- package/dist/vault/transport.d.ts.map +1 -0
- package/dist/vault/transport.js +118 -0
- package/dist/vault/transport.js.map +1 -0
- package/dist/vault/upsert.d.ts +102 -0
- package/dist/vault/upsert.d.ts.map +1 -0
- package/dist/vault/upsert.js +92 -0
- package/dist/vault/upsert.js.map +1 -0
- package/dist/vta/bridge-mediator-session.d.ts +26 -0
- package/dist/vta/bridge-mediator-session.d.ts.map +1 -0
- package/dist/vta/bridge-mediator-session.js +37 -0
- package/dist/vta/bridge-mediator-session.js.map +1 -0
- package/dist/vta/bridge-memory.d.ts +80 -0
- package/dist/vta/bridge-memory.d.ts.map +1 -0
- package/dist/vta/bridge-memory.js +162 -0
- package/dist/vta/bridge-memory.js.map +1 -0
- package/dist/vta/client.d.ts +40 -0
- package/dist/vta/client.d.ts.map +1 -0
- package/dist/vta/client.js +91 -0
- package/dist/vta/client.js.map +1 -0
- package/dist/vta/contexts.d.ts +60 -0
- package/dist/vta/contexts.d.ts.map +1 -0
- package/dist/vta/contexts.js +118 -0
- package/dist/vta/contexts.js.map +1 -0
- package/dist/vta/didcomm.d.ts +57 -0
- package/dist/vta/didcomm.d.ts.map +1 -0
- package/dist/vta/didcomm.js +138 -0
- package/dist/vta/didcomm.js.map +1 -0
- package/dist/vta/errors.d.ts +20 -0
- package/dist/vta/errors.d.ts.map +1 -0
- package/dist/vta/errors.js +64 -0
- package/dist/vta/errors.js.map +1 -0
- package/dist/vta/index.d.ts +15 -0
- package/dist/vta/index.d.ts.map +1 -0
- package/dist/vta/index.js +15 -0
- package/dist/vta/index.js.map +1 -0
- package/dist/vta/mediation.d.ts +80 -0
- package/dist/vta/mediation.d.ts.map +1 -0
- package/dist/vta/mediation.js +29 -0
- package/dist/vta/mediation.js.map +1 -0
- package/dist/vta/mediator-client.d.ts +66 -0
- package/dist/vta/mediator-client.d.ts.map +1 -0
- package/dist/vta/mediator-client.js +139 -0
- package/dist/vta/mediator-client.js.map +1 -0
- package/dist/vta/pickup.d.ts +81 -0
- package/dist/vta/pickup.d.ts.map +1 -0
- package/dist/vta/pickup.js +30 -0
- package/dist/vta/pickup.js.map +1 -0
- package/dist/vta/protocol.d.ts +76 -0
- package/dist/vta/protocol.d.ts.map +1 -0
- package/dist/vta/protocol.js +30 -0
- package/dist/vta/protocol.js.map +1 -0
- package/dist/vta/smoke.d.ts +59 -0
- package/dist/vta/smoke.d.ts.map +1 -0
- package/dist/vta/smoke.js +408 -0
- package/dist/vta/smoke.js.map +1 -0
- package/dist/vta/transport.d.ts +55 -0
- package/dist/vta/transport.d.ts.map +1 -0
- package/dist/vta/transport.js +2 -0
- package/dist/vta/transport.js.map +1 -0
- package/dist/vta/types.d.ts +50 -0
- package/dist/vta/types.d.ts.map +1 -0
- package/dist/vta/types.js +2 -0
- package/dist/vta/types.js.map +1 -0
- package/dist/vta/wallet-session.d.ts +87 -0
- package/dist/vta/wallet-session.d.ts.map +1 -0
- package/dist/vta/wallet-session.js +106 -0
- package/dist/vta/wallet-session.js.map +1 -0
- package/dist/webauthn/base64url.d.ts +3 -0
- package/dist/webauthn/base64url.d.ts.map +1 -0
- package/dist/webauthn/base64url.js +17 -0
- package/dist/webauthn/base64url.js.map +1 -0
- package/dist/webauthn/index.d.ts +4 -0
- package/dist/webauthn/index.d.ts.map +1 -0
- package/dist/webauthn/index.js +4 -0
- package/dist/webauthn/index.js.map +1 -0
- package/dist/webauthn/multikey.d.ts +26 -0
- package/dist/webauthn/multikey.d.ts.map +1 -0
- package/dist/webauthn/multikey.js +91 -0
- package/dist/webauthn/multikey.js.map +1 -0
- package/dist/webauthn/register.d.ts +36 -0
- package/dist/webauthn/register.d.ts.map +1 -0
- package/dist/webauthn/register.js +77 -0
- package/dist/webauthn/register.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
export type DidcommCurve = "X25519" | "P-256" | "secp256k1";
|
|
2
|
+
/** Plaintext message inputs. `id` is auto-generated as a v4 UUID when omitted. */
|
|
3
|
+
export interface PlaintextMessageInput {
|
|
4
|
+
id?: string;
|
|
5
|
+
type: string;
|
|
6
|
+
from?: string;
|
|
7
|
+
to?: string[];
|
|
8
|
+
body: unknown;
|
|
9
|
+
thid?: string;
|
|
10
|
+
}
|
|
11
|
+
/** A recipient for `packAuthcrypt` / `packAnoncrypt`. */
|
|
12
|
+
export interface DidcommRecipient {
|
|
13
|
+
kid: string;
|
|
14
|
+
jwk: PublicJwk;
|
|
15
|
+
}
|
|
16
|
+
/** Public key-agreement JWK shape. */
|
|
17
|
+
export interface PublicJwk {
|
|
18
|
+
kty: "OKP" | "EC";
|
|
19
|
+
crv: "X25519" | "P-256" | "secp256k1";
|
|
20
|
+
x: string;
|
|
21
|
+
y?: string;
|
|
22
|
+
}
|
|
23
|
+
/** Secret key-agreement JWK shape (must include `d`). */
|
|
24
|
+
export interface SecretJwk extends PublicJwk {
|
|
25
|
+
d: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A DIDComm key-agreement identity: a DID, the verification-method
|
|
29
|
+
* `kid` to advertise on the wire, and the X25519 secret used to
|
|
30
|
+
* authcrypt/decrypt. Replaces the former WASM `Identity` class with a
|
|
31
|
+
* pure-JS equivalent. `dispose()` drops the private material; the raw
|
|
32
|
+
* base64url strings can't be reliably zeroized in JS, so this is a
|
|
33
|
+
* best-effort release rather than a wipe.
|
|
34
|
+
*/
|
|
35
|
+
export declare class Identity {
|
|
36
|
+
readonly did: string;
|
|
37
|
+
readonly kid: string;
|
|
38
|
+
private constructor();
|
|
39
|
+
/** Mint a fresh X25519 identity for `did`. The `kid` defaults to
|
|
40
|
+
* `<did>#key-1`; callers that need a canonical key id reconstruct
|
|
41
|
+
* via `fromSecretJwk` once they've computed it. */
|
|
42
|
+
static generate(did: string): Identity;
|
|
43
|
+
/** Reconstruct a persisted identity. */
|
|
44
|
+
static fromSecretJwk(input: {
|
|
45
|
+
did: string;
|
|
46
|
+
kid: string;
|
|
47
|
+
jwk: SecretJwk;
|
|
48
|
+
}): Identity;
|
|
49
|
+
/** Public JWK + its `kid`, for handing to a counterparty as a recipient. */
|
|
50
|
+
publicJwk(): {
|
|
51
|
+
kid: string;
|
|
52
|
+
jwk: PublicJwk;
|
|
53
|
+
};
|
|
54
|
+
/** Persistable secret form (`{ did, kid, jwk }`). */
|
|
55
|
+
secretJwk(): {
|
|
56
|
+
did: string;
|
|
57
|
+
kid: string;
|
|
58
|
+
jwk: SecretJwk;
|
|
59
|
+
};
|
|
60
|
+
/** Drop the private key material held for this identity. */
|
|
61
|
+
dispose(): void;
|
|
62
|
+
}
|
|
63
|
+
export type UnpackResult = {
|
|
64
|
+
kind: "encrypted";
|
|
65
|
+
message: Record<string, unknown>;
|
|
66
|
+
authenticated: boolean;
|
|
67
|
+
sender_kid?: string;
|
|
68
|
+
recipient_kid: string;
|
|
69
|
+
} | {
|
|
70
|
+
kind: "signed";
|
|
71
|
+
message: Record<string, unknown>;
|
|
72
|
+
signer_kid?: string;
|
|
73
|
+
} | {
|
|
74
|
+
kind: "plaintext";
|
|
75
|
+
message: Record<string, unknown>;
|
|
76
|
+
};
|
|
77
|
+
/** Build a DIDComm v2 plaintext message and return its JSON form. */
|
|
78
|
+
export declare function buildPlaintextMessage(input: PlaintextMessageInput): string;
|
|
79
|
+
/** Pack as anoncrypt — no sender identity exposed. */
|
|
80
|
+
export declare function packAnoncrypt(message: PlaintextMessageInput, recipients: DidcommRecipient[]): Promise<string>;
|
|
81
|
+
/**
|
|
82
|
+
* Pack an already-serialized DIDComm Message JSON as anoncrypt.
|
|
83
|
+
* Use this for forward-envelope composition where the inner Message
|
|
84
|
+
* has fields (attachments, custom extras) that the builder shape
|
|
85
|
+
* doesn't carry.
|
|
86
|
+
*/
|
|
87
|
+
export declare function packAnoncryptJson(messageJson: string, recipients: DidcommRecipient[]): Promise<string>;
|
|
88
|
+
/**
|
|
89
|
+
* Pack an already-serialized DIDComm Message JSON as authcrypt.
|
|
90
|
+
* Sibling of `packAnoncryptJson`; needed for messages whose shape
|
|
91
|
+
* exceeds the builder (attachments, custom extras) **and** whose
|
|
92
|
+
* sender must be authenticated to the recipient. The
|
|
93
|
+
* `pickup/3.0/delivery` envelope is the primary case.
|
|
94
|
+
*/
|
|
95
|
+
export declare function packAuthcryptJson(messageJson: string, sender: Identity, recipients: DidcommRecipient[]): Promise<string>;
|
|
96
|
+
/**
|
|
97
|
+
* Wrap an already-encrypted JWE in a Routing 2.0 forward envelope
|
|
98
|
+
* addressed to `mediatorDid`, with `from` set so the envelope is
|
|
99
|
+
* **authcrypt**-packed to the mediator. An authenticated mediator
|
|
100
|
+
* relays a forward only when it can verify the sender is the
|
|
101
|
+
* authenticated client, so the forward must carry a sender — an
|
|
102
|
+
* anoncrypt forward is silently dropped. Returns the plaintext forward
|
|
103
|
+
* Message JSON; pair with `packAuthcryptJson(_, sender, [mediator])`.
|
|
104
|
+
*/
|
|
105
|
+
export declare function wrapForward(next: string, from: string, mediatorDid: string, encryptedJwe: string): string;
|
|
106
|
+
/**
|
|
107
|
+
* Pack as authcrypt — sender authenticated to recipients. The
|
|
108
|
+
* `sender` identity's private key is used to derive the sender-bound
|
|
109
|
+
* KEK; only its public material reaches the wire.
|
|
110
|
+
*/
|
|
111
|
+
export declare function packAuthcrypt(message: PlaintextMessageInput, sender: Identity, recipients: DidcommRecipient[]): Promise<string>;
|
|
112
|
+
/**
|
|
113
|
+
* Auto-detect format and unpack a JWE. For authcrypt pass
|
|
114
|
+
* `sender_public_jwk` so the sender binding can be verified. The
|
|
115
|
+
* library only produces encrypted results, so `kind` is always
|
|
116
|
+
* `"encrypted"`; the union retains the other variants for API
|
|
117
|
+
* stability.
|
|
118
|
+
*/
|
|
119
|
+
export declare function unpackMessage(args: {
|
|
120
|
+
input: string;
|
|
121
|
+
sender_public_jwk?: PublicJwk;
|
|
122
|
+
}, recipient: Identity): Promise<UnpackResult>;
|
|
123
|
+
/** Identifier of the underlying DIDComm implementation. */
|
|
124
|
+
export declare function didcommCrateVersion(): string;
|
|
125
|
+
/** A DID resolved to its X25519 key-agreement endpoint. */
|
|
126
|
+
export interface ResolvedKeyAgreement {
|
|
127
|
+
did: string;
|
|
128
|
+
keyAgreementKid: string;
|
|
129
|
+
keyAgreementPublicJwk: PublicJwk;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Resolve a DID to its first X25519 key-agreement verification method.
|
|
133
|
+
* `kid` is the canonical verification-method id; the public JWK is the
|
|
134
|
+
* X25519 key to authcrypt to. Throws if the DID has no X25519
|
|
135
|
+
* key-agreement entry.
|
|
136
|
+
*/
|
|
137
|
+
export declare function resolveKeyAgreement(did: string): Promise<ResolvedKeyAgreement>;
|
|
138
|
+
/** A resolved mediator: key-agreement endpoint plus its transport URLs. */
|
|
139
|
+
export interface ResolvedMediatorEndpoint extends ResolvedKeyAgreement {
|
|
140
|
+
/** WebSocket URL for live delivery (the bridge connects here). */
|
|
141
|
+
websocketUrl: string;
|
|
142
|
+
/** REST DIDCommMessaging endpoint. */
|
|
143
|
+
restEndpoint: string;
|
|
144
|
+
/** Mediator authentication endpoint. */
|
|
145
|
+
authEndpoint: string;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Resolve a mediator DID to its key-agreement material + transport
|
|
149
|
+
* endpoints. Refuses plaintext (`ws://`/`http://`) endpoints unless
|
|
150
|
+
* `allowInsecure` is set (local dev only) — a tampered/stale DID
|
|
151
|
+
* document must not be able to downgrade the transport. Throws if the
|
|
152
|
+
* mediator advertises no WebSocket endpoint, since the bridge needs one
|
|
153
|
+
* for live delivery.
|
|
154
|
+
*/
|
|
155
|
+
export declare function resolveMediatorEndpoint(mediatorDid: string, options?: {
|
|
156
|
+
allowInsecure?: boolean;
|
|
157
|
+
}): Promise<ResolvedMediatorEndpoint>;
|
|
158
|
+
/** The transports a VTA advertises in its DID document. A VTA may enable
|
|
159
|
+
* REST, DIDComm, or both (runtime service management) — onboarding resolves
|
|
160
|
+
* the DID once and uses whichever is present. */
|
|
161
|
+
export interface VtaServices {
|
|
162
|
+
/** REST base URL from the `#vta-rest` service (`type: "VTARest"`). */
|
|
163
|
+
rest?: {
|
|
164
|
+
baseUrl: string;
|
|
165
|
+
};
|
|
166
|
+
/** Mediator DID from the `#vta-didcomm` service (`type: "DIDCommMessaging"`). */
|
|
167
|
+
didcomm?: {
|
|
168
|
+
mediatorDid: string;
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Resolve a VTA/RP DID to its advertised transports — so a caller supplies a
|
|
173
|
+
* single DID and the wallet derives the REST endpoint and/or DIDComm mediator
|
|
174
|
+
* itself, rather than asking the operator for URLs. Returns whichever of
|
|
175
|
+
* `#vta-rest` / `#vta-didcomm` the document carries (possibly both, possibly
|
|
176
|
+
* one).
|
|
177
|
+
*/
|
|
178
|
+
export declare function resolveVtaServices(did: string): Promise<VtaServices>;
|
|
179
|
+
/** WebSocket constructor compatible with the library session (the
|
|
180
|
+
* browser global `WebSocket` satisfies it). */
|
|
181
|
+
export type WebSocketCtor = new (url: string, protocols?: string | string[]) => unknown;
|
|
182
|
+
/**
|
|
183
|
+
* A live, authenticated mediator session plus the resolved endpoints
|
|
184
|
+
* the DIDComm transport needs. `waitFor` resolves with the decrypted,
|
|
185
|
+
* sender-authenticated reply correlated by `thid`.
|
|
186
|
+
*/
|
|
187
|
+
export interface MediatorConnection {
|
|
188
|
+
send(jwe: string): void;
|
|
189
|
+
waitFor(thid: string, timeoutMs: number): Promise<Record<string, unknown>>;
|
|
190
|
+
close(): void;
|
|
191
|
+
/** True while the underlying WebSocket is open (live delivery active). A
|
|
192
|
+
* warm-session holder checks this before reusing a cached connection. */
|
|
193
|
+
readonly isOpen: boolean;
|
|
194
|
+
/** Register a handler for unsolicited inbound messages (those no `waitFor`
|
|
195
|
+
* claims) — e.g. an RP-initiated `confirm` request. The handler should
|
|
196
|
+
* filter by message `type`. Replaces any previously-registered handler. */
|
|
197
|
+
onInbound(handler: (message: Record<string, unknown>, thid: string) => void): void;
|
|
198
|
+
/** Resolved VTA key-agreement endpoint (inner authcrypt target). */
|
|
199
|
+
vta: ResolvedKeyAgreement;
|
|
200
|
+
/** Resolved mediator key-agreement endpoint (forward-envelope target). */
|
|
201
|
+
mediator: ResolvedKeyAgreement;
|
|
202
|
+
}
|
|
203
|
+
export interface ConnectMediatorSessionOptions {
|
|
204
|
+
/** Holder identity (its X25519 key authenticates to the mediator). */
|
|
205
|
+
holder: Identity;
|
|
206
|
+
/** Mediator DID — resolved + authenticated against. */
|
|
207
|
+
mediatorDid: string;
|
|
208
|
+
/** VTA DID — resolved so its replies unpack by skid. */
|
|
209
|
+
vtaDid: string;
|
|
210
|
+
/** fetch impl for the mediator auth handshake. */
|
|
211
|
+
fetch?: typeof fetch;
|
|
212
|
+
/** WebSocket ctor (defaults to globalThis.WebSocket). */
|
|
213
|
+
webSocketImpl?: WebSocketCtor;
|
|
214
|
+
/** Allow ws://, http:// endpoints. Local dev only. */
|
|
215
|
+
allowInsecure?: boolean;
|
|
216
|
+
/** Called once if the socket drops unexpectedly (not via `close()`).
|
|
217
|
+
* A warm-session holder uses this to evict + reconnect. */
|
|
218
|
+
onClose?: () => void;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Authenticate to the mediator and open a live-delivery session.
|
|
222
|
+
* Resolves once the WebSocket is open and live delivery is enabled.
|
|
223
|
+
* The returned handle's `send`/`waitFor` drive request/response over
|
|
224
|
+
* the mediator; `close()` tears the socket down.
|
|
225
|
+
*/
|
|
226
|
+
export declare function connectMediatorSession(opts: ConnectMediatorSessionOptions): Promise<MediatorConnection>;
|
|
227
|
+
export interface SmokeRoundtripResult {
|
|
228
|
+
ok: boolean;
|
|
229
|
+
packedLength: number;
|
|
230
|
+
recoveredMessageType: string | undefined;
|
|
231
|
+
authenticated: boolean | undefined;
|
|
232
|
+
error?: string;
|
|
233
|
+
}
|
|
234
|
+
export declare function smokeAuthcryptRoundtrip(): Promise<SmokeRoundtripResult>;
|
|
235
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/didcomm/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
// DIDComm v2 facade over `@openvtc/vti-didcomm-js`.
|
|
2
|
+
//
|
|
3
|
+
// This module is the single seam between `@openvtc/pnm-core` and the
|
|
4
|
+
// underlying DIDComm implementation. It used to wrap a WASM crate;
|
|
5
|
+
// it now wraps the pure-JS `@openvtc/vti-didcomm-js` library. The
|
|
6
|
+
// public surface (Identity, pack*/unpack*, wrapForward, the type
|
|
7
|
+
// shapes) is kept stable so consumers only had to learn that the
|
|
8
|
+
// pack/unpack calls became async.
|
|
9
|
+
//
|
|
10
|
+
// Scope of the current library version: X25519 key agreement,
|
|
11
|
+
// ECDH-1PU+A256CBC-HS512 authcrypt and ECDH-ES anoncrypt, single
|
|
12
|
+
// recipient per envelope. The type surface intentionally stays
|
|
13
|
+
// broader than that (OKP|EC, X25519|P-256|secp256k1) because did:peer
|
|
14
|
+
// and P-256/secp256k1 support are landing in the library — when they
|
|
15
|
+
// do, this facade needs no change since it only forwards JWKs to the
|
|
16
|
+
// library's curve-dispatching pack/unpack.
|
|
17
|
+
import { pack as vtiPack, packAnoncrypt as vtiPackAnoncrypt, unpack as vtiUnpack, buildForward as vtiBuildForward, resolveX25519KeyAgreement as vtiResolveKeyAgreement, resolveMediator as vtiResolveMediator, resolve as vtiResolve, authenticateToMediator as vtiAuthenticateToMediator, MediatorSession as VtiMediatorSession, x25519, jwk as vtiJwk, } from "@openvtc/vti-didcomm-js";
|
|
18
|
+
const SECRETS = new WeakMap();
|
|
19
|
+
function requireSecret(id) {
|
|
20
|
+
const secret = SECRETS.get(id);
|
|
21
|
+
if (!secret) {
|
|
22
|
+
throw new Error("Identity has been disposed");
|
|
23
|
+
}
|
|
24
|
+
return secret;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A DIDComm key-agreement identity: a DID, the verification-method
|
|
28
|
+
* `kid` to advertise on the wire, and the X25519 secret used to
|
|
29
|
+
* authcrypt/decrypt. Replaces the former WASM `Identity` class with a
|
|
30
|
+
* pure-JS equivalent. `dispose()` drops the private material; the raw
|
|
31
|
+
* base64url strings can't be reliably zeroized in JS, so this is a
|
|
32
|
+
* best-effort release rather than a wipe.
|
|
33
|
+
*/
|
|
34
|
+
export class Identity {
|
|
35
|
+
did;
|
|
36
|
+
kid;
|
|
37
|
+
constructor(did, kid, privateJwk) {
|
|
38
|
+
this.did = did;
|
|
39
|
+
this.kid = kid;
|
|
40
|
+
SECRETS.set(this, { kid, privateJwk });
|
|
41
|
+
}
|
|
42
|
+
/** Mint a fresh X25519 identity for `did`. The `kid` defaults to
|
|
43
|
+
* `<did>#key-1`; callers that need a canonical key id reconstruct
|
|
44
|
+
* via `fromSecretJwk` once they've computed it. */
|
|
45
|
+
static generate(did) {
|
|
46
|
+
const { privateKey, publicKey } = x25519.generateKeyPair();
|
|
47
|
+
const priv = vtiJwk.privateJwk("X25519", privateKey, publicKey);
|
|
48
|
+
return new Identity(did, `${did}#key-1`, {
|
|
49
|
+
kty: "OKP",
|
|
50
|
+
crv: "X25519",
|
|
51
|
+
x: priv.x,
|
|
52
|
+
d: priv.d,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/** Reconstruct a persisted identity. */
|
|
56
|
+
static fromSecretJwk(input) {
|
|
57
|
+
if (!input.jwk.d) {
|
|
58
|
+
throw new TypeError("Identity.fromSecretJwk: jwk.d (private scalar) required");
|
|
59
|
+
}
|
|
60
|
+
return new Identity(input.did, input.kid, { ...input.jwk });
|
|
61
|
+
}
|
|
62
|
+
/** Public JWK + its `kid`, for handing to a counterparty as a recipient. */
|
|
63
|
+
publicJwk() {
|
|
64
|
+
const { privateJwk } = requireSecret(this);
|
|
65
|
+
const pub = {
|
|
66
|
+
kty: privateJwk.kty,
|
|
67
|
+
crv: privateJwk.crv,
|
|
68
|
+
x: privateJwk.x,
|
|
69
|
+
};
|
|
70
|
+
if (privateJwk.y !== undefined)
|
|
71
|
+
pub.y = privateJwk.y;
|
|
72
|
+
return { kid: this.kid, jwk: pub };
|
|
73
|
+
}
|
|
74
|
+
/** Persistable secret form (`{ did, kid, jwk }`). */
|
|
75
|
+
secretJwk() {
|
|
76
|
+
const { privateJwk } = requireSecret(this);
|
|
77
|
+
return { did: this.did, kid: this.kid, jwk: { ...privateJwk } };
|
|
78
|
+
}
|
|
79
|
+
/** Drop the private key material held for this identity. */
|
|
80
|
+
dispose() {
|
|
81
|
+
SECRETS.delete(this);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function withId(message) {
|
|
85
|
+
if (message.id)
|
|
86
|
+
return message;
|
|
87
|
+
return { ...message, id: globalThis.crypto.randomUUID() };
|
|
88
|
+
}
|
|
89
|
+
function singleRecipient(recipients) {
|
|
90
|
+
const recipient = recipients[0];
|
|
91
|
+
if (recipients.length !== 1 || !recipient) {
|
|
92
|
+
throw new Error(`DIDComm facade packs to exactly one recipient, got ${recipients.length}`);
|
|
93
|
+
}
|
|
94
|
+
return recipient;
|
|
95
|
+
}
|
|
96
|
+
/** Build a DIDComm v2 plaintext message and return its JSON form. */
|
|
97
|
+
export function buildPlaintextMessage(input) {
|
|
98
|
+
return JSON.stringify(withId(input));
|
|
99
|
+
}
|
|
100
|
+
/** Pack as anoncrypt — no sender identity exposed. */
|
|
101
|
+
export function packAnoncrypt(message, recipients) {
|
|
102
|
+
const recipient = singleRecipient(recipients);
|
|
103
|
+
return vtiPackAnoncrypt({
|
|
104
|
+
message: withId(message),
|
|
105
|
+
recipient: { kid: recipient.kid, publicJwk: recipient.jwk },
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Pack an already-serialized DIDComm Message JSON as anoncrypt.
|
|
110
|
+
* Use this for forward-envelope composition where the inner Message
|
|
111
|
+
* has fields (attachments, custom extras) that the builder shape
|
|
112
|
+
* doesn't carry.
|
|
113
|
+
*/
|
|
114
|
+
export function packAnoncryptJson(messageJson, recipients) {
|
|
115
|
+
const recipient = singleRecipient(recipients);
|
|
116
|
+
return vtiPackAnoncrypt({
|
|
117
|
+
message: JSON.parse(messageJson),
|
|
118
|
+
recipient: { kid: recipient.kid, publicJwk: recipient.jwk },
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Pack an already-serialized DIDComm Message JSON as authcrypt.
|
|
123
|
+
* Sibling of `packAnoncryptJson`; needed for messages whose shape
|
|
124
|
+
* exceeds the builder (attachments, custom extras) **and** whose
|
|
125
|
+
* sender must be authenticated to the recipient. The
|
|
126
|
+
* `pickup/3.0/delivery` envelope is the primary case.
|
|
127
|
+
*/
|
|
128
|
+
export function packAuthcryptJson(messageJson, sender, recipients) {
|
|
129
|
+
const secret = requireSecret(sender);
|
|
130
|
+
const recipient = singleRecipient(recipients);
|
|
131
|
+
return vtiPack({
|
|
132
|
+
message: JSON.parse(messageJson),
|
|
133
|
+
sender: { kid: secret.kid, privateJwk: secret.privateJwk },
|
|
134
|
+
recipient: { kid: recipient.kid, publicJwk: recipient.jwk },
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Wrap an already-encrypted JWE in a Routing 2.0 forward envelope
|
|
139
|
+
* addressed to `mediatorDid`, with `from` set so the envelope is
|
|
140
|
+
* **authcrypt**-packed to the mediator. An authenticated mediator
|
|
141
|
+
* relays a forward only when it can verify the sender is the
|
|
142
|
+
* authenticated client, so the forward must carry a sender — an
|
|
143
|
+
* anoncrypt forward is silently dropped. Returns the plaintext forward
|
|
144
|
+
* Message JSON; pair with `packAuthcryptJson(_, sender, [mediator])`.
|
|
145
|
+
*/
|
|
146
|
+
export function wrapForward(next, from, mediatorDid, encryptedJwe) {
|
|
147
|
+
return JSON.stringify(vtiBuildForward({
|
|
148
|
+
next,
|
|
149
|
+
from,
|
|
150
|
+
mediatorDid,
|
|
151
|
+
innerJwe: encryptedJwe,
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Pack as authcrypt — sender authenticated to recipients. The
|
|
156
|
+
* `sender` identity's private key is used to derive the sender-bound
|
|
157
|
+
* KEK; only its public material reaches the wire.
|
|
158
|
+
*/
|
|
159
|
+
export function packAuthcrypt(message, sender, recipients) {
|
|
160
|
+
const secret = requireSecret(sender);
|
|
161
|
+
const recipient = singleRecipient(recipients);
|
|
162
|
+
return vtiPack({
|
|
163
|
+
message: withId(message),
|
|
164
|
+
sender: { kid: secret.kid, privateJwk: secret.privateJwk },
|
|
165
|
+
recipient: { kid: recipient.kid, publicJwk: recipient.jwk },
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
// The library matches the recipient by an exact `kid` string against
|
|
169
|
+
// the JWE `recipients[]`. The former WASM impl matched by key material
|
|
170
|
+
// (via a secrets resolver), so a holder whose stored `kid` differed
|
|
171
|
+
// from the one a counterparty used to address it still decrypted.
|
|
172
|
+
// Preserve that: if the stored kid isn't present but there's exactly
|
|
173
|
+
// one recipient entry, decrypt against that entry's kid. The private
|
|
174
|
+
// key is the real authority — a wrong key fails AES-KW unwrap
|
|
175
|
+
// regardless of the kid string.
|
|
176
|
+
function resolveRecipientKid(jweJson, storedKid) {
|
|
177
|
+
try {
|
|
178
|
+
const jwe = JSON.parse(jweJson);
|
|
179
|
+
const entries = jwe.recipients ?? [];
|
|
180
|
+
if (entries.some((e) => e?.header?.kid === storedKid))
|
|
181
|
+
return storedKid;
|
|
182
|
+
const sole = entries.length === 1 ? entries[0]?.header?.kid : undefined;
|
|
183
|
+
if (typeof sole === "string")
|
|
184
|
+
return sole;
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
// Fall through — let the library's unpack raise the canonical
|
|
188
|
+
// parse error.
|
|
189
|
+
}
|
|
190
|
+
return storedKid;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Auto-detect format and unpack a JWE. For authcrypt pass
|
|
194
|
+
* `sender_public_jwk` so the sender binding can be verified. The
|
|
195
|
+
* library only produces encrypted results, so `kind` is always
|
|
196
|
+
* `"encrypted"`; the union retains the other variants for API
|
|
197
|
+
* stability.
|
|
198
|
+
*/
|
|
199
|
+
export async function unpackMessage(args, recipient) {
|
|
200
|
+
const secret = requireSecret(recipient);
|
|
201
|
+
const recipientKid = resolveRecipientKid(args.input, secret.kid);
|
|
202
|
+
const result = await vtiUnpack(args.input, { kid: recipientKid, privateJwk: secret.privateJwk }, args.sender_public_jwk ? { publicJwk: args.sender_public_jwk } : undefined);
|
|
203
|
+
const out = {
|
|
204
|
+
kind: "encrypted",
|
|
205
|
+
message: result.message,
|
|
206
|
+
authenticated: result.authenticated,
|
|
207
|
+
recipient_kid: recipientKid,
|
|
208
|
+
};
|
|
209
|
+
if (result.senderKid)
|
|
210
|
+
out.sender_kid = result.senderKid;
|
|
211
|
+
return out;
|
|
212
|
+
}
|
|
213
|
+
/** Identifier of the underlying DIDComm implementation. */
|
|
214
|
+
export function didcommCrateVersion() {
|
|
215
|
+
return "@openvtc/vti-didcomm-js";
|
|
216
|
+
}
|
|
217
|
+
// ---------------------------------------------------------------------------
|
|
218
|
+
// DID resolution. did:key resolves in-tree (deterministic); did:webvh is
|
|
219
|
+
// fetched from its hosting service (the `did.jsonl` host named in the DID).
|
|
220
|
+
// These turn a DID string into the key-agreement material a DIDComm
|
|
221
|
+
// transport needs, so callers configure endpoints by DID rather than by
|
|
222
|
+
// hand-supplying keys.
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
function x25519PublicJwk(bytes) {
|
|
225
|
+
const okp = vtiJwk.publicJwk("X25519", bytes);
|
|
226
|
+
return { kty: "OKP", crv: "X25519", x: okp.x };
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Resolve a DID to its first X25519 key-agreement verification method.
|
|
230
|
+
* `kid` is the canonical verification-method id; the public JWK is the
|
|
231
|
+
* X25519 key to authcrypt to. Throws if the DID has no X25519
|
|
232
|
+
* key-agreement entry.
|
|
233
|
+
*/
|
|
234
|
+
export async function resolveKeyAgreement(did) {
|
|
235
|
+
const { kid, x25519Pub } = await vtiResolveKeyAgreement(did);
|
|
236
|
+
return {
|
|
237
|
+
did,
|
|
238
|
+
keyAgreementKid: kid,
|
|
239
|
+
keyAgreementPublicJwk: x25519PublicJwk(x25519Pub),
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Resolve a mediator DID to its key-agreement material + transport
|
|
244
|
+
* endpoints. Refuses plaintext (`ws://`/`http://`) endpoints unless
|
|
245
|
+
* `allowInsecure` is set (local dev only) — a tampered/stale DID
|
|
246
|
+
* document must not be able to downgrade the transport. Throws if the
|
|
247
|
+
* mediator advertises no WebSocket endpoint, since the bridge needs one
|
|
248
|
+
* for live delivery.
|
|
249
|
+
*/
|
|
250
|
+
export async function resolveMediatorEndpoint(mediatorDid, options = {}) {
|
|
251
|
+
const m = await vtiResolveMediator(mediatorDid, {
|
|
252
|
+
allowInsecure: options.allowInsecure ?? false,
|
|
253
|
+
});
|
|
254
|
+
if (!m.wsEndpoint) {
|
|
255
|
+
throw new Error(`mediator ${mediatorDid} advertises no WebSocket endpoint for live delivery`);
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
did: m.did,
|
|
259
|
+
keyAgreementKid: m.kid,
|
|
260
|
+
keyAgreementPublicJwk: x25519PublicJwk(m.x25519Pub),
|
|
261
|
+
websocketUrl: m.wsEndpoint,
|
|
262
|
+
restEndpoint: m.restEndpoint,
|
|
263
|
+
authEndpoint: m.authEndpoint,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Resolve a VTA/RP DID to its advertised transports — so a caller supplies a
|
|
268
|
+
* single DID and the wallet derives the REST endpoint and/or DIDComm mediator
|
|
269
|
+
* itself, rather than asking the operator for URLs. Returns whichever of
|
|
270
|
+
* `#vta-rest` / `#vta-didcomm` the document carries (possibly both, possibly
|
|
271
|
+
* one).
|
|
272
|
+
*/
|
|
273
|
+
export async function resolveVtaServices(did) {
|
|
274
|
+
const resolution = (await vtiResolve(did, {}));
|
|
275
|
+
const services = resolution.didDocument?.service ?? [];
|
|
276
|
+
const out = {};
|
|
277
|
+
for (const svc of services) {
|
|
278
|
+
const fragment = (svc.id ?? "").split("#")[1];
|
|
279
|
+
if (fragment === "vta-rest" || svc.type === "VTARest") {
|
|
280
|
+
// `#vta-rest` serviceEndpoint is a plain URL string.
|
|
281
|
+
if (typeof svc.serviceEndpoint === "string") {
|
|
282
|
+
out.rest = { baseUrl: svc.serviceEndpoint };
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (fragment === "vta-didcomm" || svc.type === "DIDCommMessaging") {
|
|
286
|
+
// `#vta-didcomm` serviceEndpoint is `[{ uri: <mediator-did>, ... }]`;
|
|
287
|
+
// tolerate the object and bare-string encodings too.
|
|
288
|
+
const ep = svc.serviceEndpoint;
|
|
289
|
+
let mediatorDid;
|
|
290
|
+
if (Array.isArray(ep))
|
|
291
|
+
mediatorDid = ep[0]?.uri;
|
|
292
|
+
else if (ep && typeof ep === "object")
|
|
293
|
+
mediatorDid = ep.uri;
|
|
294
|
+
else if (typeof ep === "string")
|
|
295
|
+
mediatorDid = ep;
|
|
296
|
+
// Prefer the VTA-specific fragment over a generic DIDCommMessaging entry.
|
|
297
|
+
if (mediatorDid && (fragment === "vta-didcomm" || !out.didcomm)) {
|
|
298
|
+
out.didcomm = { mediatorDid };
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return out;
|
|
303
|
+
}
|
|
304
|
+
const authenticateToMediator = vtiAuthenticateToMediator;
|
|
305
|
+
/**
|
|
306
|
+
* Authenticate to the mediator and open a live-delivery session.
|
|
307
|
+
* Resolves once the WebSocket is open and live delivery is enabled.
|
|
308
|
+
* The returned handle's `send`/`waitFor` drive request/response over
|
|
309
|
+
* the mediator; `close()` tears the socket down.
|
|
310
|
+
*/
|
|
311
|
+
export async function connectMediatorSession(opts) {
|
|
312
|
+
const secret = requireSecret(opts.holder);
|
|
313
|
+
const okp = secret.privateJwk;
|
|
314
|
+
const clientPrivate = vtiJwk.rawPrivate(okp);
|
|
315
|
+
const clientPublic = vtiJwk.rawPublic(okp);
|
|
316
|
+
const auth = await authenticateToMediator({
|
|
317
|
+
mediatorDid: opts.mediatorDid,
|
|
318
|
+
clientDid: opts.holder.did,
|
|
319
|
+
clientX25519Private: clientPrivate,
|
|
320
|
+
clientX25519Public: clientPublic,
|
|
321
|
+
clientKid: opts.holder.kid,
|
|
322
|
+
allowInsecure: opts.allowInsecure ?? false,
|
|
323
|
+
...(opts.fetch ? { fetch: opts.fetch } : {}),
|
|
324
|
+
});
|
|
325
|
+
const vta = await resolveKeyAgreement(opts.vtaDid);
|
|
326
|
+
// Seed the VTA's key so its replies unpack by skid; resolve any other
|
|
327
|
+
// sender on demand.
|
|
328
|
+
const senderKeys = new Map([
|
|
329
|
+
[opts.vtaDid, { publicJwk: vta.keyAgreementPublicJwk }],
|
|
330
|
+
]);
|
|
331
|
+
const session = new VtiMediatorSession({
|
|
332
|
+
mediator: auth.mediator,
|
|
333
|
+
mediatorJwt: auth.accessToken,
|
|
334
|
+
client: {
|
|
335
|
+
did: opts.holder.did,
|
|
336
|
+
kid: opts.holder.kid,
|
|
337
|
+
privateKey: clientPrivate,
|
|
338
|
+
publicKey: clientPublic,
|
|
339
|
+
},
|
|
340
|
+
senderKeys,
|
|
341
|
+
resolveSender: async (did) => {
|
|
342
|
+
const r = await vtiResolveKeyAgreement(did);
|
|
343
|
+
return { publicJwk: x25519PublicJwk(r.x25519Pub) };
|
|
344
|
+
},
|
|
345
|
+
...(opts.onClose ? { onClose: opts.onClose } : {}),
|
|
346
|
+
...(opts.webSocketImpl ? { WebSocketImpl: opts.webSocketImpl } : {}),
|
|
347
|
+
});
|
|
348
|
+
await session.connect();
|
|
349
|
+
const liveSession = session;
|
|
350
|
+
return {
|
|
351
|
+
send: (jwe) => session.send(jwe),
|
|
352
|
+
waitFor: (thid, timeoutMs) => session.waitFor(thid, timeoutMs),
|
|
353
|
+
close: () => session.close(),
|
|
354
|
+
get isOpen() {
|
|
355
|
+
return liveSession.isOpen;
|
|
356
|
+
},
|
|
357
|
+
// The session reads `onMessage` dynamically on each inbound frame, so a
|
|
358
|
+
// post-connect assignment takes effect immediately.
|
|
359
|
+
onInbound: (handler) => {
|
|
360
|
+
session.onMessage = handler;
|
|
361
|
+
},
|
|
362
|
+
vta,
|
|
363
|
+
mediator: {
|
|
364
|
+
did: auth.mediator.did,
|
|
365
|
+
keyAgreementKid: auth.mediator.kid,
|
|
366
|
+
keyAgreementPublicJwk: x25519PublicJwk(auth.mediator.x25519Pub),
|
|
367
|
+
},
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
export async function smokeAuthcryptRoundtrip() {
|
|
371
|
+
let alice = null;
|
|
372
|
+
let bob = null;
|
|
373
|
+
try {
|
|
374
|
+
alice = Identity.generate("did:example:alice");
|
|
375
|
+
bob = Identity.generate("did:example:bob");
|
|
376
|
+
const bobPub = bob.publicJwk();
|
|
377
|
+
const alicePub = alice.publicJwk();
|
|
378
|
+
const packed = await packAuthcrypt({
|
|
379
|
+
type: "https://didcomm.org/basicmessage/2.0/message",
|
|
380
|
+
from: alice.did,
|
|
381
|
+
to: [bob.did],
|
|
382
|
+
body: { content: "hello from the vti-didcomm-js smoke test" },
|
|
383
|
+
}, alice, [bobPub]);
|
|
384
|
+
const out = await unpackMessage({ input: packed, sender_public_jwk: alicePub.jwk }, bob);
|
|
385
|
+
if (out.kind !== "encrypted") {
|
|
386
|
+
return {
|
|
387
|
+
ok: false,
|
|
388
|
+
packedLength: packed.length,
|
|
389
|
+
recoveredMessageType: undefined,
|
|
390
|
+
authenticated: undefined,
|
|
391
|
+
error: `unexpected kind ${out.kind}`,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
return {
|
|
395
|
+
ok: true,
|
|
396
|
+
packedLength: packed.length,
|
|
397
|
+
recoveredMessageType: out.message["type"],
|
|
398
|
+
authenticated: out.authenticated,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
catch (err) {
|
|
402
|
+
return {
|
|
403
|
+
ok: false,
|
|
404
|
+
packedLength: 0,
|
|
405
|
+
recoveredMessageType: undefined,
|
|
406
|
+
authenticated: undefined,
|
|
407
|
+
error: err.message,
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
finally {
|
|
411
|
+
alice?.dispose();
|
|
412
|
+
bob?.dispose();
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
//# sourceMappingURL=index.js.map
|