@verbeth/sdk 0.1.4 → 0.1.6

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 (190) hide show
  1. package/README.md +20 -168
  2. package/dist/esm/src/addresses.d.ts +20 -0
  3. package/dist/esm/src/addresses.d.ts.map +1 -0
  4. package/dist/esm/src/addresses.js +33 -0
  5. package/dist/esm/src/client/HsrTagIndex.d.ts +77 -0
  6. package/dist/esm/src/client/HsrTagIndex.d.ts.map +1 -0
  7. package/dist/esm/src/client/HsrTagIndex.js +157 -0
  8. package/dist/esm/src/client/PendingManager.d.ts +65 -0
  9. package/dist/esm/src/client/PendingManager.d.ts.map +1 -0
  10. package/dist/esm/src/client/PendingManager.js +84 -0
  11. package/dist/esm/src/client/SessionManager.d.ts +65 -0
  12. package/dist/esm/src/client/SessionManager.d.ts.map +1 -0
  13. package/dist/esm/src/client/SessionManager.js +146 -0
  14. package/dist/esm/src/client/VerbethClient.d.ts +153 -99
  15. package/dist/esm/src/client/VerbethClient.d.ts.map +1 -1
  16. package/dist/esm/src/client/VerbethClient.js +429 -123
  17. package/dist/esm/src/client/VerbethClientBuilder.d.ts +105 -0
  18. package/dist/esm/src/client/VerbethClientBuilder.d.ts.map +1 -0
  19. package/dist/esm/src/client/VerbethClientBuilder.js +146 -0
  20. package/dist/esm/src/client/hsrMatcher.d.ts +22 -0
  21. package/dist/esm/src/client/hsrMatcher.d.ts.map +1 -0
  22. package/dist/esm/src/client/hsrMatcher.js +31 -0
  23. package/dist/esm/src/client/index.d.ts +6 -1
  24. package/dist/esm/src/client/index.d.ts.map +1 -1
  25. package/dist/esm/src/client/index.js +2 -0
  26. package/dist/esm/src/client/types.d.ts +151 -10
  27. package/dist/esm/src/client/types.d.ts.map +1 -1
  28. package/dist/esm/src/crypto(old).d.ts +46 -0
  29. package/dist/esm/src/crypto(old).d.ts.map +1 -0
  30. package/dist/esm/src/crypto(old).js +137 -0
  31. package/dist/esm/src/crypto.d.ts +7 -29
  32. package/dist/esm/src/crypto.d.ts.map +1 -1
  33. package/dist/esm/src/crypto.js +36 -72
  34. package/dist/esm/src/executor.d.ts +17 -18
  35. package/dist/esm/src/executor.d.ts.map +1 -1
  36. package/dist/esm/src/executor.js +54 -70
  37. package/dist/esm/src/handshake.d.ts +51 -0
  38. package/dist/esm/src/handshake.d.ts.map +1 -0
  39. package/dist/esm/src/handshake.js +105 -0
  40. package/dist/esm/src/identity.d.ts +24 -18
  41. package/dist/esm/src/identity.d.ts.map +1 -1
  42. package/dist/esm/src/identity.js +126 -31
  43. package/dist/esm/src/index.d.ts +11 -7
  44. package/dist/esm/src/index.d.ts.map +1 -1
  45. package/dist/esm/src/index.js +10 -7
  46. package/dist/esm/src/payload.d.ts +3 -30
  47. package/dist/esm/src/payload.d.ts.map +1 -1
  48. package/dist/esm/src/payload.js +3 -77
  49. package/dist/esm/src/pq/kem.d.ts +33 -0
  50. package/dist/esm/src/pq/kem.d.ts.map +1 -0
  51. package/dist/esm/src/pq/kem.js +40 -0
  52. package/dist/esm/src/ratchet/auth.d.ts +34 -0
  53. package/dist/esm/src/ratchet/auth.d.ts.map +1 -0
  54. package/dist/esm/src/ratchet/auth.js +88 -0
  55. package/dist/esm/src/ratchet/codec.d.ts +52 -0
  56. package/dist/esm/src/ratchet/codec.d.ts.map +1 -0
  57. package/dist/esm/src/ratchet/codec.js +127 -0
  58. package/dist/esm/src/ratchet/decrypt.d.ts +28 -0
  59. package/dist/esm/src/ratchet/decrypt.d.ts.map +1 -0
  60. package/dist/esm/src/ratchet/decrypt.js +255 -0
  61. package/dist/esm/src/ratchet/encrypt.d.ts +17 -0
  62. package/dist/esm/src/ratchet/encrypt.d.ts.map +1 -0
  63. package/dist/esm/src/ratchet/encrypt.js +78 -0
  64. package/dist/esm/src/ratchet/index.d.ts +8 -0
  65. package/dist/esm/src/ratchet/index.d.ts.map +1 -0
  66. package/dist/esm/src/ratchet/index.js +8 -0
  67. package/dist/esm/src/ratchet/kdf.d.ts +60 -0
  68. package/dist/esm/src/ratchet/kdf.d.ts.map +1 -0
  69. package/dist/esm/src/ratchet/kdf.js +91 -0
  70. package/dist/esm/src/ratchet/session.d.ts +43 -0
  71. package/dist/esm/src/ratchet/session.d.ts.map +1 -0
  72. package/dist/esm/src/ratchet/session.js +139 -0
  73. package/dist/esm/src/ratchet/types.d.ts +168 -0
  74. package/dist/esm/src/ratchet/types.d.ts.map +1 -0
  75. package/dist/esm/src/ratchet/types.js +27 -0
  76. package/dist/esm/src/safeSessionSigner.d.ts +35 -0
  77. package/dist/esm/src/safeSessionSigner.d.ts.map +1 -0
  78. package/dist/esm/src/safeSessionSigner.js +59 -0
  79. package/dist/esm/src/send.d.ts +32 -24
  80. package/dist/esm/src/send.d.ts.map +1 -1
  81. package/dist/esm/src/send.js +84 -39
  82. package/dist/esm/src/types.d.ts +8 -13
  83. package/dist/esm/src/types.d.ts.map +1 -1
  84. package/dist/esm/src/utils/safeSessionSigner.d.ts +23 -0
  85. package/dist/esm/src/utils/safeSessionSigner.d.ts.map +1 -0
  86. package/dist/esm/src/utils/safeSessionSigner.js +59 -0
  87. package/dist/esm/src/utils/txQueue.d.ts +12 -0
  88. package/dist/esm/src/utils/txQueue.d.ts.map +1 -0
  89. package/dist/esm/src/utils/txQueue.js +25 -0
  90. package/dist/esm/src/utils.d.ts +2 -3
  91. package/dist/esm/src/utils.d.ts.map +1 -1
  92. package/dist/esm/src/utils.js +5 -5
  93. package/dist/esm/src/verify.d.ts +9 -25
  94. package/dist/esm/src/verify.d.ts.map +1 -1
  95. package/dist/esm/src/verify.js +49 -50
  96. package/dist/src/addresses.d.ts +20 -0
  97. package/dist/src/addresses.d.ts.map +1 -0
  98. package/dist/src/addresses.js +33 -0
  99. package/dist/src/client/HsrTagIndex.d.ts +77 -0
  100. package/dist/src/client/HsrTagIndex.d.ts.map +1 -0
  101. package/dist/src/client/HsrTagIndex.js +157 -0
  102. package/dist/src/client/PendingManager.d.ts +65 -0
  103. package/dist/src/client/PendingManager.d.ts.map +1 -0
  104. package/dist/src/client/PendingManager.js +84 -0
  105. package/dist/src/client/SessionManager.d.ts +65 -0
  106. package/dist/src/client/SessionManager.d.ts.map +1 -0
  107. package/dist/src/client/SessionManager.js +146 -0
  108. package/dist/src/client/VerbethClient.d.ts +153 -99
  109. package/dist/src/client/VerbethClient.d.ts.map +1 -1
  110. package/dist/src/client/VerbethClient.js +429 -123
  111. package/dist/src/client/VerbethClientBuilder.d.ts +105 -0
  112. package/dist/src/client/VerbethClientBuilder.d.ts.map +1 -0
  113. package/dist/src/client/VerbethClientBuilder.js +146 -0
  114. package/dist/src/client/hsrMatcher.d.ts +22 -0
  115. package/dist/src/client/hsrMatcher.d.ts.map +1 -0
  116. package/dist/src/client/hsrMatcher.js +31 -0
  117. package/dist/src/client/index.d.ts +6 -1
  118. package/dist/src/client/index.d.ts.map +1 -1
  119. package/dist/src/client/index.js +2 -0
  120. package/dist/src/client/types.d.ts +151 -10
  121. package/dist/src/client/types.d.ts.map +1 -1
  122. package/dist/src/crypto(old).d.ts +46 -0
  123. package/dist/src/crypto(old).d.ts.map +1 -0
  124. package/dist/src/crypto(old).js +137 -0
  125. package/dist/src/crypto.d.ts +7 -29
  126. package/dist/src/crypto.d.ts.map +1 -1
  127. package/dist/src/crypto.js +36 -72
  128. package/dist/src/executor.d.ts +17 -18
  129. package/dist/src/executor.d.ts.map +1 -1
  130. package/dist/src/executor.js +54 -70
  131. package/dist/src/handshake.d.ts +51 -0
  132. package/dist/src/handshake.d.ts.map +1 -0
  133. package/dist/src/handshake.js +105 -0
  134. package/dist/src/identity.d.ts +24 -18
  135. package/dist/src/identity.d.ts.map +1 -1
  136. package/dist/src/identity.js +126 -31
  137. package/dist/src/index.d.ts +11 -7
  138. package/dist/src/index.d.ts.map +1 -1
  139. package/dist/src/index.js +10 -7
  140. package/dist/src/payload.d.ts +3 -30
  141. package/dist/src/payload.d.ts.map +1 -1
  142. package/dist/src/payload.js +3 -77
  143. package/dist/src/pq/kem.d.ts +33 -0
  144. package/dist/src/pq/kem.d.ts.map +1 -0
  145. package/dist/src/pq/kem.js +40 -0
  146. package/dist/src/ratchet/auth.d.ts +34 -0
  147. package/dist/src/ratchet/auth.d.ts.map +1 -0
  148. package/dist/src/ratchet/auth.js +88 -0
  149. package/dist/src/ratchet/codec.d.ts +52 -0
  150. package/dist/src/ratchet/codec.d.ts.map +1 -0
  151. package/dist/src/ratchet/codec.js +127 -0
  152. package/dist/src/ratchet/decrypt.d.ts +28 -0
  153. package/dist/src/ratchet/decrypt.d.ts.map +1 -0
  154. package/dist/src/ratchet/decrypt.js +255 -0
  155. package/dist/src/ratchet/encrypt.d.ts +17 -0
  156. package/dist/src/ratchet/encrypt.d.ts.map +1 -0
  157. package/dist/src/ratchet/encrypt.js +78 -0
  158. package/dist/src/ratchet/index.d.ts +8 -0
  159. package/dist/src/ratchet/index.d.ts.map +1 -0
  160. package/dist/src/ratchet/index.js +8 -0
  161. package/dist/src/ratchet/kdf.d.ts +60 -0
  162. package/dist/src/ratchet/kdf.d.ts.map +1 -0
  163. package/dist/src/ratchet/kdf.js +91 -0
  164. package/dist/src/ratchet/session.d.ts +43 -0
  165. package/dist/src/ratchet/session.d.ts.map +1 -0
  166. package/dist/src/ratchet/session.js +139 -0
  167. package/dist/src/ratchet/types.d.ts +168 -0
  168. package/dist/src/ratchet/types.d.ts.map +1 -0
  169. package/dist/src/ratchet/types.js +27 -0
  170. package/dist/src/safeSessionSigner.d.ts +35 -0
  171. package/dist/src/safeSessionSigner.d.ts.map +1 -0
  172. package/dist/src/safeSessionSigner.js +59 -0
  173. package/dist/src/send.d.ts +32 -24
  174. package/dist/src/send.d.ts.map +1 -1
  175. package/dist/src/send.js +84 -39
  176. package/dist/src/types.d.ts +8 -13
  177. package/dist/src/types.d.ts.map +1 -1
  178. package/dist/src/utils/safeSessionSigner.d.ts +23 -0
  179. package/dist/src/utils/safeSessionSigner.d.ts.map +1 -0
  180. package/dist/src/utils/safeSessionSigner.js +59 -0
  181. package/dist/src/utils/txQueue.d.ts +12 -0
  182. package/dist/src/utils/txQueue.d.ts.map +1 -0
  183. package/dist/src/utils/txQueue.js +25 -0
  184. package/dist/src/utils.d.ts +2 -3
  185. package/dist/src/utils.d.ts.map +1 -1
  186. package/dist/src/utils.js +5 -5
  187. package/dist/src/verify.d.ts +9 -25
  188. package/dist/src/verify.d.ts.map +1 -1
  189. package/dist/src/verify.js +49 -50
  190. package/package.json +2 -1
