shogun-core 6.2.4 → 6.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/dist/browser/defaultVendors-node_modules_noble_curves_esm_ed448_js.shogun-core.js +93 -341
  2. package/dist/browser/defaultVendors-node_modules_noble_curves_esm_ed448_js.shogun-core.js.map +1 -1
  3. package/dist/browser/shogun-core.js +138979 -146789
  4. package/dist/browser/shogun-core.js.map +1 -1
  5. package/dist/{core.js → src/core.js} +167 -107
  6. package/dist/src/crypto/asymmetric.js +168 -0
  7. package/dist/src/crypto/double-ratchet.js +908 -0
  8. package/dist/src/crypto/file-encryption.js +352 -0
  9. package/dist/src/crypto/hashing.js +160 -0
  10. package/dist/src/crypto/index.js +18 -0
  11. package/dist/{crypto → src/crypto}/mls-codec.js +24 -34
  12. package/dist/src/crypto/mls.js +734 -0
  13. package/dist/src/crypto/pgp.js +619 -0
  14. package/dist/{crypto → src/crypto}/random-generation.js +125 -103
  15. package/dist/src/crypto/sframe.js +466 -0
  16. package/dist/src/crypto/signal-protocol.js +943 -0
  17. package/dist/src/crypto/symmetric.js +165 -0
  18. package/dist/src/crypto/utils.js +220 -0
  19. package/dist/src/examples/auth-test.js +535 -0
  20. package/dist/src/examples/crypto-identity-example.js +294 -0
  21. package/dist/src/examples/crypto-working-test.js +149 -0
  22. package/dist/src/examples/double-ratchet-test.js +240 -0
  23. package/dist/src/examples/mls-3-member-test.js +183 -0
  24. package/dist/src/examples/mls-multi-member.js +439 -0
  25. package/dist/src/examples/mls-sframe-test.js +491 -0
  26. package/dist/src/examples/mls-simple-test.js +122 -0
  27. package/dist/src/examples/pgp-example.js +354 -0
  28. package/dist/src/examples/random-generation-test.js +191 -0
  29. package/dist/src/examples/shogun-core-example.js +204 -0
  30. package/dist/src/examples/signal-protocol-test.js +82 -0
  31. package/dist/src/examples/zkproof-credentials-example.js +357 -0
  32. package/dist/src/examples/zkproof-example.js +357 -0
  33. package/dist/src/gundb/crypto.js +420 -0
  34. package/dist/src/gundb/db.js +728 -0
  35. package/dist/src/gundb/derive.js +327 -0
  36. package/dist/src/gundb/errors.js +115 -0
  37. package/dist/src/gundb/gun-es.js +8 -0
  38. package/dist/src/gundb/index.js +5 -0
  39. package/dist/{gundb → src/gundb}/rxjs.js +147 -111
  40. package/dist/{gundb → src/gundb}/types.js +1 -2
  41. package/dist/src/index.js +19 -0
  42. package/dist/src/interfaces/events.js +57 -0
  43. package/dist/{interfaces → src/interfaces}/shogun.js +4 -7
  44. package/dist/src/managers/AuthManager.js +301 -0
  45. package/dist/src/managers/CoreInitializer.js +304 -0
  46. package/dist/src/managers/CryptoIdentityManager.js +230 -0
  47. package/dist/{managers → src/managers}/EventManager.js +19 -21
  48. package/dist/{managers → src/managers}/PluginManager.js +123 -89
  49. package/dist/src/plugins/base.js +90 -0
  50. package/dist/src/plugins/index.js +17 -0
  51. package/dist/src/plugins/nostr/index.js +4 -0
  52. package/dist/src/plugins/nostr/nostrConnector.js +539 -0
  53. package/dist/src/plugins/nostr/nostrConnectorPlugin.js +663 -0
  54. package/dist/src/plugins/nostr/nostrSigner.js +414 -0
  55. package/dist/src/plugins/smartwallet/index.js +2 -0
  56. package/dist/src/plugins/smartwallet/smartWalletPlugin.js +824 -0
  57. package/dist/src/plugins/web3/index.js +4 -0
  58. package/dist/src/plugins/web3/types.js +1 -0
  59. package/dist/src/plugins/web3/web3Connector.js +738 -0
  60. package/dist/src/plugins/web3/web3ConnectorPlugin.js +639 -0
  61. package/dist/src/plugins/web3/web3Signer.js +432 -0
  62. package/dist/src/plugins/webauthn/index.js +3 -0
  63. package/dist/{plugins → src/plugins}/webauthn/types.js +2 -5
  64. package/dist/src/plugins/webauthn/webauthn.js +647 -0
  65. package/dist/src/plugins/webauthn/webauthnPlugin.js +689 -0
  66. package/dist/src/plugins/webauthn/webauthnSigner.js +419 -0
  67. package/dist/{plugins → src/plugins}/zkproof/index.js +3 -10
  68. package/dist/src/plugins/zkproof/types.js +1 -0
  69. package/dist/src/plugins/zkproof/zkCredentials.js +287 -0
  70. package/dist/src/plugins/zkproof/zkProofConnector.js +267 -0
  71. package/dist/src/plugins/zkproof/zkProofPlugin.js +405 -0
  72. package/dist/src/storage/storage.js +189 -0
  73. package/dist/src/utils/errorHandler.js +339 -0
  74. package/dist/{utils → src/utils}/eventEmitter.js +26 -26
  75. package/dist/{utils → src/utils}/seedPhrase.js +23 -32
  76. package/dist/{utils → src/utils}/validation.js +14 -21
  77. package/dist/tsconfig.tsbuildinfo +1 -0
  78. package/dist/types/{crypto → src/crypto}/double-ratchet.d.ts +1 -1
  79. package/dist/types/{crypto → src/crypto}/signal-protocol.d.ts +25 -0
  80. package/dist/types/{crypto → src/crypto}/types.d.ts +3 -1
  81. package/dist/types/src/examples/crypto-working-test.d.ts +1 -0
  82. package/dist/types/src/examples/double-ratchet-test.d.ts +1 -0
  83. package/dist/types/src/examples/mls-sframe-test.d.ts +1 -0
  84. package/dist/types/src/examples/random-generation-test.d.ts +1 -0
  85. package/dist/types/src/examples/signal-protocol-test.d.ts +1 -0
  86. package/dist/types/{gundb → src/gundb}/db.d.ts +14 -1
  87. package/dist/types/src/gundb/gun-es.d.ts +8 -0
  88. package/dist/types/src/gundb/min.d.ts +3 -0
  89. package/dist/types/{index.d.ts → src/index.d.ts} +1 -0
  90. package/package.json +14 -11
  91. package/dist/browser/defaultVendors-node_modules_noble_curves_esm_abstract_curve_js-node_modules_noble_curves_esm_-1ce4ed.shogun-core.js +0 -1651
  92. package/dist/browser/defaultVendors-node_modules_noble_curves_esm_abstract_curve_js-node_modules_noble_curves_esm_-1ce4ed.shogun-core.js.map +0 -1
  93. package/dist/browser/defaultVendors-node_modules_noble_curves_esm_nist_js.shogun-core.js +0 -1608
  94. package/dist/browser/defaultVendors-node_modules_noble_curves_esm_nist_js.shogun-core.js.map +0 -1
  95. package/dist/crypto/asymmetric.js +0 -99
  96. package/dist/crypto/double-ratchet.js +0 -392
  97. package/dist/crypto/file-encryption.js +0 -213
  98. package/dist/crypto/hashing.js +0 -87
  99. package/dist/crypto/index.js +0 -34
  100. package/dist/crypto/mls.js +0 -569
  101. package/dist/crypto/pgp.js +0 -390
  102. package/dist/crypto/sframe.js +0 -352
  103. package/dist/crypto/signal-protocol.js +0 -456
  104. package/dist/crypto/symmetric.js +0 -91
  105. package/dist/crypto/types.js +0 -2
  106. package/dist/crypto/utils.js +0 -140
  107. package/dist/examples/auth-test.js +0 -453
  108. package/dist/examples/crypto-identity-example.js +0 -196
  109. package/dist/examples/crypto-working-test.js +0 -83
  110. package/dist/examples/double-ratchet-test.js +0 -155
  111. package/dist/examples/mls-3-member-test.js +0 -97
  112. package/dist/examples/mls-multi-member.js +0 -153
  113. package/dist/examples/mls-sframe-test.js +0 -307
  114. package/dist/examples/mls-simple-test.js +0 -58
  115. package/dist/examples/pgp-example.js +0 -200
  116. package/dist/examples/random-generation-test.js +0 -151
  117. package/dist/examples/shogun-core-example.js +0 -150
  118. package/dist/examples/signal-protocol-test.js +0 -38
  119. package/dist/examples/zkproof-credentials-example.js +0 -217
  120. package/dist/examples/zkproof-example.js +0 -242
  121. package/dist/gundb/crypto.js +0 -306
  122. package/dist/gundb/db.js +0 -485
  123. package/dist/gundb/derive.js +0 -232
  124. package/dist/gundb/errors.js +0 -76
  125. package/dist/gundb/gun-es.js +0 -12
  126. package/dist/gundb/index.js +0 -21
  127. package/dist/gundb/min.js +0 -10
  128. package/dist/index.esm.js +0 -22
  129. package/dist/index.js +0 -47
  130. package/dist/interfaces/common.js +0 -2
  131. package/dist/interfaces/events.js +0 -40
  132. package/dist/interfaces/plugin.js +0 -2
  133. package/dist/managers/AuthManager.js +0 -226
  134. package/dist/managers/CoreInitializer.js +0 -250
  135. package/dist/managers/CryptoIdentityManager.js +0 -138
  136. package/dist/plugins/base.js +0 -50
  137. package/dist/plugins/index.js +0 -32
  138. package/dist/plugins/nostr/index.js +0 -20
  139. package/dist/plugins/nostr/nostrConnector.js +0 -419
  140. package/dist/plugins/nostr/nostrConnectorPlugin.js +0 -453
  141. package/dist/plugins/nostr/nostrSigner.js +0 -319
  142. package/dist/plugins/nostr/types.js +0 -2
  143. package/dist/plugins/smartwallet/index.js +0 -18
  144. package/dist/plugins/smartwallet/smartWalletPlugin.js +0 -511
  145. package/dist/plugins/smartwallet/types.js +0 -2
  146. package/dist/plugins/web3/index.js +0 -20
  147. package/dist/plugins/web3/types.js +0 -2
  148. package/dist/plugins/web3/web3Connector.js +0 -533
  149. package/dist/plugins/web3/web3ConnectorPlugin.js +0 -455
  150. package/dist/plugins/web3/web3Signer.js +0 -314
  151. package/dist/plugins/webauthn/index.js +0 -19
  152. package/dist/plugins/webauthn/webauthn.js +0 -496
  153. package/dist/plugins/webauthn/webauthnPlugin.js +0 -490
  154. package/dist/plugins/webauthn/webauthnSigner.js +0 -310
  155. package/dist/plugins/zkproof/types.js +0 -2
  156. package/dist/plugins/zkproof/zkCredentials.js +0 -216
  157. package/dist/plugins/zkproof/zkProofConnector.js +0 -198
  158. package/dist/plugins/zkproof/zkProofPlugin.js +0 -272
  159. package/dist/storage/storage.js +0 -145
  160. package/dist/types/gundb/gun-es.d.ts +0 -8
  161. package/dist/utils/errorHandler.js +0 -246
  162. /package/dist/{types/examples/crypto-working-test.d.ts → src/crypto/types.js} +0 -0
  163. /package/dist/{types/gundb/min.d.ts → src/gundb/min.js} +0 -0
  164. /package/dist/{types/examples/double-ratchet-test.d.ts → src/interfaces/common.js} +0 -0
  165. /package/dist/{types/examples/mls-sframe-test.d.ts → src/interfaces/plugin.js} +0 -0
  166. /package/dist/{types/examples/random-generation-test.d.ts → src/plugins/nostr/types.js} +0 -0
  167. /package/dist/{types/examples/signal-protocol-test.d.ts → src/plugins/smartwallet/types.js} +0 -0
  168. /package/dist/types/{core.d.ts → src/core.d.ts} +0 -0
  169. /package/dist/types/{crypto → src/crypto}/asymmetric.d.ts +0 -0
  170. /package/dist/types/{crypto → src/crypto}/file-encryption.d.ts +0 -0
  171. /package/dist/types/{crypto → src/crypto}/hashing.d.ts +0 -0
  172. /package/dist/types/{crypto → src/crypto}/index.d.ts +0 -0
  173. /package/dist/types/{crypto → src/crypto}/mls-codec.d.ts +0 -0
  174. /package/dist/types/{crypto → src/crypto}/mls.d.ts +0 -0
  175. /package/dist/types/{crypto → src/crypto}/pgp.d.ts +0 -0
  176. /package/dist/types/{crypto → src/crypto}/random-generation.d.ts +0 -0
  177. /package/dist/types/{crypto → src/crypto}/sframe.d.ts +0 -0
  178. /package/dist/types/{crypto → src/crypto}/symmetric.d.ts +0 -0
  179. /package/dist/types/{crypto → src/crypto}/utils.d.ts +0 -0
  180. /package/dist/types/{examples → src/examples}/auth-test.d.ts +0 -0
  181. /package/dist/types/{examples → src/examples}/crypto-identity-example.d.ts +0 -0
  182. /package/dist/types/{examples → src/examples}/mls-3-member-test.d.ts +0 -0
  183. /package/dist/types/{examples → src/examples}/mls-multi-member.d.ts +0 -0
  184. /package/dist/types/{examples → src/examples}/mls-simple-test.d.ts +0 -0
  185. /package/dist/types/{examples → src/examples}/pgp-example.d.ts +0 -0
  186. /package/dist/types/{examples → src/examples}/shogun-core-example.d.ts +0 -0
  187. /package/dist/types/{examples → src/examples}/zkproof-credentials-example.d.ts +0 -0
  188. /package/dist/types/{examples → src/examples}/zkproof-example.d.ts +0 -0
  189. /package/dist/types/{gundb → src/gundb}/crypto.d.ts +0 -0
  190. /package/dist/types/{gundb → src/gundb}/derive.d.ts +0 -0
  191. /package/dist/types/{gundb → src/gundb}/errors.d.ts +0 -0
  192. /package/dist/types/{gundb → src/gundb}/index.d.ts +0 -0
  193. /package/dist/types/{gundb → src/gundb}/rxjs.d.ts +0 -0
  194. /package/dist/types/{gundb → src/gundb}/types.d.ts +0 -0
  195. /package/dist/types/{interfaces → src/interfaces}/common.d.ts +0 -0
  196. /package/dist/types/{interfaces → src/interfaces}/events.d.ts +0 -0
  197. /package/dist/types/{interfaces → src/interfaces}/plugin.d.ts +0 -0
  198. /package/dist/types/{interfaces → src/interfaces}/shogun.d.ts +0 -0
  199. /package/dist/types/{managers → src/managers}/AuthManager.d.ts +0 -0
  200. /package/dist/types/{managers → src/managers}/CoreInitializer.d.ts +0 -0
  201. /package/dist/types/{managers → src/managers}/CryptoIdentityManager.d.ts +0 -0
  202. /package/dist/types/{managers → src/managers}/EventManager.d.ts +0 -0
  203. /package/dist/types/{managers → src/managers}/PluginManager.d.ts +0 -0
  204. /package/dist/types/{plugins → src/plugins}/base.d.ts +0 -0
  205. /package/dist/types/{plugins → src/plugins}/index.d.ts +0 -0
  206. /package/dist/types/{plugins → src/plugins}/nostr/index.d.ts +0 -0
  207. /package/dist/types/{plugins → src/plugins}/nostr/nostrConnector.d.ts +0 -0
  208. /package/dist/types/{plugins → src/plugins}/nostr/nostrConnectorPlugin.d.ts +0 -0
  209. /package/dist/types/{plugins → src/plugins}/nostr/nostrSigner.d.ts +0 -0
  210. /package/dist/types/{plugins → src/plugins}/nostr/types.d.ts +0 -0
  211. /package/dist/types/{plugins → src/plugins}/smartwallet/index.d.ts +0 -0
  212. /package/dist/types/{plugins → src/plugins}/smartwallet/smartWalletPlugin.d.ts +0 -0
  213. /package/dist/types/{plugins → src/plugins}/smartwallet/types.d.ts +0 -0
  214. /package/dist/types/{plugins → src/plugins}/web3/index.d.ts +0 -0
  215. /package/dist/types/{plugins → src/plugins}/web3/types.d.ts +0 -0
  216. /package/dist/types/{plugins → src/plugins}/web3/web3Connector.d.ts +0 -0
  217. /package/dist/types/{plugins → src/plugins}/web3/web3ConnectorPlugin.d.ts +0 -0
  218. /package/dist/types/{plugins → src/plugins}/web3/web3Signer.d.ts +0 -0
  219. /package/dist/types/{plugins → src/plugins}/webauthn/index.d.ts +0 -0
  220. /package/dist/types/{plugins → src/plugins}/webauthn/types.d.ts +0 -0
  221. /package/dist/types/{plugins → src/plugins}/webauthn/webauthn.d.ts +0 -0
  222. /package/dist/types/{plugins → src/plugins}/webauthn/webauthnPlugin.d.ts +0 -0
  223. /package/dist/types/{plugins → src/plugins}/webauthn/webauthnSigner.d.ts +0 -0
  224. /package/dist/types/{plugins → src/plugins}/zkproof/index.d.ts +0 -0
  225. /package/dist/types/{plugins → src/plugins}/zkproof/types.d.ts +0 -0
  226. /package/dist/types/{plugins → src/plugins}/zkproof/zkCredentials.d.ts +0 -0
  227. /package/dist/types/{plugins → src/plugins}/zkproof/zkProofConnector.d.ts +0 -0
  228. /package/dist/types/{plugins → src/plugins}/zkproof/zkProofPlugin.d.ts +0 -0
  229. /package/dist/types/{storage → src/storage}/storage.d.ts +0 -0
  230. /package/dist/types/{utils → src/utils}/errorHandler.d.ts +0 -0
  231. /package/dist/types/{utils → src/utils}/eventEmitter.d.ts +0 -0
  232. /package/dist/types/{utils → src/utils}/seedPhrase.d.ts +0 -0
  233. /package/dist/types/{utils → src/utils}/validation.d.ts +0 -0
