@verbeth/sdk 0.1.4 → 0.1.5

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 (184) hide show
  1. package/README.md +16 -167
  2. package/dist/esm/src/client/HsrTagIndex.d.ts +77 -0
  3. package/dist/esm/src/client/HsrTagIndex.d.ts.map +1 -0
  4. package/dist/esm/src/client/HsrTagIndex.js +157 -0
  5. package/dist/esm/src/client/PendingManager.d.ts +65 -0
  6. package/dist/esm/src/client/PendingManager.d.ts.map +1 -0
  7. package/dist/esm/src/client/PendingManager.js +84 -0
  8. package/dist/esm/src/client/SessionManager.d.ts +65 -0
  9. package/dist/esm/src/client/SessionManager.d.ts.map +1 -0
  10. package/dist/esm/src/client/SessionManager.js +146 -0
  11. package/dist/esm/src/client/VerbethClient.d.ts +153 -99
  12. package/dist/esm/src/client/VerbethClient.d.ts.map +1 -1
  13. package/dist/esm/src/client/VerbethClient.js +429 -123
  14. package/dist/esm/src/client/VerbethClientBuilder.d.ts +105 -0
  15. package/dist/esm/src/client/VerbethClientBuilder.d.ts.map +1 -0
  16. package/dist/esm/src/client/VerbethClientBuilder.js +146 -0
  17. package/dist/esm/src/client/hsrMatcher.d.ts +22 -0
  18. package/dist/esm/src/client/hsrMatcher.d.ts.map +1 -0
  19. package/dist/esm/src/client/hsrMatcher.js +31 -0
  20. package/dist/esm/src/client/index.d.ts +6 -1
  21. package/dist/esm/src/client/index.d.ts.map +1 -1
  22. package/dist/esm/src/client/index.js +2 -0
  23. package/dist/esm/src/client/types.d.ts +151 -10
  24. package/dist/esm/src/client/types.d.ts.map +1 -1
  25. package/dist/esm/src/crypto(old).d.ts +46 -0
  26. package/dist/esm/src/crypto(old).d.ts.map +1 -0
  27. package/dist/esm/src/crypto(old).js +137 -0
  28. package/dist/esm/src/crypto.d.ts +7 -29
  29. package/dist/esm/src/crypto.d.ts.map +1 -1
  30. package/dist/esm/src/crypto.js +36 -72
  31. package/dist/esm/src/executor.d.ts +1 -2
  32. package/dist/esm/src/executor.d.ts.map +1 -1
  33. package/dist/esm/src/executor.js +8 -24
  34. package/dist/esm/src/handshake.d.ts +51 -0
  35. package/dist/esm/src/handshake.d.ts.map +1 -0
  36. package/dist/esm/src/handshake.js +105 -0
  37. package/dist/esm/src/identity.d.ts +24 -18
  38. package/dist/esm/src/identity.d.ts.map +1 -1
  39. package/dist/esm/src/identity.js +126 -31
  40. package/dist/esm/src/index.d.ts +10 -7
  41. package/dist/esm/src/index.d.ts.map +1 -1
  42. package/dist/esm/src/index.js +9 -7
  43. package/dist/esm/src/payload.d.ts +3 -30
  44. package/dist/esm/src/payload.d.ts.map +1 -1
  45. package/dist/esm/src/payload.js +3 -77
  46. package/dist/esm/src/pq/kem.d.ts +33 -0
  47. package/dist/esm/src/pq/kem.d.ts.map +1 -0
  48. package/dist/esm/src/pq/kem.js +40 -0
  49. package/dist/esm/src/ratchet/auth.d.ts +34 -0
  50. package/dist/esm/src/ratchet/auth.d.ts.map +1 -0
  51. package/dist/esm/src/ratchet/auth.js +88 -0
  52. package/dist/esm/src/ratchet/codec.d.ts +52 -0
  53. package/dist/esm/src/ratchet/codec.d.ts.map +1 -0
  54. package/dist/esm/src/ratchet/codec.js +127 -0
  55. package/dist/esm/src/ratchet/decrypt.d.ts +28 -0
  56. package/dist/esm/src/ratchet/decrypt.d.ts.map +1 -0
  57. package/dist/esm/src/ratchet/decrypt.js +255 -0
  58. package/dist/esm/src/ratchet/encrypt.d.ts +17 -0
  59. package/dist/esm/src/ratchet/encrypt.d.ts.map +1 -0
  60. package/dist/esm/src/ratchet/encrypt.js +78 -0
  61. package/dist/esm/src/ratchet/index.d.ts +8 -0
  62. package/dist/esm/src/ratchet/index.d.ts.map +1 -0
  63. package/dist/esm/src/ratchet/index.js +8 -0
  64. package/dist/esm/src/ratchet/kdf.d.ts +60 -0
  65. package/dist/esm/src/ratchet/kdf.d.ts.map +1 -0
  66. package/dist/esm/src/ratchet/kdf.js +91 -0
  67. package/dist/esm/src/ratchet/session.d.ts +43 -0
  68. package/dist/esm/src/ratchet/session.d.ts.map +1 -0
  69. package/dist/esm/src/ratchet/session.js +139 -0
  70. package/dist/esm/src/ratchet/types.d.ts +168 -0
  71. package/dist/esm/src/ratchet/types.d.ts.map +1 -0
  72. package/dist/esm/src/ratchet/types.js +27 -0
  73. package/dist/esm/src/safeSessionSigner.d.ts +35 -0
  74. package/dist/esm/src/safeSessionSigner.d.ts.map +1 -0
  75. package/dist/esm/src/safeSessionSigner.js +59 -0
  76. package/dist/esm/src/send.d.ts +32 -24
  77. package/dist/esm/src/send.d.ts.map +1 -1
  78. package/dist/esm/src/send.js +84 -39
  79. package/dist/esm/src/types.d.ts +8 -13
  80. package/dist/esm/src/types.d.ts.map +1 -1
  81. package/dist/esm/src/utils/safeSessionSigner.d.ts +23 -0
  82. package/dist/esm/src/utils/safeSessionSigner.d.ts.map +1 -0
  83. package/dist/esm/src/utils/safeSessionSigner.js +59 -0
  84. package/dist/esm/src/utils/txQueue.d.ts +12 -0
  85. package/dist/esm/src/utils/txQueue.d.ts.map +1 -0
  86. package/dist/esm/src/utils/txQueue.js +25 -0
  87. package/dist/esm/src/utils.d.ts +2 -3
  88. package/dist/esm/src/utils.d.ts.map +1 -1
  89. package/dist/esm/src/utils.js +5 -5
  90. package/dist/esm/src/verify.d.ts +9 -25
  91. package/dist/esm/src/verify.d.ts.map +1 -1
  92. package/dist/esm/src/verify.js +49 -50
  93. package/dist/src/client/HsrTagIndex.d.ts +77 -0
  94. package/dist/src/client/HsrTagIndex.d.ts.map +1 -0
  95. package/dist/src/client/HsrTagIndex.js +157 -0
  96. package/dist/src/client/PendingManager.d.ts +65 -0
  97. package/dist/src/client/PendingManager.d.ts.map +1 -0
  98. package/dist/src/client/PendingManager.js +84 -0
  99. package/dist/src/client/SessionManager.d.ts +65 -0
  100. package/dist/src/client/SessionManager.d.ts.map +1 -0
  101. package/dist/src/client/SessionManager.js +146 -0
  102. package/dist/src/client/VerbethClient.d.ts +153 -99
  103. package/dist/src/client/VerbethClient.d.ts.map +1 -1
  104. package/dist/src/client/VerbethClient.js +429 -123
  105. package/dist/src/client/VerbethClientBuilder.d.ts +105 -0
  106. package/dist/src/client/VerbethClientBuilder.d.ts.map +1 -0
  107. package/dist/src/client/VerbethClientBuilder.js +146 -0
  108. package/dist/src/client/hsrMatcher.d.ts +22 -0
  109. package/dist/src/client/hsrMatcher.d.ts.map +1 -0
  110. package/dist/src/client/hsrMatcher.js +31 -0
  111. package/dist/src/client/index.d.ts +6 -1
  112. package/dist/src/client/index.d.ts.map +1 -1
  113. package/dist/src/client/index.js +2 -0
  114. package/dist/src/client/types.d.ts +151 -10
  115. package/dist/src/client/types.d.ts.map +1 -1
  116. package/dist/src/crypto(old).d.ts +46 -0
  117. package/dist/src/crypto(old).d.ts.map +1 -0
  118. package/dist/src/crypto(old).js +137 -0
  119. package/dist/src/crypto.d.ts +7 -29
  120. package/dist/src/crypto.d.ts.map +1 -1
  121. package/dist/src/crypto.js +36 -72
  122. package/dist/src/executor.d.ts +1 -2
  123. package/dist/src/executor.d.ts.map +1 -1
  124. package/dist/src/executor.js +8 -24
  125. package/dist/src/handshake.d.ts +51 -0
  126. package/dist/src/handshake.d.ts.map +1 -0
  127. package/dist/src/handshake.js +105 -0
  128. package/dist/src/identity.d.ts +24 -18
  129. package/dist/src/identity.d.ts.map +1 -1
  130. package/dist/src/identity.js +126 -31
  131. package/dist/src/index.d.ts +10 -7
  132. package/dist/src/index.d.ts.map +1 -1
  133. package/dist/src/index.js +9 -7
  134. package/dist/src/payload.d.ts +3 -30
  135. package/dist/src/payload.d.ts.map +1 -1
  136. package/dist/src/payload.js +3 -77
  137. package/dist/src/pq/kem.d.ts +33 -0
  138. package/dist/src/pq/kem.d.ts.map +1 -0
  139. package/dist/src/pq/kem.js +40 -0
  140. package/dist/src/ratchet/auth.d.ts +34 -0
  141. package/dist/src/ratchet/auth.d.ts.map +1 -0
  142. package/dist/src/ratchet/auth.js +88 -0
  143. package/dist/src/ratchet/codec.d.ts +52 -0
  144. package/dist/src/ratchet/codec.d.ts.map +1 -0
  145. package/dist/src/ratchet/codec.js +127 -0
  146. package/dist/src/ratchet/decrypt.d.ts +28 -0
  147. package/dist/src/ratchet/decrypt.d.ts.map +1 -0
  148. package/dist/src/ratchet/decrypt.js +255 -0
  149. package/dist/src/ratchet/encrypt.d.ts +17 -0
  150. package/dist/src/ratchet/encrypt.d.ts.map +1 -0
  151. package/dist/src/ratchet/encrypt.js +78 -0
  152. package/dist/src/ratchet/index.d.ts +8 -0
  153. package/dist/src/ratchet/index.d.ts.map +1 -0
  154. package/dist/src/ratchet/index.js +8 -0
  155. package/dist/src/ratchet/kdf.d.ts +60 -0
  156. package/dist/src/ratchet/kdf.d.ts.map +1 -0
  157. package/dist/src/ratchet/kdf.js +91 -0
  158. package/dist/src/ratchet/session.d.ts +43 -0
  159. package/dist/src/ratchet/session.d.ts.map +1 -0
  160. package/dist/src/ratchet/session.js +139 -0
  161. package/dist/src/ratchet/types.d.ts +168 -0
  162. package/dist/src/ratchet/types.d.ts.map +1 -0
  163. package/dist/src/ratchet/types.js +27 -0
  164. package/dist/src/safeSessionSigner.d.ts +35 -0
  165. package/dist/src/safeSessionSigner.d.ts.map +1 -0
  166. package/dist/src/safeSessionSigner.js +59 -0
  167. package/dist/src/send.d.ts +32 -24
  168. package/dist/src/send.d.ts.map +1 -1
  169. package/dist/src/send.js +84 -39
  170. package/dist/src/types.d.ts +8 -13
  171. package/dist/src/types.d.ts.map +1 -1
  172. package/dist/src/utils/safeSessionSigner.d.ts +23 -0
  173. package/dist/src/utils/safeSessionSigner.d.ts.map +1 -0
  174. package/dist/src/utils/safeSessionSigner.js +59 -0
  175. package/dist/src/utils/txQueue.d.ts +12 -0
  176. package/dist/src/utils/txQueue.d.ts.map +1 -0
  177. package/dist/src/utils/txQueue.js +25 -0
  178. package/dist/src/utils.d.ts +2 -3
  179. package/dist/src/utils.d.ts.map +1 -1
  180. package/dist/src/utils.js +5 -5
  181. package/dist/src/verify.d.ts +9 -25
  182. package/dist/src/verify.d.ts.map +1 -1
  183. package/dist/src/verify.js +49 -50
  184. package/package.json +2 -1