@@ -1,22 +1,87 @@
1
+ // packages/sdk/src/utils/identity.ts
1
2
  import { sha256 } from "@noble/hashes/sha2";
2
3
  import { hkdf } from "@noble/hashes/hkdf";
3
- import { concat, hexlify } from "ethers";
4
+ import { Wallet, concat, hexlify, getBytes } from "ethers";
4
5
  import nacl from "tweetnacl";
5
6
  import { encodeUnifiedPubKeys } from "./payload.js";
7
+ const SECP256K1_N = BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
8
+ const SECP256K1_HALF_N = SECP256K1_N >> 1n;
9
+ function bytesToBigIntBE(bytes) {
10
+ let hex = "";
11
+ for (const b of bytes)
12
+ hex += b.toString(16).padStart(2, "0");
13
+ return hex.length ? BigInt("0x" + hex) : 0n;
14
+ }
15
+ function bigIntTo32BytesBE(x) {
16
+ let hex = x.toString(16);
17
+ if (hex.length > 64)
18
+ hex = hex.slice(hex.length - 64);
19
+ hex = hex.padStart(64, "0");
20
+ const out = new Uint8Array(32);
21
+ for (let i = 0; i < 32; i++) {
22
+ out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
23
+ }
24
+ return out;
25
+ }
6
26
  /**
7
- * HKDF (RFC 5869) identity key derivation.
8
- * Returns a proof binding the derived keypair to the wallet address.
27
+ * Canonicalize an Ethereum ECDSA signature (65 bytes) to low-s form (only used as KDF input)
9
28
  */