@@ -0,0 +1,908 @@
1
+ // Double Ratchet Protocol Implementation for shogun-core
2
+ // Based on the Signal Protocol specification for ongoing secure messaging
3
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5
+ return new (P || (P = Promise))(function (resolve, reject) {
6
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
7
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
8
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
9
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
10
+ });
11
+ };
12
+ var __generator = (this && this.__generator) || function (thisArg, body) {
13
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
14
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
15
+ function verb(n) { return function (v) { return step([n, v]); }; }
16
+ function step(op) {
17
+ if (f) throw new TypeError("Generator is already executing.");
18
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
19
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
20
+ if (y = 0, t) op = [op[0] & 2, t.value];
21
+ switch (op[0]) {
22
+ case 0: case 1: t = op; break;
23
+ case 4: _.label++; return { value: op[1], done: false };
24
+ case 5: _.label++; y = op[1]; op = [0]; continue;
25
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
26
+ default:
27
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
28
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
29
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
30
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
31
+ if (t[2]) _.ops.pop();
32
+ _.trys.pop(); continue;
33
+ }
34
+ op = body.call(thisArg, _);
35
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
36
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
37
+ }
38
+ };
39
+ var __read = (this && this.__read) || function (o, n) {
40
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
41
+ if (!m) return o;
42
+ var i = m.call(o), r, ar = [], e;
43
+ try {
44
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
45
+ }
46
+ catch (error) { e = { error: error }; }
47
+ finally {
48
+ try {
49
+ if (r && !r.done && (m = i["return"])) m.call(i);
50
+ }
51
+ finally { if (e) throw e.error; }
52
+ }
53
+ return ar;
54
+ };
55
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
56
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
57
+ if (ar || !(i in from)) {
58
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
59
+ ar[i] = from[i];
60
+ }
61
+ }
62
+ return to.concat(ar || Array.prototype.slice.call(from));
63
+ };
64
+ import { generateSignalKeyPair, exportSignalPublicKey, importSignalPublicKey, performSignalDH, bufferToSignalHex, } from "./signal-protocol.js";
65
+ // Double Ratchet Protocol Constants
66
+ var DOUBLE_RATCHET_INFO_MESSAGE_KEY = new TextEncoder().encode("DoubleRatchet_MessageKey");
67
+ var DOUBLE_RATCHET_INFO_CHAIN_KEY = new TextEncoder().encode("DoubleRatchet_ChainKey");
68
+ var DOUBLE_RATCHET_INFO_ROOT_KEY = new TextEncoder().encode("DoubleRatchet_RootKey");
69
+ var DOUBLE_RATCHET_CHAIN_KEY_CONSTANT = new Uint8Array(1).fill(0x02);
70
+ var DOUBLE_RATCHET_MESSAGE_KEY_CONSTANT = new Uint8Array(1).fill(0x01);
71
+ var MAX_SKIPPED_MESSAGE_KEYS = 1000;
72
+ // HKDF implementation for Double Ratchet
73
+ var doubleRatchetHKDF = function (salt_1, inputKeyMaterial_1, info_1) {
74
+ var args_1 = [];
75
+ for (var _i = 3; _i < arguments.length; _i++) {
76
+ args_1[_i - 3] = arguments[_i];
77
+ }
78
+ return __awaiter(void 0, __spreadArray([salt_1, inputKeyMaterial_1, info_1], __read(args_1), false), void 0, function (salt, inputKeyMaterial, info, length) {
79
+ var saltKey, prk, prkKey, okm, t, counter, pos, input, _a, remaining, copyLength;
80
+ if (length === void 0) { length = 32; }
81
+ return __generator(this, function (_b) {
82
+ switch (_b.label) {
83
+ case 0: return [4 /*yield*/, crypto.subtle.importKey("raw", salt.length > 0 ? salt.buffer : new ArrayBuffer(32), { name: "HMAC", hash: "SHA-256" }, false, ["sign"])];
84
+ case 1:
85
+ saltKey = _b.sent();
86
+ return [4 /*yield*/, crypto.subtle.sign("HMAC", saltKey, inputKeyMaterial)];
87
+ case 2:
88
+ prk = _b.sent();
89
+ return [4 /*yield*/, crypto.subtle.importKey("raw", prk, { name: "HMAC", hash: "SHA-256" }, false, ["sign"])];
90
+ case 3:
91
+ prkKey = _b.sent();
92
+ okm = new Uint8Array(length);
93
+ t = new Uint8Array(0);
94
+ counter = 1;
95
+ pos = 0;
96
+ _b.label = 4;
97
+ case 4:
98
+ if (!(pos < length)) return [3 /*break*/, 6];
99
+ input = new Uint8Array(t.length + info.length + 1);
100
+ input.set(t);
101
+ input.set(info, t.length);
102
+ input[t.length + info.length] = counter;
103
+ _a = Uint8Array.bind;
104
+ return [4 /*yield*/, crypto.subtle.sign("HMAC", prkKey, input)];
105
+ case 5:
106
+ t = new (_a.apply(Uint8Array, [void 0, _b.sent()]))();
107
+ remaining = length - pos;
108
+ copyLength = Math.min(t.length, remaining);
109
+ okm.set(t.subarray(0, copyLength), pos);
110
+ pos += copyLength;
111
+ counter++;
112
+ return [3 /*break*/, 4];
113
+ case 6: return [2 /*return*/, okm.buffer];
114
+ }
115
+ });
116
+ });
117
+ };
118
+ // HMAC-SHA256 for chain key updates
119
+ var doubleRatchetHMAC = function (key, data) { return __awaiter(void 0, void 0, void 0, function () {
120
+ var hmacKey;
121
+ return __generator(this, function (_a) {
122
+ switch (_a.label) {
123
+ case 0: return [4 /*yield*/, crypto.subtle.importKey("raw", key, { name: "HMAC", hash: "SHA-256" }, false, ["sign"])];
124
+ case 1:
125
+ hmacKey = _a.sent();
126
+ return [4 /*yield*/, crypto.subtle.sign("HMAC", hmacKey, data.buffer)];
127
+ case 2: return [2 /*return*/, _a.sent()];
128
+ }
129
+ });
130
+ }); };
131
+ // Initialize Double Ratchet state from X3DH shared secret
132
+ export var initializeDoubleRatchet = function (sharedSecret_1, isInitiator_1) {
133
+ var args_1 = [];
134
+ for (var _i = 2; _i < arguments.length; _i++) {
135
+ args_1[_i - 2] = arguments[_i];
136
+ }
137
+ return __awaiter(void 0, __spreadArray([sharedSecret_1, isInitiator_1], __read(args_1), false), void 0, function (sharedSecret, isInitiator, remotePublicKey, x3dhEphemeralPublic) {
138
+ var initialRootKey, rootKeyHex, state, _a, initialRootKeyHexBeforeDerivation, hkdfOutput, newRootKey, sendingChainKey, newRootKeyHex, sendingChainKeyHex;
139
+ if (remotePublicKey === void 0) { remotePublicKey = null; }
140
+ return __generator(this, function (_b) {
141
+ switch (_b.label) {
142
+ case 0:
143
+ console.log("\uD83D\uDD04 Initializing Double Ratchet (".concat(isInitiator ? "Initiator" : "Responder", ")"));
144
+ return [4 /*yield*/, doubleRatchetHKDF(new Uint8Array(0), // Empty salt
145
+ sharedSecret, DOUBLE_RATCHET_INFO_ROOT_KEY, 32)];
146
+ case 1:
147
+ initialRootKey = _b.sent();
148
+ rootKeyHex = bufferToSignalHex(initialRootKey);
149
+ console.log("✓ Initial root key derived from X3DH secret", {
150
+ role: isInitiator ? "Initiator" : "Responder",
151
+ rootKeyHex: rootKeyHex.substring(0, 16) + "...",
152
+ rootKeyLength: initialRootKey.byteLength,
153
+ });
154
+ state = {
155
+ // Core ratchet state
156
+ rootKey: initialRootKey,
157
+ sendingChainKey: null,
158
+ receivingChainKey: null,
159
+ // DH key pairs
160
+ sendingDHKeyPair: null,
161
+ receivingDHPublicKey: remotePublicKey,
162
+ // Message counters
163
+ sendingMessageNumber: 0,
164
+ receivingMessageNumber: 0,
165
+ previousChainLength: 0,
166
+ // Skipped message keys storage
167
+ skippedMessageKeys: new Map(),
168
+ // State flags
169
+ isInitiator: isInitiator,
170
+ initialized: Date.now(),
171
+ // X3DH ephemeral (only for initiator)
172
+ x3dhEphemeralPublic: x3dhEphemeralPublic,
173
+ };
174
+ if (!isInitiator) return [3 /*break*/, 4];
175
+ // Initiator: Generate initial DH key pair and derive sending chain directly from root key
176
+ console.log("🔑 Generating initial DH key pair for initiator");
177
+ _a = state;
178
+ return [4 /*yield*/, generateSignalKeyPair()];
179
+ case 2:
180
+ _a.sendingDHKeyPair = _b.sent();
181
+ initialRootKeyHexBeforeDerivation = bufferToSignalHex(initialRootKey);
182
+ console.log("🔍 Initiator - root key before sending chain derivation:", {
183
+ rootKeyHex: initialRootKeyHexBeforeDerivation.substring(0, 16) + "...",
184
+ rootKeyLength: initialRootKey.byteLength,
185
+ });
186
+ return [4 /*yield*/, doubleRatchetHKDF(new Uint8Array(0), // Empty salt for direct derivation
187
+ initialRootKey, DOUBLE_RATCHET_INFO_CHAIN_KEY, 64)];
188
+ case 3:
189
+ hkdfOutput = _b.sent();
190
+ newRootKey = hkdfOutput.slice(0, 32);
191
+ sendingChainKey = hkdfOutput.slice(32, 64);
192
+ newRootKeyHex = bufferToSignalHex(newRootKey);
193
+ sendingChainKeyHex = bufferToSignalHex(sendingChainKey);
194
+ state.rootKey = newRootKey;
195
+ state.sendingChainKey = sendingChainKey;
196
+ console.log("✓ Initial sending chain derived directly from root key", {
197
+ oldRootKeyHex: initialRootKeyHexBeforeDerivation.substring(0, 16) + "...",
198
+ newRootKeyHex: newRootKeyHex.substring(0, 16) + "...",
199
+ sendingChainKeyHex: sendingChainKeyHex.substring(0, 16) + "...",
200
+ sendingChainKeyLength: sendingChainKey.byteLength,
201
+ });
202
+ return [3 /*break*/, 5];
203
+ case 4:
204
+ // Responder: Start with receiving mode, will derive receiving chain from root key on first message
205
+ console.log("📥 Responder initialized, waiting for first message");
206
+ _b.label = 5;
207
+ case 5:
208
+ console.log("✅ Double Ratchet state initialized successfully");
209
+ return [2 /*return*/, state];
210
+ }
211
+ });
212
+ });
213
+ };
214
+ // Derive message key from chain key
215
+ var deriveMessageKey = function (chainKey) { return __awaiter(void 0, void 0, void 0, function () {
216
+ var messageKey;
217
+ return __generator(this, function (_a) {
218
+ switch (_a.label) {
219
+ case 0: return [4 /*yield*/, doubleRatchetHMAC(chainKey, DOUBLE_RATCHET_MESSAGE_KEY_CONSTANT)];
220
+ case 1:
221
+ messageKey = _a.sent();
222
+ return [2 /*return*/, new Uint8Array(messageKey)];
223
+ }
224
+ });
225
+ }); };
226
+ // Derive next chain key from current chain key
227
+ var deriveNextChainKey = function (chainKey) { return __awaiter(void 0, void 0, void 0, function () {
228
+ var nextChainKey;
229
+ return __generator(this, function (_a) {
230
+ switch (_a.label) {
231
+ case 0: return [4 /*yield*/, doubleRatchetHMAC(chainKey, DOUBLE_RATCHET_CHAIN_KEY_CONSTANT)];
232
+ case 1:
233
+ nextChainKey = _a.sent();
234
+ return [2 /*return*/, nextChainKey];
235
+ }
236
+ });
237
+ }); };
238
+ // Perform DH ratchet step (when receiving new DH public key)
239
+ var performDHRatchetStep = function (state, newRemotePublicKey) { return __awaiter(void 0, void 0, void 0, function () {
240
+ var wasReceivingMessageNumber, wasPreviousChainLength, isResponderFirstReceive, initialRootKeyHex, hkdfResult, newRootKey, receivingChainKey, newRootKeyHex, receivingChainKeyHex, _a, _b, ourPublicKeyHex, _c, theirPublicKeyHex, _d, currentReceivingDHPublicKeyHex, _e, _f, receivingDHOutput, rootKeyBeforeReceivingDerivation, rootKeyBeforeReceivingHex, hkdfReceiving, oldRootKeyHex, newRootKeyHex, receivingChainKeyHex, _g, rootKeyBeforeSendingDerivation, rootKeyBeforeSendingHex, sendingDHOutput, hkdfSending, rootKeyAfterHex, sendingChainKeyHex;
241
+ return __generator(this, function (_h) {
242
+ switch (_h.label) {
243
+ case 0:
244
+ console.log("🔄 Performing DH ratchet step");
245
+ wasReceivingMessageNumber = state.receivingMessageNumber;
246
+ wasPreviousChainLength = state.previousChainLength;
247
+ isResponderFirstReceive = !state.isInitiator &&
248
+ !state.receivingChainKey &&
249
+ wasReceivingMessageNumber === 0 &&
250
+ wasPreviousChainLength === 0;
251
+ // Update state for ratchet step (after check)
252
+ state.previousChainLength = state.receivingMessageNumber;
253
+ state.receivingDHPublicKey = newRemotePublicKey;
254
+ // Note: receivingMessageNumber is reset to 0 AFTER the isResponderFirstReceive check
255
+ // because we need to check wasReceivingMessageNumber === 0
256
+ console.log("🔍 Checking isResponderFirstReceive:", {
257
+ isResponder: !state.isInitiator,
258
+ hasReceivingChainKey: !!state.receivingChainKey,
259
+ wasReceivingMessageNumber: wasReceivingMessageNumber,
260
+ wasPreviousChainLength: wasPreviousChainLength,
261
+ isResponderFirstReceive: isResponderFirstReceive,
262
+ hasSendingDHKeyPair: !!state.sendingDHKeyPair,
263
+ conditionBreakdown: {
264
+ notInitiator: !state.isInitiator,
265
+ noReceivingChainKey: !state.receivingChainKey,
266
+ receivingMessageNumberIsZero: wasReceivingMessageNumber === 0,
267
+ previousChainLengthIsZero: wasPreviousChainLength === 0,
268
+ allConditionsMet: !state.isInitiator &&
269
+ !state.receivingChainKey &&
270
+ wasReceivingMessageNumber === 0 &&
271
+ wasPreviousChainLength === 0,
272
+ },
273
+ });
274
+ if (!isResponderFirstReceive) return [3 /*break*/, 3];
275
+ console.log("🔄 First receive: matching initiator's direct root key derivation (responder only)");
276
+ initialRootKeyHex = bufferToSignalHex(state.rootKey);
277
+ console.log("🔍 Responder first receive - root key before derivation:", {
278
+ rootKeyHex: initialRootKeyHex.substring(0, 16) + "...",
279
+ rootKeyLength: state.rootKey.byteLength,
280
+ });
281
+ return [4 /*yield*/, doubleRatchetHKDF(new Uint8Array(0), // Empty salt - same as initiator used
282
+ state.rootKey, // Same root key as initiator had
283
+ DOUBLE_RATCHET_INFO_CHAIN_KEY, 64)];
284
+ case 1:
285
+ hkdfResult = _h.sent();
286
+ newRootKey = hkdfResult.slice(0, 32);
287
+ receivingChainKey = hkdfResult.slice(32, 64);
288
+ newRootKeyHex = bufferToSignalHex(newRootKey);
289
+ receivingChainKeyHex = bufferToSignalHex(receivingChainKey);
290
+ state.rootKey = newRootKey;
291
+ // Set receiving chain to match initiator's sending chain
292
+ state.receivingChainKey = receivingChainKey;
293
+ // Reset receiving message number for the new chain
294
+ state.receivingMessageNumber = 0;
295
+ console.log("🔄 Receiving chain set to match initiator's sending chain", {
296
+ oldRootKeyHex: initialRootKeyHex.substring(0, 16) + "...",
297
+ newRootKeyHex: newRootKeyHex.substring(0, 16) + "...",
298
+ receivingChainKeyHex: receivingChainKeyHex.substring(0, 16) + "...",
299
+ receivingChainKeyLength: receivingChainKey.byteLength,
300
+ });
301
+ // Generate our sending key pair for future messages
302
+ console.log("🔑 Generating DH key pair for responder's future sending");
303
+ _a = state;
304
+ return [4 /*yield*/, generateSignalKeyPair()];
305
+ case 2:
306
+ _a.sendingDHKeyPair = _h.sent();
307
+ // For responder's first receive, we don't derive a sending chain yet
308
+ // because we haven't sent anything. The sending chain will be derived
309
+ // when we send our first message.
310
+ console.log("✓ DH ratchet step completed (responder first receive)");
311
+ return [2 /*return*/];
312
+ case 3:
313
+ // Reset receiving message number for new chain (for non-first receive cases)
314
+ state.receivingMessageNumber = 0;
315
+ if (!!state.sendingDHKeyPair) return [3 /*break*/, 5];
316
+ console.log("⚠️ Warning: No sendingDHKeyPair found, generating new one. This might cause chain derivation issues if state was restored.");
317
+ _b = state;
318
+ return [4 /*yield*/, generateSignalKeyPair()];
319
+ case 4:
320
+ _b.sendingDHKeyPair = _h.sent();
321
+ _h.label = 5;
322
+ case 5:
323
+ if (!state.sendingDHKeyPair) return [3 /*break*/, 13];
324
+ console.log("🔄 Deriving receiving chain from: DH(our_current_private, their_public)");
325
+ _c = bufferToSignalHex;
326
+ return [4 /*yield*/, exportSignalPublicKey(state.sendingDHKeyPair.publicKey)];
327
+ case 6:
328
+ ourPublicKeyHex = _c.apply(void 0, [_h.sent()]);
329
+ _d = bufferToSignalHex;
330
+ return [4 /*yield*/, exportSignalPublicKey(newRemotePublicKey)];
331
+ case 7:
332
+ theirPublicKeyHex = _d.apply(void 0, [_h.sent()]);
333
+ if (!state.receivingDHPublicKey) return [3 /*break*/, 9];
334
+ _f = bufferToSignalHex;
335
+ return [4 /*yield*/, exportSignalPublicKey(state.receivingDHPublicKey)];
336
+ case 8:
337
+ _e = _f.apply(void 0, [_h.sent()]);
338
+ return [3 /*break*/, 10];
339
+ case 9:
340
+ _e = "null";
341
+ _h.label = 10;
342
+ case 10:
343
+ currentReceivingDHPublicKeyHex = _e;
344
+ console.log("🔍 DH key derivation details:", {
345
+ ourPublicKeyHex: ourPublicKeyHex.substring(0, 16) + "...",
346
+ theirPublicKeyHex: theirPublicKeyHex.substring(0, 16) + "...",
347
+ currentReceivingDHPublicKeyHex: currentReceivingDHPublicKeyHex !== "null"
348
+ ? currentReceivingDHPublicKeyHex.substring(0, 16) + "..."
349
+ : "null",
350
+ rootKeyLength: state.rootKey.byteLength,
351
+ rootKeyHex: bufferToSignalHex(state.rootKey).substring(0, 16) + "...",
352
+ previousChainLength: state.previousChainLength,
353
+ receivingMessageNumber: state.receivingMessageNumber,
354
+ });
355
+ return [4 /*yield*/, performSignalDH(state.sendingDHKeyPair.privateKey, newRemotePublicKey)];
356
+ case 11:
357
+ receivingDHOutput = _h.sent();
358
+ rootKeyBeforeReceivingDerivation = state.rootKey;
359
+ rootKeyBeforeReceivingHex = bufferToSignalHex(rootKeyBeforeReceivingDerivation);
360
+ return [4 /*yield*/, doubleRatchetHKDF(new Uint8Array(rootKeyBeforeReceivingDerivation), receivingDHOutput, DOUBLE_RATCHET_INFO_CHAIN_KEY, 64)];
361
+ case 12:
362
+ hkdfReceiving = _h.sent();
363
+ oldRootKeyHex = rootKeyBeforeReceivingHex.substring(0, 16) + "...";
364
+ state.rootKey = hkdfReceiving.slice(0, 32);
365
+ state.receivingChainKey = hkdfReceiving.slice(32, 64);
366
+ newRootKeyHex = bufferToSignalHex(state.rootKey).substring(0, 16) + "...";
367
+ receivingChainKeyHex = bufferToSignalHex(state.receivingChainKey).substring(0, 16) + "...";
368
+ console.log("🔄 DH ratchet step - receiving chain established", {
369
+ oldRootKeyHex: oldRootKeyHex,
370
+ newRootKeyHex: newRootKeyHex,
371
+ receivingChainKeyHex: receivingChainKeyHex,
372
+ receivingChainKeyLength: state.receivingChainKey.byteLength,
373
+ previousChainLength: state.previousChainLength,
374
+ });
375
+ _h.label = 13;
376
+ case 13:
377
+ // Step 2: Generate NEW DH key pair and derive sending chain
378
+ // This only executes for subsequent ratchet steps (not responder's first receive)
379
+ console.log("🔑 Generating NEW DH key pair for ratchet step", {
380
+ rootKeyBeforeSendingDerivation: bufferToSignalHex(state.rootKey).substring(0, 16) + "...",
381
+ previousChainLength: state.previousChainLength,
382
+ });
383
+ _g = state;
384
+ return [4 /*yield*/, generateSignalKeyPair()];
385
+ case 14:
386
+ _g.sendingDHKeyPair = _h.sent();
387
+ state.sendingMessageNumber = 0;
388
+ rootKeyBeforeSendingDerivation = state.rootKey;
389
+ rootKeyBeforeSendingHex = bufferToSignalHex(rootKeyBeforeSendingDerivation);
390
+ return [4 /*yield*/, performSignalDH(state.sendingDHKeyPair.privateKey, newRemotePublicKey)];
391
+ case 15:
392
+ sendingDHOutput = _h.sent();
393
+ return [4 /*yield*/, doubleRatchetHKDF(new Uint8Array(rootKeyBeforeSendingDerivation), sendingDHOutput, DOUBLE_RATCHET_INFO_CHAIN_KEY, 64)];
394
+ case 16:
395
+ hkdfSending = _h.sent();
396
+ state.rootKey = hkdfSending.slice(0, 32);
397
+ state.sendingChainKey = hkdfSending.slice(32, 64);
398
+ rootKeyAfterHex = bufferToSignalHex(state.rootKey);
399
+ sendingChainKeyHex = bufferToSignalHex(state.sendingChainKey);
400
+ console.log("🔄 DH ratchet step - sending chain established", {
401
+ rootKeyBeforeHex: rootKeyBeforeSendingHex.substring(0, 16) + "...",
402
+ rootKeyAfterHex: rootKeyAfterHex.substring(0, 16) + "...",
403
+ sendingChainKeyHex: sendingChainKeyHex.substring(0, 16) + "...",
404
+ previousChainLength: state.previousChainLength,
405
+ });
406
+ console.log("✓ DH ratchet step completed");
407
+ return [2 /*return*/];
408
+ }
409
+ });
410
+ }); };
411
+ // Skip message keys for out-of-order messages
412
+ var skipMessageKeys = function (state, until) { return __awaiter(void 0, void 0, void 0, function () {
413
+ var dhPublicKeyHex, _a, _b, chainKey, messageKey, keyId;
414
+ return __generator(this, function (_c) {
415
+ switch (_c.label) {
416
+ case 0:
417
+ console.log("\u23ED\uFE0F Skipping message keys from ".concat(state.receivingMessageNumber, " to ").concat(until));
418
+ if (!(state.receivingChainKey && state.receivingMessageNumber < until)) return [3 /*break*/, 8];
419
+ if (until - state.receivingMessageNumber > MAX_SKIPPED_MESSAGE_KEYS) {
420
+ throw new Error("Too many skipped message keys: ".concat(until - state.receivingMessageNumber));
421
+ }
422
+ if (!state.receivingDHPublicKey) return [3 /*break*/, 2];
423
+ _b = bufferToSignalHex;
424
+ return [4 /*yield*/, exportSignalPublicKey(state.receivingDHPublicKey)];
425
+ case 1:
426
+ _a = _b.apply(void 0, [_c.sent()]);
427
+ return [3 /*break*/, 3];
428
+ case 2:
429
+ _a = "null";
430
+ _c.label = 3;
431
+ case 3:
432
+ dhPublicKeyHex = _a;
433
+ chainKey = state.receivingChainKey;
434
+ _c.label = 4;
435
+ case 4:
436
+ if (!(state.receivingMessageNumber < until)) return [3 /*break*/, 7];
437
+ return [4 /*yield*/, deriveMessageKey(chainKey)];
438
+ case 5:
439
+ messageKey = _c.sent();
440
+ keyId = "".concat(dhPublicKeyHex, ":").concat(state.receivingMessageNumber);
441
+ state.skippedMessageKeys.set(keyId, messageKey);
442
+ return [4 /*yield*/, deriveNextChainKey(chainKey)];
443
+ case 6:
444
+ chainKey = _c.sent();
445
+ state.receivingMessageNumber++;
446
+ console.log("\uD83D\uDCDD Saved skipped message key for ".concat(keyId));
447
+ return [3 /*break*/, 4];
448
+ case 7:
449
+ state.receivingChainKey = chainKey;
450
+ _c.label = 8;
451
+ case 8: return [2 /*return*/];
452
+ }
453
+ });
454
+ }); };
455
+ // Encrypt message using Double Ratchet
456
+ export var doubleRatchetEncrypt = function (state, plaintext) { return __awaiter(void 0, void 0, void 0, function () {
457
+ var sendingDHOutput, hkdfSending, messageKey, dhPublicKeyBuffer, dhPublicKeyBytes, sendingDHPublicKeyHex, rootKeyHex, sendingChainKeyHex, receivingDHPublicKeyHex, _a, _b, aad, view, plaintextBytes, iv, cryptoKey, ciphertext, _c, messageEnvelope;
458
+ return __generator(this, function (_d) {
459
+ switch (_d.label) {
460
+ case 0:
461
+ console.log("\uD83D\uDD12 Encrypting message #".concat(state.sendingMessageNumber, " with Double Ratchet"));
462
+ if (!!state.sendingChainKey) return [3 /*break*/, 4];
463
+ if (!(!state.isInitiator &&
464
+ state.receivingDHPublicKey &&
465
+ state.sendingDHKeyPair)) return [3 /*break*/, 3];
466
+ console.log("🔄 Responder's first send: Deriving sending chain");
467
+ return [4 /*yield*/, performSignalDH(state.sendingDHKeyPair.privateKey, state.receivingDHPublicKey)];
468
+ case 1:
469
+ sendingDHOutput = _d.sent();
470
+ return [4 /*yield*/, doubleRatchetHKDF(new Uint8Array(state.rootKey), sendingDHOutput, DOUBLE_RATCHET_INFO_CHAIN_KEY, 64)];
471
+ case 2:
472
+ hkdfSending = _d.sent();
473
+ state.rootKey = hkdfSending.slice(0, 32);
474
+ state.sendingChainKey = hkdfSending.slice(32, 64);
475
+ state.sendingMessageNumber = 0;
476
+ state.previousChainLength = state.receivingMessageNumber;
477
+ console.log("✅ Sending chain derived for responder's first message");
478
+ return [3 /*break*/, 4];
479
+ case 3: throw new Error("No sending chain key available - cannot encrypt");
480
+ case 4: return [4 /*yield*/, deriveMessageKey(state.sendingChainKey)];
481
+ case 5:
482
+ messageKey = _d.sent();
483
+ return [4 /*yield*/, exportSignalPublicKey(state.sendingDHKeyPair.publicKey)];
484
+ case 6:
485
+ dhPublicKeyBuffer = _d.sent();
486
+ dhPublicKeyBytes = new Uint8Array(dhPublicKeyBuffer);
487
+ sendingDHPublicKeyHex = bufferToSignalHex(dhPublicKeyBuffer);
488
+ rootKeyHex = bufferToSignalHex(state.rootKey);
489
+ sendingChainKeyHex = bufferToSignalHex(state.sendingChainKey);
490
+ if (!state.receivingDHPublicKey) return [3 /*break*/, 8];
491
+ _b = bufferToSignalHex;
492
+ return [4 /*yield*/, exportSignalPublicKey(state.receivingDHPublicKey)];
493
+ case 7:
494
+ _a = _b.apply(void 0, [_d.sent()]);
495
+ return [3 /*break*/, 9];
496
+ case 8:
497
+ _a = "null";
498
+ _d.label = 9;
499
+ case 9:
500
+ receivingDHPublicKeyHex = _a;
501
+ console.log("🔑 Alice encryption - Chain and message keys", {
502
+ sendingDHPublicKeyHex: sendingDHPublicKeyHex.substring(0, 16) + "...",
503
+ receivingDHPublicKeyHex: receivingDHPublicKeyHex !== "null"
504
+ ? receivingDHPublicKeyHex.substring(0, 16) + "..."
505
+ : "null",
506
+ rootKeyHex: rootKeyHex.substring(0, 16) + "...",
507
+ sendingChainKeyHex: sendingChainKeyHex.substring(0, 16) + "...",
508
+ sendingMessageNumber: state.sendingMessageNumber,
509
+ previousChainLength: state.previousChainLength,
510
+ });
511
+ aad = new Uint8Array(dhPublicKeyBytes.length + 8);
512
+ aad.set(dhPublicKeyBytes);
513
+ view = new DataView(aad.buffer, dhPublicKeyBytes.length);
514
+ view.setUint32(0, state.sendingMessageNumber, true);
515
+ view.setUint32(4, state.previousChainLength, true);
516
+ plaintextBytes = new TextEncoder().encode(plaintext);
517
+ iv = crypto.getRandomValues(new Uint8Array(12));
518
+ return [4 /*yield*/, crypto.subtle.importKey("raw", messageKey.buffer, { name: "AES-GCM" }, false, ["encrypt"])];
519
+ case 10:
520
+ cryptoKey = _d.sent();
521
+ return [4 /*yield*/, crypto.subtle.encrypt({ name: "AES-GCM", iv: iv, additionalData: aad }, cryptoKey, plaintextBytes)];
522
+ case 11:
523
+ ciphertext = _d.sent();
524
+ console.log("🔍 Encryption details:", {
525
+ messageNumber: state.sendingMessageNumber,
526
+ previousChainLength: state.previousChainLength,
527
+ dhPublicKeyLength: dhPublicKeyBytes.length,
528
+ plaintextLength: plaintextBytes.length,
529
+ ciphertextLength: ciphertext.byteLength,
530
+ ivLength: iv.length,
531
+ aadLength: aad.length,
532
+ messageKeyLength: messageKey.length,
533
+ });
534
+ // Update sending chain key
535
+ _c = state;
536
+ return [4 /*yield*/, deriveNextChainKey(state.sendingChainKey)];
537
+ case 12:
538
+ // Update sending chain key
539
+ _c.sendingChainKey = _d.sent();
540
+ messageEnvelope = {
541
+ dhPublicKey: dhPublicKeyBytes,
542
+ messageNumber: state.sendingMessageNumber,
543
+ previousChainLength: state.previousChainLength,
544
+ ciphertext: new Uint8Array(ciphertext),
545
+ iv: iv,
546
+ timestamp: Date.now(),
547
+ };
548
+ // Include X3DH ephemeral public key in the first message from initiator
549
+ if (state.isInitiator &&
550
+ state.sendingMessageNumber === 0 &&
551
+ state.x3dhEphemeralPublic) {
552
+ console.log("📤 Including X3DH ephemeral public key in first message");
553
+ messageEnvelope.x3dhEphemeralPublic = new Uint8Array(state.x3dhEphemeralPublic);
554
+ }
555
+ state.sendingMessageNumber++;
556
+ console.log("\u2705 Message encrypted successfully (msg #".concat(state.sendingMessageNumber - 1, ")"));
557
+ // Securely delete message key
558
+ messageKey.fill(0);
559
+ return [2 /*return*/, messageEnvelope];
560
+ }
561
+ });
562
+ }); };
563
+ // Decrypt message using Double Ratchet
564
+ export var doubleRatchetDecrypt = function (state, messageEnvelope) { return __awaiter(void 0, void 0, void 0, function () {
565
+ var dhPublicKey, messageNumber, previousChainLength, ciphertext, iv, dhPublicKeyHex, skippedKeyId, messageKey, currentDhKeyHex, _a, _b, remotePublicKey, skippedKeyCheck, originalChainKey, receivingChainKeyHex, rootKeyHex, receivingDHPublicKeyHex, _c, _d, _e, currentMessageNumber, aad, view, cryptoKey, aadDetails, rootKeyHex, messageKeyHex, receivingChainKeyHex, plaintext, plaintextString, error_1, errorObj;
566
+ return __generator(this, function (_f) {
567
+ switch (_f.label) {
568
+ case 0:
569
+ console.log("\uD83D\uDD13 Decrypting message #".concat(messageEnvelope.messageNumber, " with Double Ratchet"));
570
+ // Log initial state for debugging
571
+ console.log("🔍 Initial decrypt state:", {
572
+ receivingMessageNumber: state.receivingMessageNumber,
573
+ sendingMessageNumber: state.sendingMessageNumber,
574
+ previousChainLength: state.previousChainLength,
575
+ hasReceivingChainKey: !!state.receivingChainKey,
576
+ hasReceivingDHPublicKey: !!state.receivingDHPublicKey,
577
+ hasSendingDHKeyPair: !!state.sendingDHKeyPair,
578
+ isInitiator: state.isInitiator,
579
+ });
580
+ dhPublicKey = messageEnvelope.dhPublicKey, messageNumber = messageEnvelope.messageNumber, previousChainLength = messageEnvelope.previousChainLength, ciphertext = messageEnvelope.ciphertext, iv = messageEnvelope.iv;
581
+ dhPublicKeyHex = bufferToSignalHex(dhPublicKey.buffer);
582
+ skippedKeyId = "".concat(dhPublicKeyHex, ":").concat(messageNumber);
583
+ messageKey = state.skippedMessageKeys.get(skippedKeyId);
584
+ if (!messageKey) return [3 /*break*/, 1];
585
+ console.log("\uD83D\uDCCB Using skipped message key for message ".concat(messageNumber));
586
+ state.skippedMessageKeys.delete(skippedKeyId);
587
+ return [3 /*break*/, 17];
588
+ case 1:
589
+ if (!state.receivingDHPublicKey) return [3 /*break*/, 3];
590
+ _b = bufferToSignalHex;
591
+ return [4 /*yield*/, exportSignalPublicKey(state.receivingDHPublicKey)];
592
+ case 2:
593
+ _a = _b.apply(void 0, [_f.sent()]);
594
+ return [3 /*break*/, 4];
595
+ case 3:
596
+ _a = null;
597
+ _f.label = 4;
598
+ case 4:
599
+ currentDhKeyHex = _a;
600
+ console.log("🔍 DH key comparison:", {
601
+ messageDhKeyHex: dhPublicKeyHex.substring(0, 16) + "...",
602
+ currentDhKeyHex: currentDhKeyHex
603
+ ? currentDhKeyHex.substring(0, 16) + "..."
604
+ : "null",
605
+ match: dhPublicKeyHex === currentDhKeyHex,
606
+ receivingMessageNumber: state.receivingMessageNumber,
607
+ });
608
+ if (!(dhPublicKeyHex !== currentDhKeyHex)) return [3 /*break*/, 8];
609
+ console.log("🔄 New DH public key detected, performing ratchet step");
610
+ // Skip message keys for current chain if needed
611
+ return [4 /*yield*/, skipMessageKeys(state, state.receivingMessageNumber)];
612
+ case 5:
613
+ // Skip message keys for current chain if needed
614
+ _f.sent();
615
+ return [4 /*yield*/, importSignalPublicKey(dhPublicKey.buffer)];
616
+ case 6:
617
+ remotePublicKey = _f.sent();
618
+ return [4 /*yield*/, performDHRatchetStep(state, remotePublicKey)];
619
+ case 7:
620
+ _f.sent();
621
+ _f.label = 8;
622
+ case 8:
623
+ if (!(messageNumber > state.receivingMessageNumber)) return [3 /*break*/, 10];
624
+ return [4 /*yield*/, skipMessageKeys(state, messageNumber)];
625
+ case 9:
626
+ _f.sent();
627
+ _f.label = 10;
628
+ case 10:
629
+ if (!(messageNumber !== state.receivingMessageNumber)) return [3 /*break*/, 11];
630
+ skippedKeyCheck = state.skippedMessageKeys.get(skippedKeyId);
631
+ if (!skippedKeyCheck) {
632
+ throw new Error("Message number mismatch: expected ".concat(state.receivingMessageNumber, ", got ").concat(messageNumber, ". This may indicate a missing message or synchronization issue."));
633
+ }
634
+ // If we found it in skipped keys, we should have handled it earlier
635
+ // This shouldn't happen, but if it does, use the skipped key
636
+ messageKey = skippedKeyCheck;
637
+ state.skippedMessageKeys.delete(skippedKeyId);
638
+ console.log("\uD83D\uDCCB Using skipped message key for message ".concat(messageNumber, " (late catch)"));
639
+ return [3 /*break*/, 17];
640
+ case 11:
641
+ // Derive message key
642
+ if (!state.receivingChainKey) {
643
+ throw new Error("No receiving chain key available - cannot decrypt");
644
+ }
645
+ originalChainKey = state.receivingChainKey;
646
+ receivingChainKeyHex = bufferToSignalHex(originalChainKey);
647
+ rootKeyHex = bufferToSignalHex(state.rootKey);
648
+ if (!state.receivingDHPublicKey) return [3 /*break*/, 13];
649
+ _d = bufferToSignalHex;
650
+ return [4 /*yield*/, exportSignalPublicKey(state.receivingDHPublicKey)];
651
+ case 12:
652
+ _c = _d.apply(void 0, [_f.sent()]);
653
+ return [3 /*break*/, 14];
654
+ case 13:
655
+ _c = "null";
656
+ _f.label = 14;
657
+ case 14:
658
+ receivingDHPublicKeyHex = _c;
659
+ return [4 /*yield*/, deriveMessageKey(originalChainKey)];
660
+ case 15:
661
+ messageKey = _f.sent();
662
+ _e = state;
663
+ return [4 /*yield*/, deriveNextChainKey(originalChainKey)];
664
+ case 16:
665
+ _e.receivingChainKey = _f.sent();
666
+ currentMessageNumber = state.receivingMessageNumber;
667
+ state.receivingMessageNumber++;
668
+ console.log("🔑 Bob decryption - Chain and message keys", {
669
+ messageNumber: currentMessageNumber,
670
+ chainKeyLength: originalChainKey.byteLength,
671
+ messageKeyLength: messageKey.length,
672
+ nextReceivingMessageNumber: state.receivingMessageNumber,
673
+ receivingDHPublicKeyHex: receivingDHPublicKeyHex.substring(0, 16) + "...",
674
+ rootKeyHex: rootKeyHex.substring(0, 16) + "...",
675
+ receivingChainKeyHex: receivingChainKeyHex.substring(0, 16) + "...",
676
+ previousChainLength: state.previousChainLength,
677
+ });
678
+ _f.label = 17;
679
+ case 17:
680
+ aad = new Uint8Array(dhPublicKey.length + 8);
681
+ aad.set(dhPublicKey);
682
+ view = new DataView(aad.buffer, dhPublicKey.length);
683
+ view.setUint32(0, messageNumber, true);
684
+ view.setUint32(4, previousChainLength, true);
685
+ // Log AAD details for debugging (before decryption attempt)
686
+ console.log("🔍 AAD details for decryption:", {
687
+ dhPublicKeyHex: dhPublicKeyHex.substring(0, 16) + "...",
688
+ messageNumber: messageNumber,
689
+ previousChainLength: previousChainLength,
690
+ statePreviousChainLength: state.previousChainLength,
691
+ receivingMessageNumber: state.receivingMessageNumber,
692
+ aadLength: aad.length,
693
+ messageKeyLength: messageKey.length,
694
+ });
695
+ return [4 /*yield*/, crypto.subtle.importKey("raw", messageKey.buffer, { name: "AES-GCM" }, false, ["decrypt"])];
696
+ case 18:
697
+ cryptoKey = _f.sent();
698
+ _f.label = 19;
699
+ case 19:
700
+ _f.trys.push([19, 21, , 22]);
701
+ aadDetails = {
702
+ dhPublicKeyPrefix: Array.from(dhPublicKey.slice(0, 8))
703
+ .map(function (b) { return b.toString(16).padStart(2, "0"); })
704
+ .join(""),
705
+ messageNumberBytes: Array.from(new Uint8Array(aad.slice(dhPublicKey.length, dhPublicKey.length + 4)))
706
+ .map(function (b) { return b.toString(16).padStart(2, "0"); })
707
+ .join(""),
708
+ previousChainLengthBytes: Array.from(new Uint8Array(aad.slice(dhPublicKey.length + 4)))
709
+ .map(function (b) { return b.toString(16).padStart(2, "0"); })
710
+ .join(""),
711
+ };
712
+ rootKeyHex = bufferToSignalHex(state.rootKey);
713
+ messageKeyHex = bufferToSignalHex(messageKey.buffer);
714
+ receivingChainKeyHex = state.receivingChainKey
715
+ ? bufferToSignalHex(state.receivingChainKey)
716
+ : "null";
717
+ console.log("🔍 Decryption attempt details:", {
718
+ messageNumber: messageNumber,
719
+ previousChainLength: previousChainLength,
720
+ statePreviousChainLength: state.previousChainLength,
721
+ dhPublicKeyLength: dhPublicKey.length,
722
+ ciphertextLength: ciphertext.length,
723
+ ivLength: iv.length,
724
+ aadLength: aad.length,
725
+ messageKeyLength: messageKey.length,
726
+ rootKeyHex: rootKeyHex.substring(0, 32) + "...", // Show more for comparison
727
+ receivingChainKeyHex: receivingChainKeyHex !== "null"
728
+ ? receivingChainKeyHex.substring(0, 32) + "..."
729
+ : "null",
730
+ messageKeyHex: messageKeyHex.substring(0, 32) + "...",
731
+ receivingMessageNumber: state.receivingMessageNumber,
732
+ aadDetails: aadDetails,
733
+ });
734
+ return [4 /*yield*/, crypto.subtle.decrypt({ name: "AES-GCM", iv: new Uint8Array(iv), additionalData: aad }, cryptoKey, new Uint8Array(ciphertext))];
735
+ case 20:
736
+ plaintext = _f.sent();
737
+ plaintextString = new TextDecoder().decode(plaintext);
738
+ console.log("\u2705 Message decrypted successfully: \"".concat(plaintextString, "\""));
739
+ // Securely delete message key
740
+ messageKey.fill(0);
741
+ return [2 /*return*/, plaintextString];
742
+ case 21:
743
+ error_1 = _f.sent();
744
+ errorObj = error_1 instanceof Error ? error_1 : new Error(String(error_1));
745
+ console.error("❌ Message decryption failed:", errorObj);
746
+ console.error("❌ Decryption error details:", {
747
+ errorName: errorObj.name,
748
+ errorMessage: errorObj.message,
749
+ messageNumber: messageNumber,
750
+ previousChainLength: previousChainLength,
751
+ dhPublicKeyLength: dhPublicKey.length,
752
+ ciphertextLength: ciphertext.length,
753
+ ivLength: iv.length,
754
+ aadLength: aad.length,
755
+ messageKeyLength: messageKey.length,
756
+ });
757
+ throw new Error("Message decryption failed - authentication failed: ".concat(errorObj.message));
758
+ case 22: return [2 /*return*/];
759
+ }
760
+ });
761
+ }); };
762
+ // Serialize Double Ratchet state for storage
763
+ export var serializeDoubleRatchetState = function (state) { return __awaiter(void 0, void 0, void 0, function () {
764
+ var serialized, _a, _b, _c, _d;
765
+ var _e;
766
+ return __generator(this, function (_f) {
767
+ switch (_f.label) {
768
+ case 0:
769
+ _e = {
770
+ rootKey: bufferToSignalHex(state.rootKey),
771
+ sendingChainKey: state.sendingChainKey
772
+ ? bufferToSignalHex(state.sendingChainKey)
773
+ : null,
774
+ receivingChainKey: state.receivingChainKey
775
+ ? bufferToSignalHex(state.receivingChainKey)
776
+ : null
777
+ };
778
+ if (!state.sendingDHKeyPair) return [3 /*break*/, 2];
779
+ _b = bufferToSignalHex;
780
+ return [4 /*yield*/, exportSignalPublicKey(state.sendingDHKeyPair.publicKey)];
781
+ case 1:
782
+ _a = _b.apply(void 0, [_f.sent()]);
783
+ return [3 /*break*/, 3];
784
+ case 2:
785
+ _a = null;
786
+ _f.label = 3;
787
+ case 3:
788
+ _e.sendingDHPublicKey = _a;
789
+ if (!state.receivingDHPublicKey) return [3 /*break*/, 5];
790
+ _d = bufferToSignalHex;
791
+ return [4 /*yield*/, exportSignalPublicKey(state.receivingDHPublicKey)];
792
+ case 4:
793
+ _c = _d.apply(void 0, [_f.sent()]);
794
+ return [3 /*break*/, 6];
795
+ case 5:
796
+ _c = null;
797
+ _f.label = 6;
798
+ case 6:
799
+ serialized = (_e.receivingDHPublicKey = _c,
800
+ _e.sendingMessageNumber = state.sendingMessageNumber,
801
+ _e.receivingMessageNumber = state.receivingMessageNumber,
802
+ _e.previousChainLength = state.previousChainLength,
803
+ _e.isInitiator = state.isInitiator,
804
+ _e.initialized = state.initialized,
805
+ _e.skippedMessageKeysCount = state.skippedMessageKeys.size,
806
+ _e);
807
+ return [2 /*return*/, JSON.stringify(serialized)];
808
+ }
809
+ });
810
+ }); };
811
+ // Clean up old skipped message keys to prevent memory bloat
812
+ export var cleanupSkippedMessageKeys = function (state, maxAge) {
813
+ if (maxAge === void 0) { maxAge = 7 * 24 * 60 * 60 * 1000; }
814
+ var now = Date.now();
815
+ var keysToDelete = [];
816
+ // In a real implementation, you'd track the age of each skipped key
817
+ // For now, just limit the total number
818
+ if (state.skippedMessageKeys.size > MAX_SKIPPED_MESSAGE_KEYS * 0.8) {
819
+ var keys = Array.from(state.skippedMessageKeys.keys());
820
+ var deleteCount = state.skippedMessageKeys.size - MAX_SKIPPED_MESSAGE_KEYS / 2;
821
+ for (var i = 0; i < deleteCount; i++) {
822
+ keysToDelete.push(keys[i]);
823
+ }
824
+ }
825
+ keysToDelete.forEach(function (key) {
826
+ state.skippedMessageKeys.delete(key);
827
+ });
828
+ if (keysToDelete.length > 0) {
829
+ console.log("\uD83E\uDDF9 Cleaned up ".concat(keysToDelete.length, " old skipped message keys"));
830
+ }
831
+ };
832
+ // Demonstrate Double Ratchet conversation
833
+ export var demonstrateDoubleRatchet = function () { return __awaiter(void 0, void 0, void 0, function () {
834
+ var _a, initializeSignalUser, getSignalPublicKeyBundle, performSignalX3DHKeyExchange, alice, bob, bobBundle, exchangeResult, aliceState, bobState, conversation, msg1, decrypted1, msg2, decrypted2, result, error_2;
835
+ var _b;
836
+ return __generator(this, function (_c) {
837
+ switch (_c.label) {
838
+ case 0:
839
+ _c.trys.push([0, 14, , 15]);
840
+ console.log("🚀 Starting Double Ratchet demonstration...");
841
+ return [4 /*yield*/, import("./signal-protocol")];
842
+ case 1:
843
+ _a = _c.sent(), initializeSignalUser = _a.initializeSignalUser, getSignalPublicKeyBundle = _a.getSignalPublicKeyBundle, performSignalX3DHKeyExchange = _a.performSignalX3DHKeyExchange;
844
+ return [4 /*yield*/, initializeSignalUser("Alice")];
845
+ case 2:
846
+ alice = _c.sent();
847
+ return [4 /*yield*/, initializeSignalUser("Bob")];
848
+ case 3:
849
+ bob = _c.sent();
850
+ return [4 /*yield*/, getSignalPublicKeyBundle(bob)];
851
+ case 4:
852
+ bobBundle = _c.sent();
853
+ return [4 /*yield*/, performSignalX3DHKeyExchange(alice, bobBundle)];
854
+ case 5:
855
+ exchangeResult = _c.sent();
856
+ return [4 /*yield*/, initializeDoubleRatchet(exchangeResult.masterSecret, true)];
857
+ case 6:
858
+ aliceState = _c.sent();
859
+ return [4 /*yield*/, initializeDoubleRatchet(exchangeResult.masterSecret, false)];
860
+ case 7:
861
+ bobState = _c.sent();
862
+ console.log("📊 Double Ratchet states initialized");
863
+ conversation = [];
864
+ return [4 /*yield*/, doubleRatchetEncrypt(aliceState, "Hello Bob! This is our first Double Ratchet message! 🔒")];
865
+ case 8:
866
+ msg1 = _c.sent();
867
+ conversation.push({ from: "Alice", envelope: msg1 });
868
+ return [4 /*yield*/, doubleRatchetDecrypt(bobState, msg1)];
869
+ case 9:
870
+ decrypted1 = _c.sent();
871
+ console.log("Bob decrypted: \"".concat(decrypted1, "\""));
872
+ return [4 /*yield*/, doubleRatchetEncrypt(bobState, "Hi Alice! The Double Ratchet is working perfectly! 🎉")];
873
+ case 10:
874
+ msg2 = _c.sent();
875
+ conversation.push({ from: "Bob", envelope: msg2 });
876
+ return [4 /*yield*/, doubleRatchetDecrypt(aliceState, msg2)];
877
+ case 11:
878
+ decrypted2 = _c.sent();
879
+ console.log("Alice decrypted: \"".concat(decrypted2, "\""));
880
+ console.log("✅ Double Ratchet basic exchange completed successfully");
881
+ _b = {
882
+ success: true
883
+ };
884
+ return [4 /*yield*/, serializeDoubleRatchetState(aliceState)];
885
+ case 12:
886
+ _b.aliceState = _c.sent();
887
+ return [4 /*yield*/, serializeDoubleRatchetState(bobState)];
888
+ case 13:
889
+ result = (_b.bobState = _c.sent(),
890
+ _b.conversation = conversation,
891
+ _b.messagesExchanged = conversation.length,
892
+ _b.demonstration = {
893
+ forwardSecrecy: true,
894
+ outOfOrderHandling: true,
895
+ dhRatcheting: true,
896
+ chainKeyUpdating: true,
897
+ },
898
+ _b);
899
+ console.log("✅ Double Ratchet demonstration completed successfully");
900
+ return [2 /*return*/, result];
901
+ case 14:
902
+ error_2 = _c.sent();
903
+ console.error("❌ Double Ratchet demonstration failed:", error_2);
904
+ throw error_2;
905
+ case 15: return [2 /*return*/];
906
+ }
907
+ });
908
+ }); };