@@ -0,0 +1,137 @@
1
+ // packages/sdk/src/crypto.ts
2
+ import nacl from 'tweetnacl';
3
+ import { keccak256, toUtf8Bytes, dataSlice } from 'ethers';
4
+ import { sha256 } from '@noble/hashes/sha2';
5
+ import { hkdf } from '@noble/hashes/hkdf';
6
+ import { encodePayload, decodePayload, encodeStructuredContent, decodeStructuredContent, extractKeysFromHandshakeResponse } from './payload.js';
7
+ /**
8
+ * Encrypts a structured payload (JSON-serializable objects)
9
+ */
10
+ export function encryptStructuredPayload(payload, recipientPublicKey, ephemeralSecretKey, ephemeralPublicKey, staticSigningSecretKey, staticSigningPublicKey) {
11
+ // encode payload as binary JSON
12
+ const plaintext = encodeStructuredContent(payload);
13
+ const nonce = nacl.randomBytes(nacl.box.nonceLength);
14
+ const box = nacl.box(plaintext, nonce, recipientPublicKey, ephemeralSecretKey);
15
+ let sig;
16
+ if (staticSigningSecretKey && staticSigningPublicKey) {
17
+ const dataToSign = Buffer.concat([ephemeralPublicKey, nonce, box]);
18
+ sig = nacl.sign.detached(dataToSign, staticSigningSecretKey);
19
+ }
20
+ return encodePayload(ephemeralPublicKey, nonce, box, sig);
21
+ }
22
+ /**
23
+ * Decrypts a structured payload with converter function
24
+ */
25
+ export function decryptStructuredPayload(payloadJson, recipientSecretKey, converter, staticSigningPublicKey) {
26
+ const { epk, nonce, ciphertext, sig } = decodePayload(payloadJson);
27
+ if (sig && staticSigningPublicKey) {
28
+ const dataToVerify = Buffer.concat([epk, nonce, ciphertext]);
29
+ const valid = nacl.sign.detached.verify(dataToVerify, sig, staticSigningPublicKey);
30
+ if (!valid)
31
+ return null;
32
+ }
33
+ const box = nacl.box.open(ciphertext, nonce, epk, recipientSecretKey);
34
+ if (!box)
35
+ return null;
36
+ return decodeStructuredContent(box, converter);
37
+ }
38
+ // wrappers for encrypting and decrypting messages
39
+ export function encryptMessage(message, recipientPublicKey, ephemeralSecretKey, ephemeralPublicKey, staticSigningSecretKey, staticSigningPublicKey) {
40
+ const payload = { content: message };
41
+ return encryptStructuredPayload(payload, recipientPublicKey, ephemeralSecretKey, ephemeralPublicKey, staticSigningSecretKey, staticSigningPublicKey);
42
+ }
43
+ export function decryptMessage(payloadJson, recipientSecretKey, staticSigningPublicKey) {
44
+ const result = decryptStructuredPayload(payloadJson, recipientSecretKey, (obj) => obj, staticSigningPublicKey);
45
+ return result ? result.content : null;
46
+ }
47
+ /**
48
+ * Decrypts handshake response and extracts individual keys from unified format
49
+ */
50
+ export function decryptHandshakeResponse(payloadJson, initiatorEphemeralSecretKey) {
51
+ return decryptStructuredPayload(payloadJson, initiatorEphemeralSecretKey, (obj) => {
52
+ if (!obj.identityProof) {
53
+ throw new Error("Invalid handshake response: missing identityProof");
54
+ }
55
+ return {
56
+ unifiedPubKeys: Uint8Array.from(Buffer.from(obj.unifiedPubKeys, 'base64')),
57
+ ephemeralPubKey: Uint8Array.from(Buffer.from(obj.ephemeralPubKey, 'base64')),
58
+ note: obj.note,
59
+ identityProof: obj.identityProof
60
+ };
61
+ });
62
+ }
63
+ /**
64
+ * helper to decrypt handshake response and extract individual keys
65
+ */
66
+ export function decryptAndExtractHandshakeKeys(payloadJson, initiatorEphemeralSecretKey) {
67
+ const decrypted = decryptHandshakeResponse(payloadJson, initiatorEphemeralSecretKey);
68
+ if (!decrypted)
69
+ return null;
70
+ const extracted = extractKeysFromHandshakeResponse(decrypted);
71
+ if (!extracted)
72
+ return null;
73
+ return {
74
+ identityPubKey: extracted.identityPubKey,
75
+ signingPubKey: extracted.signingPubKey,
76
+ ephemeralPubKey: extracted.ephemeralPubKey,
77
+ note: decrypted.note,
78
+ identityProof: decrypted.identityProof
79
+ };
80
+ }
81
+ /**
82
+ * HKDF(sha256) on shared secret, info="verbeth:hsr", then Keccak-256 -> bytes32 (0x...)
83
+ */
84
+ function finalizeHsrTag(shared) {
85
+ const okm = hkdf(sha256, shared, new Uint8Array(0), toUtf8Bytes("verbeth:hsr"), 32);
86
+ return keccak256(okm);
87
+ }
88
+ /**
89
+ * Responder: tag = H( KDF( ECDH(r, viewPubA), "verbeth:hsr"))
90
+ */
91
+ export function computeTagFromResponder(rSecretKey, viewPubA) {
92
+ const shared = nacl.scalarMult(rSecretKey, viewPubA);
93
+ return finalizeHsrTag(shared);
94
+ }
95
+ /**
96
+ * Initiator: tag = H( KDF( ECDH(viewPrivA, R), "verbeth:hsr"))
97
+ */
98
+ export function computeTagFromInitiator(viewPrivA, R) {
99
+ const shared = nacl.scalarMult(viewPrivA, R);
100
+ return finalizeHsrTag(shared);
101
+ }
102
+ /**
103
+ * Derives a bytes32 topic from the shared secret via HKDF(SHA256) + Keccak-256.
104
+ * - info: domain separation (e.g., "verbeth:topic-out:v1")
105
+ * - salt: recommended to use a tag as salt (stable and shareable)
106
+ */
107
+ function deriveTopic(shared, info, salt) {
108
+ const okm = hkdf(sha256, shared, salt ?? new Uint8Array(0), new TextEncoder().encode(info), 32);
109
+ return keccak256(okm);
110
+ }
111
+ export function deriveLongTermShared(myIdentitySecretKey, theirIdentityPublicKey) {
112
+ return nacl.scalarMult(myIdentitySecretKey, theirIdentityPublicKey);
113
+ }
114
+ /**
115
+ * Directional duplex topics (Initiator-Responder, Responder-Initiator).
116
+ * Recommended salt: tag (bytes)
117
+ */
118
+ export function deriveDuplexTopics(myIdentitySecretKey, theirIdentityPublicKey, salt) {
119
+ const shared = deriveLongTermShared(myIdentitySecretKey, theirIdentityPublicKey);
120
+ const topicOut = deriveTopic(shared, "verbeth:topic-out:v1", salt);
121
+ const topicIn = deriveTopic(shared, "verbeth:topic-in:v1", salt);
122
+ const chkFull = keccak256(Buffer.concat([
123
+ toUtf8Bytes("verbeth:topic-chk:v1"),
124
+ Buffer.from(topicOut.slice(2), 'hex'),
125
+ Buffer.from(topicIn.slice(2), 'hex'),
126
+ ]));
127
+ const checksum = dataSlice(chkFull, 8);
128
+ return { topicOut, topicIn, checksum };
129
+ }
130
+ export function verifyDuplexTopicsChecksum(topicOut, topicIn, checksum) {
131
+ const chkFull = keccak256(Buffer.concat([
132
+ toUtf8Bytes("verbeth:topic-chk:v1"),
133
+ Buffer.from(topicOut.slice(2), 'hex'),
134
+ Buffer.from(topicIn.slice(2), 'hex'),
135
+ ]));
136
+ return dataSlice(chkFull, 8) === checksum;
137
+ }
@@ -1,46 +1,24 @@
1
1
  import { HandshakeResponseContent } from './payload.js';
