shogun-core 6.2.3 → 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 +138850 -146638
  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 -370
  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
@@ -1,34 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- // Crypto module exports for shogun-core
18
- __exportStar(require("./symmetric"), exports);
19
- __exportStar(require("./asymmetric"), exports);
20
- __exportStar(require("./hashing"), exports);
21
- __exportStar(require("./file-encryption"), exports);
22
- __exportStar(require("./signal-protocol"), exports);
23
- __exportStar(require("./double-ratchet"), exports);
24
- __exportStar(require("./random-generation"), exports);
25
- // RFC-compliant MLS and SFrame implementations
26
- __exportStar(require("./mls"), exports);
27
- __exportStar(require("./mls-codec"), exports);
28
- __exportStar(require("./sframe"), exports);
29
- // PGP/OpenPGP implementation
30
- __exportStar(require("./pgp"), exports);
31
- __exportStar(require("./types"), exports);
32
- __exportStar(require("./utils"), exports);
33
- // Main crypto provider (only for React apps)
34
- // export { CryptoProvider, useCrypto } from './provider';
@@ -1,569 +0,0 @@
1
- "use strict";
2
- /**
3
- * MLS (Message Layer Security) Manager
4
- * RFC 9420 implementation using ts-mls library
5
- * Provides end-to-end encrypted group messaging with forward secrecy
6
- */
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.MLSManager = void 0;
9
- const ts_mls_1 = require("ts-mls");
10
- // Helper to strip trailing null nodes per RFC 9420
11
- function stripTrailingNulls(tree) {
12
- let lastNonNull = tree.length - 1;
13
- while (lastNonNull >= 0 && tree[lastNonNull] === null) {
14
- lastNonNull--;
15
- }
16
- return tree.slice(0, lastNonNull + 1);
17
- }
18
- /**
19
- * MLSManager wraps the ts-mls functional API with a class-based interface
20
- * for easier state management in applications
21
- */
22
- class MLSManager {
23
- constructor(userId) {
24
- this.cipherSuite = null;
25
- this.initialized = false;
26
- this.groups = new Map();
27
- this.keyPackage = null;
28
- this.userId = userId;
29
- this.credential = {
30
- credentialType: "basic",
31
- identity: new TextEncoder().encode(userId),
32
- };
33
- }
34
- /**
35
- * Initialize the MLS client with a ciphersuite
36
- */
37
- async initialize() {
38
- if (this.initialized) {
39
- console.warn("MLS Manager already initialized");
40
- return;
41
- }
42
- try {
43
- console.log(`🔐 [MLS] Initializing for user: ${this.userId}`);
44
- // Use MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 (ID: 1)
45
- // Using nobleCryptoProvider for compatibility (pure JS implementation)
46
- const cipherSuiteName = "MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519";
47
- const cs = (0, ts_mls_1.getCiphersuiteFromName)(cipherSuiteName);
48
- this.cipherSuite = await ts_mls_1.nobleCryptoProvider.getCiphersuiteImpl(cs);
49
- console.log(`✅ [MLS] Using ciphersuite: ${cipherSuiteName}`);
50
- // Mark as initialized before generating key package
51
- this.initialized = true;
52
- // Generate initial key package for this user
53
- await this.generateKeyPackage();
54
- console.log("✅ [MLS] Initialized successfully");
55
- }
56
- catch (error) {
57
- console.error("❌ [MLS] Failed to initialize:", error);
58
- throw new Error(`MLS initialization failed: ${error instanceof Error ? error.message : String(error)}`);
59
- }
60
- }
61
- /**
62
- * Generate a new key package for joining groups
63
- */
64
- async generateKeyPackage() {
65
- this.ensureInitialized();
66
- try {
67
- console.log("🔑 [MLS] Generating key package");
68
- const keyPackageResult = await (0, ts_mls_1.generateKeyPackage)(this.credential, (0, ts_mls_1.defaultCapabilities)(), ts_mls_1.defaultLifetime, [], this.cipherSuite);
69
- this.keyPackage = {
70
- ...keyPackageResult,
71
- userId: this.userId,
72
- };
73
- console.log("✅ [MLS] Key package generated");
74
- return this.keyPackage;
75
- }
76
- catch (error) {
77
- console.error("❌ [MLS] Failed to generate key package:", error);
78
- throw new Error(`Key package generation failed: ${error instanceof Error ? error.message : String(error)}`);
79
- }
80
- }
81
- /**
82
- * Get the current key package
83
- */
84
- getKeyPackage() {
85
- return this.keyPackage;
86
- }
87
- /**
88
- * Create a new MLS group
89
- */
90
- async createGroup(groupId) {
91
- this.ensureInitialized();
92
- try {
93
- console.log(`📝 [MLS] Creating group: ${groupId}`);
94
- if (!this.keyPackage) {
95
- throw new Error("No key package available. Call generateKeyPackage() first.");
96
- }
97
- const groupIdBytes = new TextEncoder().encode(groupId);
98
- // Create group using ts-mls
99
- const groupState = await (0, ts_mls_1.createGroup)(groupIdBytes, this.keyPackage.publicPackage, this.keyPackage.privatePackage, [], this.cipherSuite);
100
- this.groups.set(groupId, groupState);
101
- const groupInfo = {
102
- groupId: groupIdBytes,
103
- members: [this.userId],
104
- epoch: groupState.groupContext.epoch,
105
- };
106
- console.log(`✅ [MLS] Group created: ${groupId}, epoch: ${groupState.groupContext.epoch}`);
107
- return groupInfo;
108
- }
109
- catch (error) {
110
- console.error("❌ [MLS] Failed to create group:", error);
111
- throw new Error(`Group creation failed: ${error instanceof Error ? error.message : String(error)}`);
112
- }
113
- }
114
- /**
115
- * Add members to an existing group
116
- */
117
- async addMembers(groupId, keyPackages) {
118
- this.ensureInitialized();
119
- try {
120
- console.log(`➕ [MLS] Adding ${keyPackages.length} member(s) to group: ${groupId}`);
121
- const groupState = this.groups.get(groupId);
122
- if (!groupState) {
123
- throw new Error(`Group ${groupId} not found`);
124
- }
125
- // Create add proposals for each key package
126
- const addProposals = keyPackages.map((kp) => ({
127
- proposalType: "add",
128
- add: {
129
- keyPackage: kp.publicPackage,
130
- },
131
- }));
132
- // Create commit with add proposals
133
- const commitResult = await (0, ts_mls_1.createCommit)({ state: groupState, cipherSuite: this.cipherSuite }, { extraProposals: addProposals });
134
- // Update group state
135
- this.groups.set(groupId, commitResult.newState);
136
- if (!commitResult.welcome) {
137
- throw new Error("No welcome message generated");
138
- }
139
- console.log(`✅ [MLS] Members added, new epoch: ${commitResult.newState.groupContext.epoch}`);
140
- // Debug: Log the commit structure
141
- console.group("🔍 [MLS Debug] Commit Structure");
142
- console.log("commitResult keys:", Object.keys(commitResult));
143
- console.log("commit:", commitResult.commit);
144
- if (commitResult.commit?.wireformat === "mls_private_message") {
145
- console.log("commit.privateMessage:", commitResult.commit.privateMessage);
146
- }
147
- console.groupEnd();
148
- // RFC 9420 Section 11.2: Commit Distribution
149
- // ⚠️ IMPORTANT: The returned commit MUST be sent to all existing group members
150
- // so they can process it with processCommit() to stay synchronized.
151
- //
152
- // Distribution flow:
153
- // 1. Alice adds Bob: addMembers() returns { welcome, commit }
154
- // 2. Alice sends welcome to Bob (new member)
155
- // 3. Alice sends commit to existing members (Charlie, David, etc.)
156
- // 4. All existing members call processCommit(commit) to update their state
157
- //
158
- // Without distributing the commit, existing members will remain at old epoch
159
- // and won't be able to decrypt messages from the updated group.
160
- // Convert ratchetTree to a real array (it's Uint8Array-like with numeric indices)
161
- const ratchetTreeArray = Array.from(commitResult.newState.ratchetTree);
162
- // RFC 9420: Strip trailing null nodes before transmission
163
- const strippedTree = stripTrailingNulls(ratchetTreeArray);
164
- console.log(`🔍 [MLS] Ratchet tree stripped: ${ratchetTreeArray.length} -> ${strippedTree.length} nodes`);
165
- return {
166
- welcome: commitResult.welcome,
167
- ratchetTree: strippedTree,
168
- commit: commitResult.commit,
169
- };
170
- }
171
- catch (error) {
172
- console.error("❌ [MLS] Failed to add members:", error);
173
- throw new Error(`Adding members failed: ${error instanceof Error ? error.message : String(error)}`);
174
- }
175
- }
176
- /**
177
- * Process a Welcome message to join an MLS group
178
- *
179
- * RFC 9420 Compliance:
180
- * - Interior null nodes represent blank parent nodes (unmerged positions)
181
- * - These nulls are REQUIRED for proper binary tree structure
182
- * - Trailing nulls are stripped by sender (per RFC 9420 requirement)
183
- * - ratchetTree parameter is optional; ts-mls can extract from Welcome extension
184
- *
185
- * @param welcome - The Welcome message from group creator
186
- * @param ratchetTree - Optional ratchet tree (normally provided out-of-band)
187
- */
188
- async processWelcome(welcome, ratchetTree) {
189
- this.ensureInitialized();
190
- try {
191
- console.log("📩 [MLS] Processing welcome message");
192
- if (!this.keyPackage) {
193
- throw new Error("No key package available");
194
- }
195
- // RFC 9420: Interior null nodes are valid (represent blank parent nodes)
196
- // Trailing nulls are stripped by sender per RFC requirement
197
- // Simply pass the tree as-is to ts-mls joinGroup()
198
- if (ratchetTree && Array.isArray(ratchetTree)) {
199
- const nullCount = ratchetTree.filter((n) => n === null).length;
200
- console.log(`🔍 [MLS] Ratchet tree received: ${ratchetTree.length} nodes (${nullCount} interior nulls)`);
201
- // DEBUG: Log structure of each node
202
- console.group("🔍 [MLS Debug] Ratchet Tree Structure");
203
- ratchetTree.forEach((node, i) => {
204
- if (node === null) {
205
- console.log(` Node ${i}: NULL`);
206
- }
207
- else {
208
- console.log(` Node ${i}:`, {
209
- type: typeof node,
210
- isObject: typeof node === "object" && node !== null,
211
- hasNodeType: typeof node === "object" && node !== null && "nodeType" in node,
212
- nodeType: node?.nodeType,
213
- keys: node && typeof node === "object"
214
- ? Object.keys(node).slice(0, 5)
215
- : "n/a",
216
- });
217
- }
218
- });
219
- console.groupEnd();
220
- }
221
- const groupState = await (0, ts_mls_1.joinGroup)(welcome, this.keyPackage.publicPackage, this.keyPackage.privatePackage, ts_mls_1.emptyPskIndex, this.cipherSuite, ratchetTree);
222
- const groupId = new TextDecoder().decode(groupState.groupContext.groupId);
223
- this.groups.set(groupId, groupState);
224
- // Extract member identities from ratchet tree
225
- const members = this.extractMembersFromState(groupState);
226
- const groupInfo = {
227
- groupId: groupState.groupContext.groupId,
228
- members,
229
- epoch: groupState.groupContext.epoch,
230
- };
231
- console.log(`✅ [MLS] Welcome processed, joined group: ${groupId}`);
232
- return groupInfo;
233
- }
234
- catch (error) {
235
- console.error("❌ [MLS] Failed to process welcome:", error);
236
- throw new Error(`Welcome processing failed: ${error instanceof Error ? error.message : String(error)}`);
237
- }
238
- }
239
- /**
240
- * Encrypt a message for a group
241
- */
242
- async encryptMessage(groupId, plaintext) {
243
- this.ensureInitialized();
244
- try {
245
- console.log(`🔒 [MLS] Encrypting message for group: ${groupId}`);
246
- const groupState = this.groups.get(groupId);
247
- if (!groupState) {
248
- throw new Error(`Group ${groupId} not found`);
249
- }
250
- const plaintextBytes = new TextEncoder().encode(plaintext);
251
- // Create application message
252
- const result = await (0, ts_mls_1.createApplicationMessage)(groupState, plaintextBytes, this.cipherSuite);
253
- // Update group state (for key ratcheting)
254
- this.groups.set(groupId, result.newState);
255
- // Encode the private message
256
- const encoded = (0, ts_mls_1.encodeMlsMessage)({
257
- privateMessage: result.privateMessage,
258
- wireformat: "mls_private_message",
259
- version: "mls10",
260
- });
261
- const envelope = {
262
- groupId: new TextEncoder().encode(groupId),
263
- ciphertext: encoded,
264
- timestamp: Date.now(),
265
- };
266
- console.log("✅ [MLS] Message encrypted");
267
- return envelope;
268
- }
269
- catch (error) {
270
- console.error("❌ [MLS] Failed to encrypt message:", error);
271
- throw new Error(`Message encryption failed: ${error instanceof Error ? error.message : String(error)}`);
272
- }
273
- }
274
- /**
275
- * Decrypt a message from a group
276
- */
277
- async decryptMessage(envelope) {
278
- this.ensureInitialized();
279
- try {
280
- const groupId = new TextDecoder().decode(envelope.groupId);
281
- console.log(`🔓 [MLS] Decrypting message for group: ${groupId}`);
282
- const groupState = this.groups.get(groupId);
283
- if (!groupState) {
284
- throw new Error(`Group ${groupId} not found`);
285
- }
286
- // Decode the message
287
- const decoded = (0, ts_mls_1.decodeMlsMessage)(envelope.ciphertext, 0);
288
- if (!decoded || decoded.length === 0) {
289
- // Changed from 0n to 0 to fix type error
290
- throw new Error("Failed to decode message");
291
- }
292
- const decodedMessage = decoded[0];
293
- if (decodedMessage.wireformat !== "mls_private_message") {
294
- throw new Error("Expected private message");
295
- }
296
- // Process the private message
297
- const result = await (0, ts_mls_1.processPrivateMessage)(groupState, decodedMessage.privateMessage, ts_mls_1.emptyPskIndex, this.cipherSuite);
298
- // Update group state
299
- this.groups.set(groupId, result.newState);
300
- if (result.kind !== "applicationMessage") {
301
- throw new Error("Expected application message");
302
- }
303
- const plaintext = new TextDecoder().decode(result.message);
304
- console.log("✅ [MLS] Message decrypted");
305
- return plaintext;
306
- }
307
- catch (error) {
308
- console.error("❌ [MLS] Failed to decrypt message:", error);
309
- throw new Error(`Decryption failed: ${error instanceof Error ? error.message : String(error)}`);
310
- }
311
- }
312
- /**
313
- * Update the group keys (key rotation)
314
- */
315
- async updateKey(groupId) {
316
- this.ensureInitialized();
317
- try {
318
- console.log(`🔄 [MLS] Performing key rotation for group: ${groupId}`);
319
- const groupState = this.groups.get(groupId);
320
- if (!groupState) {
321
- throw new Error(`Group ${groupId} not found`);
322
- }
323
- // Create update commit (forces path update)
324
- const commitResult = await (0, ts_mls_1.createCommit)({ state: groupState, cipherSuite: this.cipherSuite }, {});
325
- // Update group state
326
- this.groups.set(groupId, commitResult.newState);
327
- console.log(`✅ [MLS] Key rotation successful, new epoch: ${commitResult.newState.groupContext.epoch}`);
328
- // Return the raw commit object for other members to process
329
- return commitResult.commit;
330
- }
331
- catch (error) {
332
- console.error("❌ [MLS] Failed to update key:", error);
333
- throw new Error(`Key update failed: ${error instanceof Error ? error.message : String(error)}`);
334
- }
335
- }
336
- /**
337
- * Process a commit message (key rotation, member changes)
338
- *
339
- * RFC 9420 Section 12.1.8:
340
- * - Update commits (key rotation) → PrivateMessage
341
- * - Add/Remove commits → PublicMessage (for existing group members)
342
- *
343
- * This implementation handles both types based on wireformat.
344
- */
345
- async processCommit(groupId, commit) {
346
- this.ensureInitialized();
347
- try {
348
- console.log(`⚙️ [MLS] Processing commit for group: ${groupId}`);
349
- console.log(`🔍 [MLS Debug] Commit wireformat: ${commit.wireformat}`);
350
- // DETAILED DEBUG LOGGING
351
- console.group("🔍 [MLS Debug] Full Commit Structure");
352
- console.log("commit keys:", Object.keys(commit));
353
- console.log("commit.wireformat:", commit.wireformat);
354
- console.log("commit.publicMessage:", commit.publicMessage);
355
- console.log("commit.privateMessage:", commit.privateMessage);
356
- // Log proposals if present
357
- if (commit.publicMessage?.content) {
358
- console.log("publicMessage.content:", commit.publicMessage.content);
359
- console.log("publicMessage.content.proposals:", commit.publicMessage.content.proposals);
360
- if (commit.publicMessage.content.proposals) {
361
- commit.publicMessage.content.proposals.forEach((prop, i) => {
362
- console.log(` Proposal ${i}:`, {
363
- proposalType: prop.proposalType,
364
- keys: Object.keys(prop),
365
- full: prop,
366
- });
367
- });
368
- }
369
- }
370
- console.groupEnd();
371
- const groupState = this.groups.get(groupId);
372
- if (!groupState) {
373
- throw new Error(`Group ${groupId} not found`);
374
- }
375
- let result;
376
- // RFC 9420: Route based on message type
377
- if (commit.wireformat === "mls_public_message") {
378
- // Public messages (add/remove member commits)
379
- console.log("🔍 [MLS Debug] Processing as PUBLIC message (add/remove)...");
380
- const publicMessage = commit.publicMessage || commit;
381
- result = await (0, ts_mls_1.processPublicMessage)(groupState, publicMessage, ts_mls_1.emptyPskIndex, this.cipherSuite);
382
- }
383
- else if (commit.wireformat === "mls_private_message") {
384
- // Private messages (update/key rotation commits)
385
- console.log("🔍 [MLS Debug] Processing as PRIVATE message (update)...");
386
- const privateMessage = commit.privateMessage || commit;
387
- result = await (0, ts_mls_1.processPrivateMessage)(groupState, privateMessage, ts_mls_1.emptyPskIndex, this.cipherSuite);
388
- }
389
- else {
390
- throw new Error(`Unknown commit wireformat: ${commit.wireformat}`);
391
- }
392
- // Update group state
393
- this.groups.set(groupId, result.newState);
394
- console.log(`✅ [MLS] Commit processed, epoch: ${result.newState.groupContext.epoch}`);
395
- }
396
- catch (error) {
397
- console.error("❌ [MLS] Failed to process commit:", error);
398
- console.error("❌ [MLS Debug] Error details:", error instanceof Error ? error.stack : String(error));
399
- console.error("❌ [MLS Debug] Error message:", error instanceof Error ? error.message : String(error));
400
- throw new Error(`Commit processing failed: ${error instanceof Error ? error.message : String(error)}`);
401
- }
402
- }
403
- /**
404
- * Remove members from a group
405
- */
406
- async removeMembers(groupId, memberIndices) {
407
- this.ensureInitialized();
408
- try {
409
- console.log(`➖ [MLS] Removing ${memberIndices.length} member(s) from group: ${groupId}`);
410
- const groupState = this.groups.get(groupId);
411
- if (!groupState) {
412
- throw new Error(`Group ${groupId} not found`);
413
- }
414
- // Create remove proposals
415
- const removeProposals = memberIndices.map((index) => ({
416
- proposalType: "remove",
417
- remove: {
418
- removed: index, // Changed from BigInt(index) to number
419
- },
420
- }));
421
- // Create commit with remove proposals
422
- const commitResult = await (0, ts_mls_1.createCommit)({ state: groupState, cipherSuite: this.cipherSuite }, { extraProposals: removeProposals });
423
- // Update group state
424
- this.groups.set(groupId, commitResult.newState);
425
- // Encode the commit
426
- let encodedCommit;
427
- if (commitResult.commit &&
428
- commitResult.commit.wireformat === "mls_public_message") {
429
- encodedCommit = (0, ts_mls_1.encodeMlsMessage)({
430
- publicMessage: commitResult.commit
431
- .publicMessage,
432
- wireformat: "mls_public_message",
433
- version: "mls10",
434
- });
435
- }
436
- else {
437
- // Fallback or error handling if not a public message
438
- // For now, we'll assume it should be public for remove operation.
439
- throw new Error("Commit result does not contain a public message for encoding.");
440
- }
441
- console.log("✅ [MLS] Members removed");
442
- return encodedCommit;
443
- }
444
- catch (error) {
445
- console.error("❌ [MLS] Failed to remove members:", error);
446
- throw new Error(`Member removal failed: ${error instanceof Error ? error.message : String(error)}`);
447
- }
448
- }
449
- /**
450
- * Get list of groups
451
- */
452
- async getGroups() {
453
- this.ensureInitialized();
454
- try {
455
- const groupIds = Array.from(this.groups.keys()).map((id) => new TextEncoder().encode(id));
456
- return groupIds;
457
- }
458
- catch (error) {
459
- console.error("❌ [MLS] Failed to get groups:", error);
460
- throw new Error(`Getting groups failed: ${error instanceof Error ? error.message : String(error)}`);
461
- }
462
- }
463
- /**
464
- * Export group state for persistence
465
- */
466
- async exportGroupState(groupId) {
467
- this.ensureInitialized();
468
- try {
469
- console.log(`💾 [MLS] Exporting state for group: ${groupId}`);
470
- const groupState = this.groups.get(groupId);
471
- if (!groupState) {
472
- throw new Error(`Group ${groupId} not found`);
473
- }
474
- // Note: ts-mls ClientState contains non-serializable crypto keys
475
- // This is a simplified export - in production you'd need proper serialization
476
- const exportData = {
477
- groupId,
478
- epoch: groupState.groupContext.epoch.toString(),
479
- exported: Date.now(),
480
- // Add other serializable fields as needed
481
- };
482
- console.log("✅ [MLS] Group state exported");
483
- return exportData;
484
- }
485
- catch (error) {
486
- console.error("❌ [MLS] Failed to export group state:", error);
487
- throw new Error(`Group state export failed: ${error instanceof Error ? error.message : String(error)}`);
488
- }
489
- }
490
- /**
491
- * Get user ID
492
- */
493
- getUserId() {
494
- return this.userId;
495
- }
496
- /**
497
- * Get group information
498
- */
499
- async getGroupKeyInfo(groupId) {
500
- const groupState = this.groups.get(groupId);
501
- if (!groupState) {
502
- return null;
503
- }
504
- const members = this.extractMembersFromState(groupState);
505
- return {
506
- groupId,
507
- epoch: groupState.groupContext.epoch.toString(),
508
- members,
509
- cipherSuite: "MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519",
510
- treeHash: this.bytesToHex(groupState.groupContext.treeHash).substring(0, 16),
511
- };
512
- }
513
- /**
514
- * Clean up resources
515
- */
516
- async destroy() {
517
- this.groups.clear();
518
- this.keyPackage = null;
519
- this.initialized = false;
520
- console.log("✅ [MLS] Manager destroyed");
521
- }
522
- /**
523
- * Extract member identities from group state
524
- */
525
- extractMembersFromState(state) {
526
- const members = [];
527
- try {
528
- // Iterate through ratchet tree to find leaf nodes
529
- for (let i = 0; i < state.ratchetTree.length; i++) {
530
- const node = state.ratchetTree[i];
531
- if (node &&
532
- node.nodeType === "leaf" &&
533
- node.leaf.credential) {
534
- const credential = node.leaf.credential;
535
- if (credential.credentialType === "basic" && credential.identity) {
536
- const identity = new TextDecoder().decode(credential.identity);
537
- members.push(identity);
538
- }
539
- else {
540
- console.warn("Skipping credential without basic identity:", credential);
541
- }
542
- }
543
- }
544
- }
545
- catch (error) {
546
- console.warn("Could not extract members:", error);
547
- members.push(this.userId); // At least include self
548
- }
549
- return members;
550
- }
551
- /**
552
- * Convert bytes to hex string
553
- */
554
- bytesToHex(bytes) {
555
- return Array.from(bytes)
556
- .map((b) => b.toString(16).padStart(2, "0"))
557
- .join("");
558
- }
559
- /**
560
- * Ensure the manager is initialized
561
- */
562
- ensureInitialized() {
563
- if (!this.initialized) {
564
- throw new Error("MLS Manager not initialized. Call initialize() first.");
565
- }
566
- }
567
- }
568
- exports.MLSManager = MLSManager;
569
- exports.default = MLSManager;