10
- export async function deriveIdentityKeyPairWithProof(signer, address) {
11
- // 1) Local secret seed (32B CSPRNG), domain-separated by address
12
- const r = nacl.randomBytes(32);
29
+ function canonicalizeEcdsaSig65(sig) {
30
+ if (sig.length !== 65)
31
+ return sig;
32
+ const r = sig.slice(0, 32);
33
+ const s = sig.slice(32, 64);
34
+ const v = sig[64];
35
+ const sBig = bytesToBigIntBE(s);
36
+ if (sBig <= SECP256K1_HALF_N)
37
+ return sig;
38
+ const sLow = SECP256K1_N - sBig;
39
+ const out = new Uint8Array(65);
40
+ out.set(r, 0);
41
+ out.set(bigIntTo32BytesBE(sLow), 32);
42
+ out[64] = v;
43
+ return out;
44
+ }
45
+ function buildSeedMessage(addrLower) {
46
+ const lines = [
47
+ "VerbEth Identity Seed v1",
48
+ `Address: ${addrLower}`,
49
+ "Context: verbeth",
50
+ ];
51
+ return lines.join("\n");
52
+ }
53
+ function buildBindingMessage(addrLower, pkEd25519Hex, pkX25519Hex, executorSafeAddress, ctx) {
54
+ const lines = [
55
+ "VerbEth Key Binding v1",
56
+ `Address: ${addrLower}`,
57
+ `PkEd25519: ${pkEd25519Hex}`,
58
+ `PkX25519: ${pkX25519Hex}`,
59
+ `ExecutorSafeAddress: ${executorSafeAddress ?? ""}`,
60
+ ];
61
+ if (typeof ctx?.chainId === "number")
62
+ lines.push(`ChainId: ${ctx.chainId}`);
63
+ if (ctx?.rpId)
64
+ lines.push(`RpId: ${ctx.rpId}`);
65
+ return lines.join("\n");
66
+ }
67
+ // ============================================================================
68
+ // Derive all keys from seed signature
69
+ // ============================================================================
70
+ /**
71
+ * Derive all identity keys and session key from a single seed signature.
72
+ */
73
+ export async function deriveIdentityKeys(signer, address) {
13
74
  const enc = new TextEncoder();
14
75
  const addrLower = address.toLowerCase();
15
- // IKM = HKDF(r || "verbeth/addr:" || address_lower)
16
- // salt/info are public domain labels
17
- const seedSalt = enc.encode("verbeth/seed-v1");
76
+ const seedMessage = buildSeedMessage(addrLower);
77
+ let seedSignature = await signer.signMessage(seedMessage);
78
+ const seedSigBytes = canonicalizeEcdsaSig65(getBytes(seedSignature));
79
+ seedSignature = "";
80
+ // IKM = HKDF( canonicalSig || H(seedMessage) || "verbeth/addr:" || address_lower )
81
+ const seedSalt = enc.encode("verbeth/seed-sig-v1");
18
82
  const seedInfo = enc.encode("verbeth/ikm");
19
- const ikmInput = concat([r, enc.encode("verbeth/addr:" + addrLower)]);
83
+ const seedMsgHash = sha256(enc.encode(seedMessage));
84
+ const ikmInput = getBytes(concat([seedSigBytes, seedMsgHash, enc.encode("verbeth/addr:" + addrLower)]));
20
85
  const ikm = hkdf(sha256, ikmInput, seedSalt, seedInfo, 32);
21
86
  // Derive X25519 (encryption)
22
87
  const info_x25519 = enc.encode("verbeth-x25519-v1");
@@ -26,6 +91,22 @@ export async function deriveIdentityKeyPairWithProof(signer, address) {
26
91
  const info_ed25519 = enc.encode("verbeth-ed25519-v1");
27
92
  const ed25519_seed = hkdf(sha256, ikm, new Uint8Array(0), info_ed25519, 32);
28
93
  const signKeyPair = nacl.sign.keyPair.fromSeed(ed25519_seed);
94
+ // Derive secp256k1 session key for txs via Safe module
95
+ const info_session = enc.encode("verbeth-session-secp256k1-v1");
96
+ const sessionSeed = hkdf(sha256, ikm, new Uint8Array(0), info_session, 32);
97
+ const sessionPrivateKey = hexlify(sessionSeed);
98
+ const sessionWallet = new Wallet(sessionPrivateKey);
99
+ const sessionAddress = sessionWallet.address;
100
+ try {
101
+ seedSigBytes.fill(0);
102
+ seedMsgHash.fill(0);
103
+ ikmInput.fill(0);
104
+ ikm.fill(0);
105
+ ed25519_seed.fill(0);
106
+ x25519_sk.fill(0);
107
+ sessionSeed.fill(0);
108
+ }
109
+ catch { }
29
110
  const pkX25519Hex = hexlify(boxKeyPair.publicKey);
30
111
  const pkEd25519Hex = hexlify(signKeyPair.publicKey);
31
112
  const keyPair = {
@@ -34,37 +115,51 @@ export async function deriveIdentityKeyPairWithProof(signer, address) {
34
115
  signingPublicKey: signKeyPair.publicKey,
35
116
  signingSecretKey: signKeyPair.secretKey,
36
117
  };
37
- // 2) Single signature binding both public keys
38
- const bindingMsgLines = [
39
- "VerbEth Key Binding v1",
40
- `Address: ${addrLower}`,
41
- `PkEd25519: ${pkEd25519Hex}`,
42
- `PkX25519: ${pkX25519Hex}`,
43
- `Context: verbeth`,
44
- `Version: 1`,
45
- ];
46
- const message = bindingMsgLines.join("\n");
118
+ return {
119
+ keyPair,
120
+ sessionPrivateKey,
121
+ sessionAddress,
122
+ pkX25519Hex,
123
+ pkEd25519Hex,
124
+ };
125
+ }
126
+ // ============================================================================
127
+ // Create binding proof with Safe address
128
+ // ============================================================================
129
+ /**
130
+ * Create the binding proof that ties the derived keys to the Safe address.
131
+ */
132
+ export async function createBindingProof(signer, address, derivedKeys, executorSafeAddress, ctx) {
133
+ const addrLower = address.toLowerCase();
134
+ const executorSafeAddressLower = executorSafeAddress.toLowerCase();
135
+ const message = buildBindingMessage(addrLower, derivedKeys.pkEd25519Hex, derivedKeys.pkX25519Hex, executorSafeAddressLower, ctx);
47
136
  const signature = await signer.signMessage(message);
48
137
  const messageRawHex = ("0x" +
49
138
  Buffer.from(message, "utf-8").toString("hex"));
50
139
  return {
51
- keyPair,
52
- identityProof: {
53
- message,
54
- signature,
55
- messageRawHex,
56
- },
140
+ message,
141
+ signature,
142
+ messageRawHex,
143
+ };
144
+ }
145
+ // this is when the Safe address is known upfront
146
+ export async function deriveIdentityKeyPairWithProof(signer, address, executorSafeAddress, ctx) {
147
+ const derivedKeys = await deriveIdentityKeys(signer, address);
148
+ const identityProof = await createBindingProof(signer, address, derivedKeys, executorSafeAddress ?? "", ctx);
149
+ return {
150
+ ...derivedKeys,
151
+ identityProof,
57
152
  };
58
153
  }
59
- export async function deriveIdentityWithUnifiedKeys(signer, address) {
60
- const result = await deriveIdentityKeyPairWithProof(signer, address);
61
- const unifiedPubKeys = encodeUnifiedPubKeys(result.keyPair.publicKey, // X25519
62
- result.keyPair.signingPublicKey // Ed25519
63
- );
154
+ export async function deriveIdentityWithUnifiedKeys(signer, address, executorSafeAddress, ctx) {
155
+ const result = await deriveIdentityKeyPairWithProof(signer, address, executorSafeAddress, ctx);
156
+ const unifiedPubKeys = encodeUnifiedPubKeys(result.keyPair.publicKey, result.keyPair.signingPublicKey);
64
157
  return {
65
158
  identityProof: result.identityProof,
66
159
  identityPubKey: result.keyPair.publicKey,
67
160
  signingPubKey: result.keyPair.signingPublicKey,
68
161
  unifiedPubKeys,
162
+ sessionPrivateKey: result.sessionPrivateKey,
163
+ sessionAddress: result.sessionAddress,
69
164
  };
70
165
  }
@@ -1,18 +1,22 @@
1
1
  export * from './crypto.js';
2
2
  export * from './payload.js';
3
- export * from './send.js';
3
+ export * from './handshake.js';
4
4
  export * from './verify.js';
5
5
  export * from './types.js';
6
6
  export * from './utils.js';
7
7
  export * from './identity.js';
8
8
  export * from './executor.js';
9
- export { decryptMessage as decryptLog } from './crypto.js';
10
- export { getNextNonce } from './utils/nonce.js';
11
- export { encodeUnifiedPubKeys, decodeUnifiedPubKeys, createHandshakePayload, createHandshakeResponseContent, extractKeysFromHandshakePayload, extractKeysFromHandshakeResponse, parseHandshakeKeys } from './payload.js';
12
- export { decryptAndExtractHandshakeKeys, decryptMessage, decryptHandshakeResponse } from './crypto.js';
9
+ export { encodeUnifiedPubKeys, decodeUnifiedPubKeys, createHandshakeResponseContent, extractKeysFromHandshakeResponse, parseHandshakeKeys } from './payload.js';
10
+ export { decryptAndExtractHandshakeKeys, decryptHandshakeResponse } from './crypto.js';
13
11
  export { verifyIdentityProof, verifyAndExtractHandshakeKeys, verifyAndExtractHandshakeResponseKeys } from './verify.js';
14
12
  export { deriveIdentityKeyPairWithProof, deriveIdentityWithUnifiedKeys } from './identity.js';
15
13
  export { IExecutor, EOAExecutor, UserOpExecutor, DirectEntryPointExecutor, ExecutorFactory } from './executor.js';
16
- export { VerbethClient } from './client/index.js';
17
- export type { VerbethClientConfig, HandshakeResult, HandshakeResponseResult } from './client/index.js';
14
+ export { SafeSessionSigner } from "./utils/safeSessionSigner.js";
15
+ export type { SafeSessionSignerOptions } from "./utils/safeSessionSigner.js";
16
+ export { VerbethClient, VerbethClientBuilder, createVerbethClient, matchHsrToContact, } from './client/index.js';
17
+ export type { VerbethClientConfig, VerbethClientCallbacks, TopicRatchetEvent, MessageDecryptedEvent, HandshakeResult, HandshakeResponseResult, SessionStore, PendingStore, PreparedMessage, DecryptedMessage, PendingMessage, PendingStatus, SendResult, ConfirmResult, SerializedSessionInfo, HsrEventData, CreateInitiatorSessionFromHsrParams, CreateVerbethClientOptions, PendingContactEntry, } from './client/index.js';
18
+ export * from './ratchet/index.js';
19
+ export { dh, deriveTopic, hybridInitialSecret } from './ratchet/kdf.js';
20
+ export { kem } from './pq/kem.js';
21
+ export * from './addresses.js';
18
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAE9B,OAAO,EAAE,cAAc,IAAI,UAAU,EAAE,MAAM,aAAa,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,8BAA8B,EAC9B,+BAA+B,EAC/B,gCAAgC,EAChC,kBAAkB,EACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,8BAA8B,EAC9B,cAAc,EACd,wBAAwB,EACzB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,qCAAqC,EACtC,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,8BAA8B,EAC9B,6BAA6B,EAC9B,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,SAAS,EACT,WAAW,EACX,cAAc,EACd,wBAAwB,EACxB,eAAe,EAChB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,uBAAuB,EACxB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAE9B,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,8BAA8B,EAC9B,gCAAgC,EAChC,kBAAkB,EACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,8BAA8B,EAC9B,wBAAwB,EACzB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,qCAAqC,EACtC,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,8BAA8B,EAC9B,6BAA6B,EAC9B,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,SAAS,EACT,WAAW,EACX,cAAc,EACd,wBAAwB,EACxB,eAAe,EAChB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,YAAY,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAE7E,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,uBAAuB,EAEvB,YAAY,EACZ,YAAY,EAEZ,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,aAAa,EAEb,UAAU,EACV,aAAa,EAEb,qBAAqB,EACrB,YAAY,EACZ,mCAAmC,EACnC,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAE3B,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAExE,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC,cAAc,gBAAgB,CAAC"}
package/dist/src/index.js CHANGED
@@ -1,17 +1,20 @@
1
+ // packages/sdk/src/index.ts
1
2
  export * from './crypto.js';
2
3
  export * from './payload.js';
3
- export * from './send.js';
4
+ export * from './handshake.js';
4
5
  export * from './verify.js';
5
6
  export * from './types.js';
6
7
  export * from './utils.js';
7
8
  export * from './identity.js';
8
9
  export * from './executor.js';
9
- export { decryptMessage as decryptLog } from './crypto.js';
10
- export { getNextNonce } from './utils/nonce.js';
11
- export { encodeUnifiedPubKeys, decodeUnifiedPubKeys, createHandshakePayload, createHandshakeResponseContent, extractKeysFromHandshakePayload, extractKeysFromHandshakeResponse, parseHandshakeKeys } from './payload.js';
12
- export { decryptAndExtractHandshakeKeys, decryptMessage, decryptHandshakeResponse } from './crypto.js';
10
+ export { encodeUnifiedPubKeys, decodeUnifiedPubKeys, createHandshakeResponseContent, extractKeysFromHandshakeResponse, parseHandshakeKeys } from './payload.js';
11
+ export { decryptAndExtractHandshakeKeys, decryptHandshakeResponse } from './crypto.js';
13
12
  export { verifyIdentityProof, verifyAndExtractHandshakeKeys, verifyAndExtractHandshakeResponseKeys } from './verify.js';
14
13
  export { deriveIdentityKeyPairWithProof, deriveIdentityWithUnifiedKeys } from './identity.js';
15
14
  export { EOAExecutor, UserOpExecutor, DirectEntryPointExecutor, ExecutorFactory } from './executor.js';
16
- // high-level client API
17
- export { VerbethClient } from './client/index.js';
15
+ export { SafeSessionSigner } from "./utils/safeSessionSigner.js";
16
+ export { VerbethClient, VerbethClientBuilder, createVerbethClient, matchHsrToContact, } from './client/index.js';
17
+ export * from './ratchet/index.js';
18
+ export { dh, deriveTopic, hybridInitialSecret } from './ratchet/kdf.js';
19
+ export { kem } from './pq/kem.js';
20
+ export * from './addresses.js';
@@ -1,4 +1,4 @@
1
- import { IdentityProof, TopicInfoWire } from './types.js';
1
+ import { IdentityProof } from './types.js';
2
2
  export interface EncryptedPayload {
3
3
  v: number;
4
4
  epk: string;
@@ -6,14 +6,6 @@ export interface EncryptedPayload {
6
6
  ct: string;
7
7
  sig?: string;
8
8
  }
9
- export interface MessagePayload {
10
- content: string;
11
- timestamp?: number;
12
- messageType?: 'text' | 'file' | 'media';
13
- metadata?: Record<string, any>;
14
- }
15
- export interface HandshakeResponsePayload extends EncryptedPayload {
16
- }
17
9
  export interface HandshakeContent {
18
10
  plaintextPayload: string;
19
11
  identityProof: IdentityProof;
@@ -50,30 +42,11 @@ export interface HandshakePayload {
50
42
  export interface HandshakeResponseContent {
51
43
  unifiedPubKeys: Uint8Array;
52
44
  ephemeralPubKey: Uint8Array;
45
+ kemCiphertext?: Uint8Array;
53
46
  note?: string;
54
47
  identityProof: IdentityProof;
55
- topicInfo?: TopicInfoWire;
56
48
  }
57
- export declare function encodeHandshakePayload(payload: HandshakePayload): Uint8Array;
58
- export declare function decodeHandshakePayload(encoded: Uint8Array): HandshakePayload;
59
- export declare function encodeHandshakeResponseContent(content: HandshakeResponseContent): Uint8Array;
60
- export declare function decodeHandshakeResponseContent(encoded: Uint8Array): HandshakeResponseContent;
61
- /**
62
- * Creates HandshakePayload from separate identity keys
63
- */
64
- export declare function createHandshakePayload(identityPubKey: Uint8Array, signingPubKey: Uint8Array, ephemeralPubKey: Uint8Array, plaintextPayload: string): HandshakePayload;
65
- /**
66
- * Creates HandshakeResponseContent from separate identity keys
67
- */
68
- export declare function createHandshakeResponseContent(identityPubKey: Uint8Array, signingPubKey: Uint8Array, ephemeralPubKey: Uint8Array, note?: string, identityProof?: IdentityProof, topicInfo?: TopicInfoWire): HandshakeResponseContent;
69
- /**
70
- * Extracts individual keys from HandshakePayload
71
- */
72
- export declare function extractKeysFromHandshakePayload(payload: HandshakePayload): {
73
- identityPubKey: Uint8Array;
74
- signingPubKey: Uint8Array;
75
- ephemeralPubKey: Uint8Array;
76
- } | null;
49
+ export declare function createHandshakeResponseContent(identityPubKey: Uint8Array, signingPubKey: Uint8Array, ephemeralPubKey: Uint8Array, note?: string, identityProof?: IdentityProof, kemCiphertext?: Uint8Array): HandshakeResponseContent;
77
50
  /**
78
51
  * Extracts individual keys from HandshakeResponseContent
79
52
  */
@@ -1 +1 @@
1
- {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../src/payload.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../src/payload.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,CAAC,EAAE,MAAM,CAAC;IACV,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;CAC9B;AAED,wBAAgB,qBAAqB,CAAC,gBAAgB,EAAE,MAAM,GAAG,gBAAgB,CAUhF;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAE3E;AAED,wBAAgB,aAAa,CAAC,eAAe,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,MAAM,CAS9H;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG;IAC3C,GAAG,EAAE,UAAU,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC;IAClB,UAAU,EAAE,UAAU,CAAC;IACvB,GAAG,CAAC,EAAE,UAAU,CAAA;CACjB,CAyBA;AAID,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,UAAU,CAQjE;AAGD,wBAAgB,uBAAuB,CAAC,CAAC,EACvC,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GACzB,CAAC,CAGH;AAID;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,cAAc,EAAE,UAAU,EAAG,oBAAoB;AACjD,aAAa,EAAE,UAAU,GACxB,UAAU,CAOZ;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,UAAU,GAAG;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,UAAU,CAAC;IAC3B,aAAa,EAAE,UAAU,CAAC;CAC3B,GAAG,IAAI,CAkBP;AAED,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,UAAU,CAAC;IAC3B,eAAe,EAAE,UAAU,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,UAAU,CAAC;IAC3B,eAAe,EAAE,UAAU,CAAC;IAC5B,aAAa,CAAC,EAAE,UAAU,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,aAAa,CAAC;CAC9B;AAED,wBAAgB,8BAA8B,CAC5C,cAAc,EAAE,UAAU,EAC1B,aAAa,EAAE,UAAU,EACzB,eAAe,EAAE,UAAU,EAC3B,IAAI,CAAC,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,aAAa,EAC7B,aAAa,CAAC,EAAE,UAAU,GACzB,wBAAwB,CAY1B;AAED;;GAEG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,wBAAwB,GAAG;IACnF,cAAc,EAAE,UAAU,CAAC;IAC3B,aAAa,EAAE,UAAU,CAAC;IAC1B,eAAe,EAAE,UAAU,CAAC;CAC7B,GAAG,IAAI,CASP;AAGD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAC9D,cAAc,EAAE,UAAU,CAAC;IAC3B,aAAa,EAAE,UAAU,CAAC;CAC3B,GAAG,IAAI,CAkBP"}
@@ -1,3 +1,4 @@
1
+ // packages/sdk/src/payload.ts
1
2
  export function parseHandshakePayload(plaintextPayload) {
2
3
  try {
3
4
  const parsed = JSON.parse(plaintextPayload);
@@ -80,7 +81,6 @@ signingPubKey // Ed25519 - 32 bytes
80
81
  */
81
82
  export function decodeUnifiedPubKeys(pubKeys) {
82
83
  if (pubKeys.length === 64) {
83
- // Legacy
84
84
  return {
85
85
  version: 0,
86
86
  identityPubKey: pubKeys.slice(0, 32),
@@ -88,7 +88,6 @@ export function decodeUnifiedPubKeys(pubKeys) {
88
88
  };
89
89
  }
90
90
  if (pubKeys.length === 65 && pubKeys[0] === 0x01) {
91
- // V1: with versioning
92
91
  return {
93
92
  version: 1,
94
93
  identityPubKey: pubKeys.slice(1, 33),
@@ -97,89 +96,16 @@ export function decodeUnifiedPubKeys(pubKeys) {
97
96
  }
98
97
  return null;
99
98
  }
100
- export function encodeHandshakePayload(payload) {
101
- return new TextEncoder().encode(JSON.stringify({
102
- unifiedPubKeys: Buffer.from(payload.unifiedPubKeys).toString('base64'),
103
- ephemeralPubKey: Buffer.from(payload.ephemeralPubKey).toString('base64'),
104
- plaintextPayload: payload.plaintextPayload
105
- }));
106
- }
107
- export function decodeHandshakePayload(encoded) {
108
- const json = new TextDecoder().decode(encoded);
109
- const parsed = JSON.parse(json);
110
- return {
111
- unifiedPubKeys: Uint8Array.from(Buffer.from(parsed.unifiedPubKeys, 'base64')),
112
- ephemeralPubKey: Uint8Array.from(Buffer.from(parsed.ephemeralPubKey, 'base64')),
113
- plaintextPayload: parsed.plaintextPayload
114
- };
115
- }
116
- export function encodeHandshakeResponseContent(content) {
117
- return new TextEncoder().encode(JSON.stringify({
118
- unifiedPubKeys: Buffer.from(content.unifiedPubKeys).toString('base64'),
119
- ephemeralPubKey: Buffer.from(content.ephemeralPubKey).toString('base64'),
120
- note: content.note,
121
- identityProof: content.identityProof,
122
- topicInfo: content.topicInfo ? {
123
- out: content.topicInfo.out,
124
- in: content.topicInfo.in,
125
- chk: content.topicInfo.chk
126
- } : undefined
127
- }));
128
- }
129
- export function decodeHandshakeResponseContent(encoded) {
130
- const json = new TextDecoder().decode(encoded);
131
- const obj = JSON.parse(json);
132
- if (!obj.identityProof) {
133
- throw new Error("Invalid handshake response: missing identityProof");
134
- }
135
- return {
136
- unifiedPubKeys: Uint8Array.from(Buffer.from(obj.unifiedPubKeys, 'base64')),
137
- ephemeralPubKey: Uint8Array.from(Buffer.from(obj.ephemeralPubKey, 'base64')),
138
- note: obj.note,
139
- identityProof: obj.identityProof,
140
- topicInfo: obj.topicInfo ? {
141
- out: obj.topicInfo.out,
142
- in: obj.topicInfo.in,
143
- chk: obj.topicInfo.chk
144
- } : undefined
145
- };
146
- }
147
- /**
148
- * Creates HandshakePayload from separate identity keys
149
- */
150
- export function createHandshakePayload(identityPubKey, signingPubKey, ephemeralPubKey, plaintextPayload) {
151
- return {
152
- unifiedPubKeys: encodeUnifiedPubKeys(identityPubKey, signingPubKey),
153
- ephemeralPubKey,
154
- plaintextPayload
155
- };
156
- }
157
- /**
158
- * Creates HandshakeResponseContent from separate identity keys
159
- */
160
- export function createHandshakeResponseContent(identityPubKey, signingPubKey, ephemeralPubKey, note, identityProof, topicInfo) {
99
+ export function createHandshakeResponseContent(identityPubKey, signingPubKey, ephemeralPubKey, note, identityProof, kemCiphertext) {
161
100
  if (!identityProof) {
162
101
  throw new Error("Identity proof is now mandatory for handshake responses");
163
102
  }
164
103
  return {
165
104
  unifiedPubKeys: encodeUnifiedPubKeys(identityPubKey, signingPubKey),
166
105
  ephemeralPubKey,
106
+ ...(kemCiphertext && { kemCiphertext }),
167
107
  note,
168
108
  identityProof,
169
- topicInfo
170
- };
171
- }
172
- /**
173
- * Extracts individual keys from HandshakePayload
174
- */
175
- export function extractKeysFromHandshakePayload(payload) {
176
- const decoded = decodeUnifiedPubKeys(payload.unifiedPubKeys);
177
- if (!decoded)
178
- return null;
179
- return {
180
- identityPubKey: decoded.identityPubKey,
181
- signingPubKey: decoded.signingPubKey,
182
- ephemeralPubKey: payload.ephemeralPubKey
183
109
  };
184
110
  }
185
111
  /**
@@ -0,0 +1,33 @@
1
+ export declare const kem: {
2
+ publicKeyBytes: number;
3
+ ciphertextBytes: number;
4
+ sharedSecretBytes: number;
5
+ /**
6
+ * Generate a new ML-KEM-768 keypair.
7
+ *
8
+ * @returns Object containing publicKey and secretKey
9
+ */
10
+ generateKeyPair(): {
11
+ publicKey: Uint8Array;
12
+ secretKey: Uint8Array;
13
+ };
14
+ /**
15
+ * Encapsulate a shared secret using the recipient's public key.
16
+ *
17
+ * @param publicKey - Recipient's ML-KEM-768 public key
18
+ * @returns Object containing ciphertext and sharedSecret
19
+ */
20
+ encapsulate(publicKey: Uint8Array): {
21
+ ciphertext: Uint8Array;
22
+ sharedSecret: Uint8Array;
23
+ };
24
+ /**
25
+ * Decapsulate a ciphertext using the secret key to recover the shared secret.
26
+ *
27
+ * @param ciphertext - KEM ciphertext
28
+ * @param secretKey - Recipient's ML-KEM-768 secret key
29
+ * @returns Shared secret
30
+ */
31
+ decapsulate(ciphertext: Uint8Array, secretKey: Uint8Array): Uint8Array;
32
+ };
33
+ //# sourceMappingURL=kem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kem.d.ts","sourceRoot":"","sources":["../../../src/pq/kem.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,GAAG;;;;IAKd;;;;OAIG;uBACgB;QAAE,SAAS,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,UAAU,CAAA;KAAE;IAInE;;;;;OAKG;2BACoB,UAAU,GAAG;QAAE,UAAU,EAAE,UAAU,CAAC;QAAC,YAAY,EAAE,UAAU,CAAA;KAAE;IAKxF;;;;;;OAMG;4BACqB,UAAU,aAAa,UAAU,GAAG,UAAU;CAGvE,CAAC"}
@@ -0,0 +1,40 @@
1
+ // packages/sdk/src/pq/kem.ts
2
+ /**
3
+ * ML-KEM-768 Key Encapsulation Mechanism wrapper.
4
+ *
5
+ * Provides post-quantum key encapsulation for hybrid handshakes.
6
+ */
7
+ import { ml_kem768 } from '@noble/post-quantum/ml-kem.js';
8
+ export const kem = {
9
+ publicKeyBytes: 1184, // in bytes
10
+ ciphertextBytes: 1088,
11
+ sharedSecretBytes: 32,
12
+ /**
13
+ * Generate a new ML-KEM-768 keypair.
14
+ *
15
+ * @returns Object containing publicKey and secretKey
16
+ */
17
+ generateKeyPair() {
18
+ return ml_kem768.keygen();
19
+ },
20
+ /**
21
+ * Encapsulate a shared secret using the recipient's public key.
22
+ *
23
+ * @param publicKey - Recipient's ML-KEM-768 public key
24
+ * @returns Object containing ciphertext and sharedSecret
25
+ */
26
+ encapsulate(publicKey) {
27
+ const result = ml_kem768.encapsulate(publicKey);
28
+ return { ciphertext: result.cipherText, sharedSecret: result.sharedSecret };
29
+ },
30
+ /**
31
+ * Decapsulate a ciphertext using the secret key to recover the shared secret.
32
+ *
33
+ * @param ciphertext - KEM ciphertext
34
+ * @param secretKey - Recipient's ML-KEM-768 secret key
35
+ * @returns Shared secret
36
+ */
37
+ decapsulate(ciphertext, secretKey) {
38
+ return ml_kem768.decapsulate(ciphertext, secretKey);
39
+ }
40
+ };
@@ -0,0 +1,34 @@
1
+ import { MessageHeader } from './types.js';
2
+ /**
3
+ * Verify message signature before any ratchet operations.
4
+ * This is the primary DoS protection layer.
5
+ *
6
+ * The signature covers (header || ciphertext), where header is the 40-byte
7
+ * binary encoding of (dh, pn, n).
8
+ *
9
+ * @param signature - Ed25519 signature (64 bytes)
10
+ * @param header - Message header
11
+ * @param ciphertext - Encrypted payload
12
+ * @param signingPublicKey - Contact's Ed25519 public key (32 bytes)
13
+ * @returns true if signature is valid
14
+ */
15
+ export declare function verifyMessageSignature(signature: Uint8Array, header: MessageHeader, ciphertext: Uint8Array, signingPublicKey: Uint8Array): boolean;
16
+ /**
17
+ * Create Ed25519 signature for a message.
18
+ *
19
+ * @param header - Message header
20
+ * @param ciphertext - Encrypted payload
21
+ * @param signingSecretKey - Ed25519 secret key (64 bytes)
22
+ * @returns Ed25519 signature (64 bytes)
23
+ */
24
+ export declare function signMessage(header: MessageHeader, ciphertext: Uint8Array, signingSecretKey: Uint8Array): Uint8Array;
25
+ /**
26
+ * Validate that a parsed payload has a well-formed signature and header.
27
+ * Does NOT verify the signature - just checks lengths and format.
28
+ *
29
+ * @param signature - Signature bytes
30
+ * @param header - Parsed header
31
+ * @returns true if format is valid
32
+ */
33
+ export declare function isValidPayloadFormat(signature: Uint8Array, header: MessageHeader): boolean;
34
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/ratchet/auth.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAM3C;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,UAAU,EACrB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,UAAU,EACtB,gBAAgB,EAAE,UAAU,GAC3B,OAAO,CAmBT;AAkBD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,UAAU,EACtB,gBAAgB,EAAE,UAAU,GAC3B,UAAU,CAOZ;AAMD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,UAAU,EACrB,MAAM,EAAE,aAAa,GACpB,OAAO,CAST"}
@@ -0,0 +1,88 @@
1
+ // packages/sdk/src/ratchet/auth.ts
2
+ /**
3
+ * Message Authentication for Ratchet Protocol.
4
+ */
5
+ import nacl from 'tweetnacl';
6
+ // =============================================================================
7
+ // Signature Verification
8
+ // =============================================================================
9
+ /**
10
+ * Verify message signature before any ratchet operations.
11
+ * This is the primary DoS protection layer.
12
+ *
13
+ * The signature covers (header || ciphertext), where header is the 40-byte
14
+ * binary encoding of (dh, pn, n).
15
+ *
16
+ * @param signature - Ed25519 signature (64 bytes)
17
+ * @param header - Message header
18
+ * @param ciphertext - Encrypted payload
19
+ * @param signingPublicKey - Contact's Ed25519 public key (32 bytes)
20
+ * @returns true if signature is valid
21
+ */
22
+ export function verifyMessageSignature(signature, header, ciphertext, signingPublicKey) {
23
+ if (signature.length !== 64) {
24
+ return false;
25
+ }
26
+ if (signingPublicKey.length !== 32) {
27
+ return false;
28
+ }
29
+ // Reconstruct signed data: header || ciphertext
30
+ const headerBytes = encodeHeaderForSigning(header);
31
+ const dataToVerify = new Uint8Array(headerBytes.length + ciphertext.length);
32
+ dataToVerify.set(headerBytes, 0);
33
+ dataToVerify.set(ciphertext, headerBytes.length);
34
+ try {
35
+ return nacl.sign.detached.verify(dataToVerify, signature, signingPublicKey);
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ }
41
+ /**
42
+ * Encode header as 40 bytes for signature verification.
43
+ * Format: dh (32) + pn (4, BE) + n (4, BE)
44
+ */
45
+ function encodeHeaderForSigning(header) {
46
+ const buf = new Uint8Array(40);
47
+ buf.set(header.dh, 0);
48
+ new DataView(buf.buffer).setUint32(32, header.pn, false); // big-endian
49
+ new DataView(buf.buffer).setUint32(36, header.n, false);
50
+ return buf;
51
+ }
52
+ // =============================================================================
53
+ // Signature Creation
54
+ // =============================================================================
55
+ /**
56
+ * Create Ed25519 signature for a message.
57
+ *
58
+ * @param header - Message header
59
+ * @param ciphertext - Encrypted payload
60
+ * @param signingSecretKey - Ed25519 secret key (64 bytes)
61
+ * @returns Ed25519 signature (64 bytes)
62
+ */
63
+ export function signMessage(header, ciphertext, signingSecretKey) {
64
+ const headerBytes = encodeHeaderForSigning(header);
65
+ const dataToSign = new Uint8Array(headerBytes.length + ciphertext.length);
66
+ dataToSign.set(headerBytes, 0);
67
+ dataToSign.set(ciphertext, headerBytes.length);
68
+ return nacl.sign.detached(dataToSign, signingSecretKey);
69
+ }
70
+ // =============================================================================
71
+ // Validation Helpers
72
+ // =============================================================================
73
+ /**
74
+ * Validate that a parsed payload has a well-formed signature and header.
75
+ * Does NOT verify the signature - just checks lengths and format.
76
+ *
77
+ * @param signature - Signature bytes
78
+ * @param header - Parsed header
79
+ * @returns true if format is valid
80
+ */
81
+ export function isValidPayloadFormat(signature, header) {
82
+ return (signature.length === 64 &&
83
+ header.dh.length === 32 &&
84
+ header.pn >= 0 &&
85
+ header.n >= 0 &&
86
+ Number.isInteger(header.pn) &&
87
+ Number.isInteger(header.n));
88
+ }