2
2
  import { IdentityProof } from './types.js';
3
3
  /**
4
- * Encrypts a structured payload (JSON-serializable objects)
4
+ * Encrypts a structured payload (JSON-serializable objects) using NaCl box.
5
+ * Used for handshake responses where ratchet is not yet established.
5
6
  */
6
7
  export declare function encryptStructuredPayload<T>(payload: T, recipientPublicKey: Uint8Array, ephemeralSecretKey: Uint8Array, ephemeralPublicKey: Uint8Array, staticSigningSecretKey?: Uint8Array, staticSigningPublicKey?: Uint8Array): string;
7
8
  /**
8
- * Decrypts a structured payload with converter function
9
+ * Decrypts a structured payload with converter function.
10
+ * Used for handshake responses where ratchet is not yet established.
9
11
  */
10
12
  export declare function decryptStructuredPayload<T>(payloadJson: string, recipientSecretKey: Uint8Array, converter: (obj: any) => T, staticSigningPublicKey?: Uint8Array): T | null;
11
- export declare function encryptMessage(message: string, recipientPublicKey: Uint8Array, ephemeralSecretKey: Uint8Array, ephemeralPublicKey: Uint8Array, staticSigningSecretKey?: Uint8Array, staticSigningPublicKey?: Uint8Array): string;
12
- export declare function decryptMessage(payloadJson: string, recipientSecretKey: Uint8Array, staticSigningPublicKey?: Uint8Array): string | null;
13
- /**
14
- * Decrypts handshake response and extracts individual keys from unified format
15
- */
16
13
  export declare function decryptHandshakeResponse(payloadJson: string, initiatorEphemeralSecretKey: Uint8Array): HandshakeResponseContent | null;
17
- /**
18
- * helper to decrypt handshake response and extract individual keys
19
- */
20
14
  export declare function decryptAndExtractHandshakeKeys(payloadJson: string, initiatorEphemeralSecretKey: Uint8Array): {
21
15
  identityPubKey: Uint8Array;
22
16
  signingPubKey: Uint8Array;
23
17
  ephemeralPubKey: Uint8Array;
18
+ kemCiphertext?: Uint8Array;
24
19
  note?: string;
25
20
  identityProof: IdentityProof;
26
21
  } | null;
27
- /**
28
- * Responder: tag = H( KDF( ECDH(r, viewPubA), "verbeth:hsr"))
29
- */
30
- export declare function computeTagFromResponder(rSecretKey: Uint8Array, viewPubA: Uint8Array): `0x${string}`;
31
- /**
32
- * Initiator: tag = H( KDF( ECDH(viewPrivA, R), "verbeth:hsr"))
33
- */
34
- export declare function computeTagFromInitiator(viewPrivA: Uint8Array, R: Uint8Array): `0x${string}`;
35
- export declare function deriveLongTermShared(myIdentitySecretKey: Uint8Array, theirIdentityPublicKey: Uint8Array): Uint8Array;
36
- /**
37
- * Directional duplex topics (Initiator-Responder, Responder-Initiator).
38
- * Recommended salt: tag (bytes)
39
- */
40
- export declare function deriveDuplexTopics(myIdentitySecretKey: Uint8Array, theirIdentityPublicKey: Uint8Array, salt?: Uint8Array): {
41
- topicOut: `0x${string}`;
42
- topicIn: `0x${string}`;
43
- checksum: `0x${string}`;
44
- };
45
- export declare function verifyDuplexTopicsChecksum(topicOut: `0x${string}`, topicIn: `0x${string}`, checksum: `0x${string}`): boolean;
22
+ export declare function computeHybridTagFromResponder(rSecretKey: Uint8Array, viewPubA: Uint8Array, kemSecret: Uint8Array): `0x${string}`;
23
+ export declare function computeHybridTagFromInitiator(viewPrivA: Uint8Array, R: Uint8Array, kemSecret: Uint8Array): `0x${string}`;
46
24
  //# sourceMappingURL=crypto.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAMA,OAAO,EAML,wBAAwB,EAEzB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,OAAO,EAAE,CAAC,EACV,kBAAkB,EAAE,UAAU,EAC9B,kBAAkB,EAAE,UAAU,EAC9B,kBAAkB,EAAE,UAAU,EAC9B,sBAAsB,CAAC,EAAE,UAAU,EACnC,sBAAsB,CAAC,EAAE,UAAU,GAClC,MAAM,CAcR;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,WAAW,EAAE,MAAM,EACnB,kBAAkB,EAAE,UAAU,EAC9B,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,EAC1B,sBAAsB,CAAC,EAAE,UAAU,GAClC,CAAC,GAAG,IAAI,CAaV;AAGD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,kBAAkB,EAAE,UAAU,EAC9B,kBAAkB,EAAE,UAAU,EAC9B,kBAAkB,EAAE,UAAU,EAC9B,sBAAsB,CAAC,EAAE,UAAU,EACnC,sBAAsB,CAAC,EAAE,UAAU,GAClC,MAAM,CAUR;AAED,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,kBAAkB,EAAE,UAAU,EAC9B,sBAAsB,CAAC,EAAE,UAAU,GAClC,MAAM,GAAG,IAAI,CAQf;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,2BAA2B,EAAE,UAAU,GACtC,wBAAwB,GAAG,IAAI,CAgBjC;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,MAAM,EACnB,2BAA2B,EAAE,UAAU,GACtC;IACD,cAAc,EAAE,UAAU,CAAC;IAC3B,aAAa,EAAE,UAAU,CAAC;IAC1B,eAAe,EAAE,UAAU,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,aAAa,CAAC;CAC9B,GAAG,IAAI,CAcP;AAWD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,UAAU,GACnB,KAAK,MAAM,EAAE,CAGf;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,UAAU,EACrB,CAAC,EAAE,UAAU,GACZ,KAAK,MAAM,EAAE,CAGf;AAkBD,wBAAgB,oBAAoB,CAClC,mBAAmB,EAAE,UAAU,EAC/B,sBAAsB,EAAE,UAAU,GACjC,UAAU,CAEZ;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,mBAAmB,EAAE,UAAU,EAC/B,sBAAsB,EAAE,UAAU,EAClC,IAAI,CAAC,EAAE,UAAU,GAChB;IAAE,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAA;CAAE,CAW9E;AAED,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,KAAK,MAAM,EAAE,EACvB,OAAO,EAAE,KAAK,MAAM,EAAE,EACtB,QAAQ,EAAE,KAAK,MAAM,EAAE,GACtB,OAAO,CAOT"}
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAkBA,OAAO,EAKL,wBAAwB,EAEzB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAM3C;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,OAAO,EAAE,CAAC,EACV,kBAAkB,EAAE,UAAU,EAC9B,kBAAkB,EAAE,UAAU,EAC9B,kBAAkB,EAAE,UAAU,EAC9B,sBAAsB,CAAC,EAAE,UAAU,EACnC,sBAAsB,CAAC,EAAE,UAAU,GAClC,MAAM,CAcR;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,WAAW,EAAE,MAAM,EACnB,kBAAkB,EAAE,UAAU,EAC9B,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,EAC1B,sBAAsB,CAAC,EAAE,UAAU,GAClC,CAAC,GAAG,IAAI,CAaV;AAOD,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,2BAA2B,EAAE,UAAU,GACtC,wBAAwB,GAAG,IAAI,CAiBjC;AAGD,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,MAAM,EACnB,2BAA2B,EAAE,UAAU,GACtC;IACD,cAAc,EAAE,UAAU,CAAC;IAC3B,aAAa,EAAE,UAAU,CAAC;IAC1B,eAAe,EAAE,UAAU,CAAC;IAC5B,aAAa,CAAC,EAAE,UAAU,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,aAAa,CAAC;CAC9B,GAAG,IAAI,CAeP;AAWD,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,UAAU,EACpB,SAAS,EAAE,UAAU,GACpB,KAAK,MAAM,EAAE,CAGf;AAED,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,UAAU,EACrB,CAAC,EAAE,UAAU,EACb,SAAS,EAAE,UAAU,GACpB,KAAK,MAAM,EAAE,CAGf"}
@@ -1,11 +1,26 @@
1
1
  // packages/sdk/src/crypto.ts
2
+ /**
3
+ * This module handles:
4
+ * - Handshake encryption/decryption
5
+ * - Tag computation for handshake responses
6
+ *
7
+ * Post-handshake message encryption uses the ratchet module.
8
+ * See `ratchet/encrypt.ts` and `ratchet/decrypt.ts` for Double Ratchet.
9
+ *
10
+ * Topic derivation is handled entirely by the ratchet module.
11
+ * See `ratchet/kdf.ts` for `deriveTopicFromDH`.
12
+ */
2
13
  import nacl from 'tweetnacl';
3
- import { keccak256, toUtf8Bytes, dataSlice } from 'ethers';
14
+ import { keccak256, toUtf8Bytes } from 'ethers';
4
15
  import { sha256 } from '@noble/hashes/sha2';
5
16
  import { hkdf } from '@noble/hashes/hkdf';
6
17
  import { encodePayload, decodePayload, encodeStructuredContent, decodeStructuredContent, extractKeysFromHandshakeResponse } from './payload.js';
18
+ // =============================================================================
19
+ // Handshake Encryption
20
+ // =============================================================================
7
21
  /**
8
- * Encrypts a structured payload (JSON-serializable objects)
22
+ * Encrypts a structured payload (JSON-serializable objects) using NaCl box.
23
+ * Used for handshake responses where ratchet is not yet established.
9
24
  */
10
25
  export function encryptStructuredPayload(payload, recipientPublicKey, ephemeralSecretKey, ephemeralPublicKey, staticSigningSecretKey, staticSigningPublicKey) {
11
26
  // encode payload as binary JSON
@@ -20,7 +35,8 @@ export function encryptStructuredPayload(payload, recipientPublicKey, ephemeralS
20
35
  return encodePayload(ephemeralPublicKey, nonce, box, sig);
21
36
  }
22
37
  /**
23
- * Decrypts a structured payload with converter function
38
+ * Decrypts a structured payload with converter function.
39
+ * Used for handshake responses where ratchet is not yet established.
24
40
  */
25
41
  export function decryptStructuredPayload(payloadJson, recipientSecretKey, converter, staticSigningPublicKey) {
26
42
  const { epk, nonce, ciphertext, sig } = decodePayload(payloadJson);
@@ -35,18 +51,9 @@ export function decryptStructuredPayload(payloadJson, recipientSecretKey, conver
35
51
  return null;
36
52
  return decodeStructuredContent(box, converter);
37
53
  }
38
- // wrappers for encrypting and decrypting messages
39
- export function encryptMessage(message, recipientPublicKey, ephemeralSecretKey, ephemeralPublicKey, staticSigningSecretKey, staticSigningPublicKey) {
40
- const payload = { content: message };
41
- return encryptStructuredPayload(payload, recipientPublicKey, ephemeralSecretKey, ephemeralPublicKey, staticSigningSecretKey, staticSigningPublicKey);
42
- }
43
- export function decryptMessage(payloadJson, recipientSecretKey, staticSigningPublicKey) {
44
- const result = decryptStructuredPayload(payloadJson, recipientSecretKey, (obj) => obj, staticSigningPublicKey);
45
- return result ? result.content : null;
46
- }
47
- /**
48
- * Decrypts handshake response and extracts individual keys from unified format
49
- */
54
+ // =============================================================================
55
+ // Handshake Response Decryption
56
+ // =============================================================================
50
57
  export function decryptHandshakeResponse(payloadJson, initiatorEphemeralSecretKey) {
51
58
  return decryptStructuredPayload(payloadJson, initiatorEphemeralSecretKey, (obj) => {
52
59
  if (!obj.identityProof) {
@@ -55,14 +62,12 @@ export function decryptHandshakeResponse(payloadJson, initiatorEphemeralSecretKe
55
62
  return {
56
63
  unifiedPubKeys: Uint8Array.from(Buffer.from(obj.unifiedPubKeys, 'base64')),
57
64
  ephemeralPubKey: Uint8Array.from(Buffer.from(obj.ephemeralPubKey, 'base64')),
65
+ ...(obj.kemCiphertext && { kemCiphertext: Uint8Array.from(Buffer.from(obj.kemCiphertext, 'base64')) }),
58
66
  note: obj.note,
59
- identityProof: obj.identityProof
67
+ identityProof: obj.identityProof,
60
68
  };
61
69
  });
62
70
  }
63
- /**
64
- * helper to decrypt handshake response and extract individual keys
65
- */
66
71
  export function decryptAndExtractHandshakeKeys(payloadJson, initiatorEphemeralSecretKey) {
67
72
  const decrypted = decryptHandshakeResponse(payloadJson, initiatorEphemeralSecretKey);
68
73
  if (!decrypted)
@@ -74,64 +79,23 @@ export function decryptAndExtractHandshakeKeys(payloadJson, initiatorEphemeralSe
74
79
  identityPubKey: extracted.identityPubKey,
75
80
  signingPubKey: extracted.signingPubKey,
76
81
  ephemeralPubKey: extracted.ephemeralPubKey,
82
+ kemCiphertext: decrypted.kemCiphertext,
77
83
  note: decrypted.note,
78
84
  identityProof: decrypted.identityProof
79
85
  };
80
86
  }
81
- /**
82
- * HKDF(sha256) on shared secret, info="verbeth:hsr", then Keccak-256 -> bytes32 (0x...)
83
- */
84
- function finalizeHsrTag(shared) {
85
- const okm = hkdf(sha256, shared, new Uint8Array(0), toUtf8Bytes("verbeth:hsr"), 32);
87
+ // =============================================================================
88
+ // Hybrid Tag Computation (PQ-Secure)
89
+ // =============================================================================
90
+ function finalizeHybridHsrTag(kemSecret, ecdhShared) {
91
+ const okm = hkdf(sha256, kemSecret, ecdhShared, toUtf8Bytes("verbeth:hsr-hybrid:v1"), 32);
86
92
  return keccak256(okm);
87
93
  }
88
- /**
89
- * Responder: tag = H( KDF( ECDH(r, viewPubA), "verbeth:hsr"))
90
- */
91
- export function computeTagFromResponder(rSecretKey, viewPubA) {
92
- const shared = nacl.scalarMult(rSecretKey, viewPubA);
93
- return finalizeHsrTag(shared);
94
- }
95
- /**
96
- * Initiator: tag = H( KDF( ECDH(viewPrivA, R), "verbeth:hsr"))
97
- */
98
- export function computeTagFromInitiator(viewPrivA, R) {
99
- const shared = nacl.scalarMult(viewPrivA, R);
100
- return finalizeHsrTag(shared);
101
- }
102
- /**
103
- * Derives a bytes32 topic from the shared secret via HKDF(SHA256) + Keccak-256.
104
- * - info: domain separation (e.g., "verbeth:topic-out:v1")
105
- * - salt: recommended to use a tag as salt (stable and shareable)
106
- */
107
- function deriveTopic(shared, info, salt) {
108
- const okm = hkdf(sha256, shared, salt ?? new Uint8Array(0), new TextEncoder().encode(info), 32);
109
- return keccak256(okm);
110
- }
111
- export function deriveLongTermShared(myIdentitySecretKey, theirIdentityPublicKey) {
112
- return nacl.scalarMult(myIdentitySecretKey, theirIdentityPublicKey);
113
- }
114
- /**
115
- * Directional duplex topics (Initiator-Responder, Responder-Initiator).
116
- * Recommended salt: tag (bytes)
117
- */
118
- export function deriveDuplexTopics(myIdentitySecretKey, theirIdentityPublicKey, salt) {
119
- const shared = deriveLongTermShared(myIdentitySecretKey, theirIdentityPublicKey);
120
- const topicOut = deriveTopic(shared, "verbeth:topic-out:v1", salt);
121
- const topicIn = deriveTopic(shared, "verbeth:topic-in:v1", salt);
122
- const chkFull = keccak256(Buffer.concat([
123
- toUtf8Bytes("verbeth:topic-chk:v1"),
124
- Buffer.from(topicOut.slice(2), 'hex'),
125
- Buffer.from(topicIn.slice(2), 'hex'),
126
- ]));
127
- const checksum = dataSlice(chkFull, 8);
128
- return { topicOut, topicIn, checksum };
94
+ export function computeHybridTagFromResponder(rSecretKey, viewPubA, kemSecret) {
95
+ const ecdhShared = nacl.scalarMult(rSecretKey, viewPubA);
96
+ return finalizeHybridHsrTag(kemSecret, ecdhShared);
129
97
  }
130
- export function verifyDuplexTopicsChecksum(topicOut, topicIn, checksum) {
131
- const chkFull = keccak256(Buffer.concat([
132
- toUtf8Bytes("verbeth:topic-chk:v1"),
133
- Buffer.from(topicOut.slice(2), 'hex'),
134
- Buffer.from(topicIn.slice(2), 'hex'),
135
- ]));
136
- return dataSlice(chkFull, 8) === checksum;
98
+ export function computeHybridTagFromInitiator(viewPrivA, R, kemSecret) {
99
+ const ecdhShared = nacl.scalarMult(viewPrivA, R);
100
+ return finalizeHybridHsrTag(kemSecret, ecdhShared);
137
101
  }
@@ -20,8 +20,7 @@ export declare class BaseSmartAccountExecutor implements IExecutor {
20
20
  private subAccountAddress?;
21
21
  private logChainInterface;
22
22
  private chainId;
23
- constructor(baseAccountProvider: any, logChainAddress: string, chainId?: number, // Base mainnet by default
24
- paymasterServiceUrl?: string | undefined, subAccountAddress?: string | undefined);
23
+ constructor(baseAccountProvider: any, logChainAddress: string, chainId?: number, paymasterServiceUrl?: string | undefined, subAccountAddress?: string | undefined);
25
24
  sendMessage(ciphertext: Uint8Array, topic: string, timestamp: number, nonce: bigint): Promise<any>;
26
25
  initiateHandshake(recipientHash: string, pubKeys: string, ephemeralPubKey: string, plaintextPayload: Uint8Array): Promise<any>;
27
26
  respondToHandshake(inResponseTo: string, responderEphemeralR: string, ciphertext: Uint8Array): Promise<any>;
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/executor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/executor.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,6 @@ import { Interface, toBeHex, zeroPadValue, } from "ethers";
3
3
  function pack128x128(high, low) {
4
4
  return (high << 128n) | (low & ((1n << 128n) - 1n));
5
5
  }
6
- // Unpack a packed 256-bit value into two 128-bit values
7
6
  export function split128x128(word) {
8
7
  const lowMask = (1n << 128n) - 1n;
9
8
  return [word >> 128n, word & lowMask];
@@ -47,8 +46,7 @@ export class EOAExecutor {
47
46
  }
48
47
  // Base Smart Account Executor - Uses wallet_sendCalls for sponsored transactions
49
48
  export class BaseSmartAccountExecutor {
50
- constructor(baseAccountProvider, logChainAddress, chainId = 8453, // Base mainnet by default
51
- paymasterServiceUrl, subAccountAddress) {
49
+ constructor(baseAccountProvider, logChainAddress, chainId = 8453, paymasterServiceUrl, subAccountAddress) {
52
50
  this.baseAccountProvider = baseAccountProvider;
53
51
  this.logChainAddress = logChainAddress;
54
52
  this.paymasterServiceUrl = paymasterServiceUrl;
@@ -58,7 +56,6 @@ export class BaseSmartAccountExecutor {
58
56
  "function initiateHandshake(bytes32 recipientHash, bytes pubKeys, bytes ephemeralPubKey, bytes plaintextPayload)",
59
57
  "function respondToHandshake(bytes32 inResponseTo, bytes32 responderEphemeralR, bytes ciphertext)",
60
58
  ]);
61
- // Convert chainId to hex
62
59
  this.chainId =
63
60
  chainId === 8453
64
61
  ? "0x2105" // Base mainnet
@@ -103,7 +100,6 @@ export class BaseSmartAccountExecutor {
103
100
  }
104
101
  async executeCalls(calls) {
105
102
  try {
106
- //console.log("DEBUG: Sub account address:", this.subAccountAddress);
107
103
  const requestParams = {
108
104
  version: "1.0",
109
105
  chainId: this.chainId,
@@ -112,7 +108,6 @@ export class BaseSmartAccountExecutor {
112
108
  //** WORK IN PROGRESS */
113
109
  if (this.subAccountAddress) {
114
110
  requestParams.from = this.subAccountAddress;
115
- //console.log("DEBUG: Using sub account for transaction");
116
111
  }
117
112
  if (this.paymasterServiceUrl) {
118
113
  requestParams.capabilities = {
@@ -120,19 +115,15 @@ export class BaseSmartAccountExecutor {
120
115
  url: this.paymasterServiceUrl,
121
116
  },
122
117
  };
123
- //console.log("DEBUG: Using paymaster for gas sponsorship");
124
118
  }
125
- //console.log("DEBUG: Request params:", requestParams);
126
119
  const result = await this.baseAccountProvider.request({
127
120
  method: "wallet_sendCalls",
128
121
  params: [requestParams],
129
122
  });
130
- // first 32 bytes are the actual userop hash
131
123
  if (typeof result === "string" &&
132
124
  result.startsWith("0x") &&
133
125
  result.length > 66) {
134
- const actualTxHash = "0x" + result.slice(2, 66); // Extract first 32 bytes
135
- //console.log("DEBUG: extracted tx hash:", actualTxHash);
126
+ const actualTxHash = "0x" + result.slice(2, 66);
136
127
  return { hash: actualTxHash };
137
128
  }
138
129
  return result;
@@ -155,7 +146,6 @@ export class UserOpExecutor {
155
146
  "function initiateHandshake(bytes32 recipientHash, bytes pubKeys, bytes ephemeralPubKey, bytes plaintextPayload)",
156
147
  "function respondToHandshake(bytes32 inResponseTo, bytes32 responderEphemeralR, bytes ciphertext)",
157
148
  ]);
158
- // Smart account interface for executing calls to other contracts
159
149
  this.smartAccountInterface = new Interface([
160
150
  "function execute(address target, uint256 value, bytes calldata data) returns (bytes)",
161
151
  ]);
@@ -164,7 +154,7 @@ export class UserOpExecutor {
164
154
  const logChainCallData = this.logChainInterface.encodeFunctionData("sendMessage", [ciphertext, topic, timestamp, nonce]);
165
155
  const smartAccountCallData = this.smartAccountInterface.encodeFunctionData("execute", [
166
156
  this.logChainAddress,
167
- 0, // value
157
+ 0,
168
158
  logChainCallData,
169
159
  ]);
170
160
  return this.executeUserOp(smartAccountCallData);
@@ -173,7 +163,7 @@ export class UserOpExecutor {
173
163
  const logChainCallData = this.logChainInterface.encodeFunctionData("initiateHandshake", [recipientHash, pubKeys, ephemeralPubKey, plaintextPayload]);
174
164
  const smartAccountCallData = this.smartAccountInterface.encodeFunctionData("execute", [
175
165
  this.logChainAddress,
176
- 0, // value
166
+ 0,
177
167
  logChainCallData,
178
168
  ]);
179
169
  return this.executeUserOp(smartAccountCallData);
@@ -182,7 +172,7 @@ export class UserOpExecutor {
182
172
  const logChainCallData = this.logChainInterface.encodeFunctionData("respondToHandshake", [inResponseTo, responderEphemeralR, ciphertext]);
183
173
  const smartAccountCallData = this.smartAccountInterface.encodeFunctionData("execute", [
184
174
  this.logChainAddress,
185
- 0, // value
175
+ 0,
186
176
  logChainCallData,
187
177
  ]);
188
178
  return this.executeUserOp(smartAccountCallData);
@@ -209,7 +199,7 @@ export class UserOpExecutor {
209
199
  return receipt;
210
200
  }
211
201
  }
212
- // Direct EntryPoint Executor - for local testing (bypasses bundler)
202
+ // Direct EntryPoint Executor (bypasses bundler for local testing)
213
203
  export class DirectEntryPointExecutor {
214
204
  constructor(smartAccountAddress, entryPointContract, logChainAddress, smartAccountClient, signer) {
215
205
  this.smartAccountAddress = smartAccountAddress;
@@ -221,7 +211,6 @@ export class DirectEntryPointExecutor {
221
211
  "function initiateHandshake(bytes32 recipientHash, bytes pubKeys, bytes ephemeralPubKey, bytes plaintextPayload)",
222
212
  "function respondToHandshake(bytes32 inResponseTo, bytes32 responderEphemeralR, bytes ciphertext)",
223
213
  ]);
224
- // Smart account interface for executing calls to other contracts
225
214
  this.smartAccountInterface = new Interface([
226
215
  "function execute(address target, uint256 value, bytes calldata data) returns (bytes)",
227
216
  ]);
@@ -241,7 +230,7 @@ export class DirectEntryPointExecutor {
241
230
  const logChainCallData = this.logChainInterface.encodeFunctionData("initiateHandshake", [recipientHash, pubKeys, ephemeralPubKey, plaintextPayload]);
242
231
  const smartAccountCallData = this.smartAccountInterface.encodeFunctionData("execute", [
243
232
  this.logChainAddress,
244
- 0, // value
233
+ 0,
245
234
  logChainCallData,
246
235
  ]);
247
236
  return this.executeDirectUserOp(smartAccountCallData);
@@ -250,7 +239,7 @@ export class DirectEntryPointExecutor {
250
239
  const logChainCallData = this.logChainInterface.encodeFunctionData("respondToHandshake", [inResponseTo, responderEphemeralR, ciphertext]);
251
240
  const smartAccountCallData = this.smartAccountInterface.encodeFunctionData("execute", [
252
241
  this.logChainAddress,
253
- 0, // value
242
+ 0,
254
243
  logChainCallData,
255
244
  ]);
256
245
  return this.executeDirectUserOp(smartAccountCallData);
@@ -290,11 +279,8 @@ export class DirectEntryPointExecutor {
290
279
  signature: "0x",
291
280
  };
292
281
  }
293
- // Pad bigints, bytes32 before signing
294
282
  const paddedUserOp = padBigints(userOp);
295
- //console.log("Padded UserOp:", paddedUserOp);
296
283
  const signed = await this.smartAccountClient.signUserOperation(paddedUserOp);
297
- // Direct submit to EntryPoint
298
284
  const tx = await this.entryPointContract.handleOps([signed], await this.signer.getAddress());
299
285
  return tx;
300
286
  }
@@ -320,7 +306,6 @@ export class ExecutorFactory {
320
306
  try {
321
307
  const provider = signerOrAccount?.provider || signerOrAccount;
322
308
  if (provider && typeof provider.request === "function") {
323
- // test if provider supports wallet_sendCalls
324
309
  const capabilities = await provider
325
310
  .request({
326
311
  method: "wallet_getCapabilities",
@@ -347,7 +332,6 @@ export class ExecutorFactory {
347
332
  return new UserOpExecutor(signerOrAccount.address, options.logChainAddress, options.bundlerClient, signerOrAccount);
348
333
  }
349
334
  }
350
- // default to EOA executor
351
335
  return new EOAExecutor(contract);
352
336
  }
353
337
  }
@@ -0,0 +1,51 @@
1
+ import { Signer } from "ethers";
2
+ import nacl from 'tweetnacl';
3
+ import { IdentityKeyPair, IdentityProof } from './types.js';
4
+ import { IExecutor } from './executor.js';
5
+ export interface KemKeyPair {
6
+ publicKey: Uint8Array;
7
+ secretKey: Uint8Array;
8
+ }
9
+ /**
10
+ * Initiates an on-chain handshake with unified keys and mandatory identity proof.
11
+ * Executor-agnostic: works with EOA, UserOp, and Direct EntryPoint
12
+ *
13
+ * @returns Transaction, ephemeral keypair, and KEM keypair (must be persisted for session init)
14
+ */
15
+ export declare function initiateHandshake({ executor, recipientAddress, identityKeyPair, plaintextPayload, identityProof, }: {
16
+ executor: IExecutor;
17
+ recipientAddress: string;
18
+ identityKeyPair: IdentityKeyPair;
19
+ plaintextPayload: string;
20
+ identityProof: IdentityProof;
21
+ signer?: Signer;
22
+ }): Promise<{
23
+ tx: any;
24
+ ephemeralKeyPair: nacl.BoxKeyPair;
25
+ kemKeyPair: KemKeyPair;
26
+ }>;
27
+ /**
28
+ * Responds to a handshake with unified keys and mandatory identity proof.
29
+ * Executor-agnostic: works with EOA, UserOp, and Direct EntryPoint
30
+ *
31
+ * If initiator includes KEM public key, encapsulates a shared secret and includes ciphertext in response.
32
+ *
33
+ * @returns Transaction, tag, salt, ephemeral keys, and KEM secret
34
+ */
35
+ export declare function respondToHandshake({ executor, initiatorEphemeralPubKey, responderIdentityKeyPair, note, identityProof, }: {
36
+ executor: IExecutor;
37
+ /** Initiator's ephemeral key (32 bytes X25519) OR extended key (1216 bytes: X25519 + ML-KEM) */
38
+ initiatorEphemeralPubKey: Uint8Array;
39
+ responderIdentityKeyPair: IdentityKeyPair;
40
+ note?: string;
41
+ identityProof: IdentityProof;
42
+ signer?: Signer;
43
+ }): Promise<{
44
+ tx: any;
45
+ salt: Uint8Array;
46
+ tag: `0x${string}`;
47
+ responderEphemeralSecret: Uint8Array;
48
+ responderEphemeralPublic: Uint8Array;
49
+ kemSharedSecret?: Uint8Array;
50
+ }>;
51
+ //# sourceMappingURL=handshake.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handshake.d.ts","sourceRoot":"","sources":["../../src/handshake.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,MAAM,EAEP,MAAM,QAAQ,CAAC;AAChB,OAAO,IAAI,MAAM,WAAW,CAAC;AAQ7B,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI1C,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,aAAa,GACd,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,eAAe,CAAC;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC;IACV,EAAE,EAAE,GAAG,CAAC;IACR,gBAAgB,EAAE,IAAI,CAAC,UAAU,CAAC;IAClC,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC,CA4CD;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,QAAQ,EACR,wBAAwB,EACxB,wBAAwB,EACxB,IAAI,EACJ,aAAa,GACd,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,gGAAgG;IAChG,wBAAwB,EAAE,UAAU,CAAC;IACrC,wBAAwB,EAAE,eAAe,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,aAAa,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC;IACV,EAAE,EAAE,GAAG,CAAC;IACR,IAAI,EAAE,UAAU,CAAC;IACjB,GAAG,EAAE,KAAK,MAAM,EAAE,CAAC;IAEnB,wBAAwB,EAAE,UAAU,CAAC;IAErC,wBAAwB,EAAE,UAAU,CAAC;IAErC,eAAe,CAAC,EAAE,UAAU,CAAC;CAC9B,CAAC,CAuFD"}