chatly-sdk 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CONTRIBUTING.md +658 -0
  2. package/IMPROVEMENTS.md +402 -0
  3. package/README.md +1539 -162
  4. package/dist/index.d.ts +430 -9
  5. package/dist/index.js +1420 -63
  6. package/examples/01-basic-chat/README.md +61 -0
  7. package/examples/01-basic-chat/index.js +58 -0
  8. package/examples/01-basic-chat/package.json +13 -0
  9. package/examples/02-group-chat/README.md +78 -0
  10. package/examples/02-group-chat/index.js +76 -0
  11. package/examples/02-group-chat/package.json +13 -0
  12. package/examples/03-offline-messaging/README.md +73 -0
  13. package/examples/03-offline-messaging/index.js +80 -0
  14. package/examples/03-offline-messaging/package.json +13 -0
  15. package/examples/04-live-chat/README.md +80 -0
  16. package/examples/04-live-chat/index.js +114 -0
  17. package/examples/04-live-chat/package.json +13 -0
  18. package/examples/05-hybrid-messaging/README.md +71 -0
  19. package/examples/05-hybrid-messaging/index.js +106 -0
  20. package/examples/05-hybrid-messaging/package.json +13 -0
  21. package/examples/06-postgresql-integration/README.md +101 -0
  22. package/examples/06-postgresql-integration/adapters/groupStore.js +73 -0
  23. package/examples/06-postgresql-integration/adapters/messageStore.js +47 -0
  24. package/examples/06-postgresql-integration/adapters/userStore.js +40 -0
  25. package/examples/06-postgresql-integration/index.js +92 -0
  26. package/examples/06-postgresql-integration/package.json +14 -0
  27. package/examples/06-postgresql-integration/schema.sql +58 -0
  28. package/examples/08-customer-support/README.md +70 -0
  29. package/examples/08-customer-support/index.js +104 -0
  30. package/examples/08-customer-support/package.json +13 -0
  31. package/examples/README.md +105 -0
  32. package/jest.config.cjs +28 -0
  33. package/package.json +12 -8
  34. package/src/chat/ChatSession.ts +81 -0
  35. package/src/chat/GroupSession.ts +79 -0
  36. package/src/constants.ts +61 -0
  37. package/src/crypto/e2e.ts +0 -20
  38. package/src/index.ts +525 -63
  39. package/src/models/mediaTypes.ts +58 -0
  40. package/src/models/message.ts +4 -1
  41. package/src/transport/adapters.ts +51 -1
  42. package/src/transport/memoryTransport.ts +75 -13
  43. package/src/transport/websocketClient.ts +269 -21
  44. package/src/transport/websocketServer.ts +26 -26
  45. package/src/utils/errors.ts +97 -0
  46. package/src/utils/logger.ts +96 -0
  47. package/src/utils/mediaUtils.ts +235 -0
  48. package/src/utils/messageQueue.ts +162 -0
  49. package/src/utils/validation.ts +99 -0
  50. package/test/crypto.test.ts +122 -35
  51. package/test/sdk.test.ts +276 -0
  52. package/test/validation.test.ts +64 -0
  53. package/tsconfig.json +11 -10
  54. package/tsconfig.test.json +11 -0
  55. package/src/ChatManager.ts +0 -103
  56. package/src/crypto/keyManager.ts +0 -28
@@ -0,0 +1,104 @@
1
+ import {
2
+ ChatSDK,
3
+ InMemoryUserStore,
4
+ InMemoryMessageStore,
5
+ InMemoryGroupStore,
6
+ MemoryTransport,
7
+ EVENTS,
8
+ LogLevel
9
+ } from 'chatly-sdk';
10
+
11
+ async function main() {
12
+ console.log('🎧 Chatly SDK - Customer Support Example');
13
+ console.log('========================================\n');
14
+
15
+ // Initialize support system
16
+ const transport = new MemoryTransport();
17
+ const sdk = new ChatSDK({
18
+ userStore: new InMemoryUserStore(),
19
+ messageStore: new InMemoryMessageStore(),
20
+ groupStore: new InMemoryGroupStore(),
21
+ transport,
22
+ logLevel: LogLevel.NONE,
23
+ });
24
+
25
+ console.log('Setting up support system...');
26
+
27
+ // Create support agent and customer
28
+ const agent = await sdk.createUser('support-agent');
29
+ const customer = await sdk.createUser('customer-john');
30
+ console.log('✅ Support agent created');
31
+ console.log('✅ Customer created\n');
32
+
33
+ // Create support session
34
+ const session = await sdk.startSession(customer, agent);
35
+
36
+ // Scenario 1: Customer sends message (agent offline)
37
+ console.log('Scenario 1: Customer sends message (agent offline)');
38
+ sdk.setCurrentUser(customer);
39
+
40
+ await sdk.sendMessage(session, 'I need help with my order');
41
+ console.log('📝 Customer: I need help with my order');
42
+ console.log('⏳ Message queued (no agents available)\n');
43
+
44
+ await new Promise(resolve => setTimeout(resolve, 1000));
45
+
46
+ // Scenario 2: Agent comes online and sees pending messages
47
+ console.log('Scenario 2: Agent comes online');
48
+ sdk.setCurrentUser(agent);
49
+ await sdk.setCurrentUser(agent); // Connect agent
50
+
51
+ console.log('🟢 Agent online');
52
+
53
+ const pendingMessages = await sdk.getMessagesForUser(agent.id);
54
+ console.log(`📬 Agent has ${pendingMessages.length} pending message(s)`);
55
+
56
+ for (const msg of pendingMessages) {
57
+ const text = await sdk.decryptMessage(msg, agent);
58
+ console.log(`📨 Agent sees: ${text}`);
59
+ }
60
+ console.log();
61
+
62
+ // Scenario 3: Live chat (both online)
63
+ console.log('Scenario 3: Live chat (both online)');
64
+ console.log('💬 Real-time conversation started\n');
65
+
66
+ // Set up real-time event listeners
67
+ sdk.on(EVENTS.MESSAGE_RECEIVED, async (message) => {
68
+ const currentUser = sdk.getCurrentUser();
69
+ if (currentUser) {
70
+ const plaintext = await sdk.decryptMessage(message, currentUser);
71
+ console.log(`📨 ${currentUser.username} received: ${plaintext}`);
72
+ }
73
+ });
74
+
75
+ // Agent responds
76
+ sdk.setCurrentUser(agent);
77
+ await sdk.sendMessage(session, 'Hi! How can I help?');
78
+ console.log('📤 Agent: Hi! How can I help?');
79
+ await new Promise(resolve => setTimeout(resolve, 300));
80
+
81
+ // Customer replies
82
+ sdk.setCurrentUser(customer);
83
+ await sdk.sendMessage(session, 'My order #12345 is delayed');
84
+ console.log('📤 Customer: My order #12345 is delayed');
85
+ await new Promise(resolve => setTimeout(resolve, 300));
86
+
87
+ // Agent helps
88
+ sdk.setCurrentUser(agent);
89
+ await sdk.sendMessage(session, 'Let me check that for you');
90
+ console.log('📤 Agent: Let me check that for you');
91
+ await new Promise(resolve => setTimeout(resolve, 300));
92
+
93
+ console.log();
94
+ console.log('✅ Support system works perfectly!');
95
+ console.log('\n💡 Key Features:');
96
+ console.log(' - 24/7 availability (customers message anytime)');
97
+ console.log(' - Offline queue (messages saved for agents)');
98
+ console.log(' - Real-time chat when both online');
99
+ console.log(' - Full conversation history');
100
+
101
+ await sdk.disconnect();
102
+ }
103
+
104
+ main().catch(console.error);
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "chatly-sdk-customer-support-example",
3
+ "version": "1.0.0",
4
+ "description": "Customer support chat system example using Chatly SDK",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "scripts": {
8
+ "start": "node index.js"
9
+ },
10
+ "dependencies": {
11
+ "chatly-sdk": "^0.0.5"
12
+ }
13
+ }
@@ -0,0 +1,105 @@
1
+ # Chatly SDK - Examples
2
+
3
+ This directory contains practical examples demonstrating different use cases for the Chatly SDK.
4
+
5
+ ## 📚 Examples
6
+
7
+ ### 1. [Basic Chat](./01-basic-chat)
8
+ **Difficulty**: Beginner
9
+ **Topics**: User creation, sessions, encryption, message sending
10
+
11
+ Simple 1:1 encrypted chat between two users.
12
+
13
+ ---
14
+
15
+ ### 2. [Group Chat](./02-group-chat)
16
+ **Difficulty**: Beginner
17
+ **Topics**: Group creation, multi-user messaging, group encryption
18
+
19
+ Multi-user encrypted group messaging with 3+ participants.
20
+
21
+ ---
22
+
23
+ ### 3. [Offline Messaging](./03-offline-messaging)
24
+ Asynchronous messaging without WebSocket
25
+
26
+ ### 2. **Real-time Examples**
27
+ - [`04-live-chat/`](./04-live-chat/) - Live chat with WebSocket (WhatsApp-style)
28
+ - [`05-hybrid-messaging/`](./05-hybrid-messaging/) - Hybrid online/offline messaging
29
+
30
+ ### 3. **Database Integration**
31
+ - [`06-postgresql-integration/`](./06-postgresql-integration/) - PostgreSQL storage adapter
32
+ - [`07-mongodb-integration/`](./07-mongodb-integration/) - MongoDB storage adapter
33
+
34
+ ### 4. **Real-world Applications**
35
+ - [`08-customer-support/`](./08-customer-support/) - Customer support chat system
36
+ - [`09-react-chat-app/`](./09-react-chat-app/) - Full React chat application
37
+ - [`10-websocket-server/`](./10-websocket-server/) - Node.js WebSocket server
38
+
39
+ ## 🚀 Quick Start
40
+
41
+ Each example includes:
42
+ - ✅ Complete source code
43
+ - ✅ README with setup instructions
44
+ - ✅ package.json for dependencies
45
+ - ✅ Comments explaining key concepts
46
+
47
+ ### Running an Example
48
+
49
+ ```bash
50
+ # Navigate to an example
51
+ cd examples/01-basic-chat
52
+
53
+ # Install dependencies
54
+ npm install
55
+
56
+ # Run the example
57
+ npm start
58
+ ```
59
+
60
+ ## 📚 Learning Path
61
+
62
+ **Beginner**: Start here
63
+ 1. `01-basic-chat` - Learn the basics
64
+ 2. `02-group-chat` - Understand group messaging
65
+ 3. `03-offline-messaging` - See how offline works
66
+
67
+ **Intermediate**: Real-time features
68
+ 4. `04-live-chat` - Add WebSocket support
69
+ 5. `05-hybrid-messaging` - Combine online/offline
70
+
71
+ **Advanced**: Production setup
72
+ 6. `06-postgresql-integration` - Database persistence
73
+ 7. `08-customer-support` - Real-world application
74
+ 8. `09-react-chat-app` - Full frontend integration
75
+
76
+ ## 🎯 Use Case Guide
77
+
78
+ | Use Case | Example | Description |
79
+ |----------|---------|-------------|
80
+ | **Messaging App** | `04-live-chat` | WhatsApp-style real-time chat |
81
+ | **Customer Support** | `08-customer-support` | Live support with offline fallback |
82
+ | **Team Collaboration** | `02-group-chat` + `04-live-chat` | Slack-style team chat |
83
+ | **Social Media DMs** | `05-hybrid-messaging` | Instagram-style direct messages |
84
+ | **Email-like System** | `03-offline-messaging` | Asynchronous messaging |
85
+
86
+ ## 💡 Key Concepts Demonstrated
87
+
88
+ - ✅ **End-to-end encryption** - All examples use E2E encryption
89
+ - ✅ **Message queue** - Automatic retry and offline support
90
+ - ✅ **Event handling** - Real-time UI updates
91
+ - ✅ **Database integration** - PostgreSQL and MongoDB
92
+ - ✅ **WebSocket** - Real-time bidirectional communication
93
+ - ✅ **React integration** - Hooks and context providers
94
+
95
+ ## 🔧 Prerequisites
96
+
97
+ - Node.js >= 16.x
98
+ - npm >= 8.x
99
+ - (Optional) PostgreSQL or MongoDB for database examples
100
+
101
+ ## 📞 Need Help?
102
+
103
+ - Check the main [README](../README.md)
104
+ - Read [CONTRIBUTING.md](../CONTRIBUTING.md)
105
+ - Open an [issue](https://github.com/bharath-arch/chatly-sdk/issues)
@@ -0,0 +1,28 @@
1
+ module.exports = {
2
+ preset: 'ts-jest',
3
+ testEnvironment: 'node',
4
+ roots: ['<rootDir>/test'],
5
+ testMatch: ['**/*.test.ts'],
6
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
7
+ transform: {
8
+ '^.+\\.ts$': ['ts-jest', {
9
+ tsconfig: 'tsconfig.test.json',
10
+ }],
11
+ },
12
+ collectCoverageFrom: [
13
+ 'src/**/*.ts',
14
+ '!src/**/*.d.ts',
15
+ '!src/**/index.ts',
16
+ ],
17
+ coverageThreshold: {
18
+ global: {
19
+ branches: 70,
20
+ functions: 70,
21
+ lines: 70,
22
+ statements: 70,
23
+ },
24
+ },
25
+ moduleNameMapper: {
26
+ '^(\\.{1,2}/.*)\\.js$': '$1',
27
+ },
28
+ };
package/package.json CHANGED
@@ -1,23 +1,23 @@
1
1
  {
2
2
  "name": "chatly-sdk",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
8
  "build": "tsup src/index.ts --dts --format esm",
9
9
  "start": "ts-node src/index.ts",
10
- "test": "ts-node test/crypto.test.ts"
10
+ "test": "jest",
11
+ "test:watch": "jest --watch",
12
+ "test:coverage": "jest --coverage"
11
13
  },
12
-
13
14
  "publishConfig": {
14
15
  "access": "public"
15
16
  },
16
17
  "repository": {
17
- "type": "git",
18
- "url": "https://github.com/bharath-arch/chatly-sdk.git"
19
- },
20
-
18
+ "type": "git",
19
+ "url": "https://github.com/bharath-arch/chatly-sdk.git"
20
+ },
21
21
  "keywords": [
22
22
  "chat",
23
23
  "sdk",
@@ -30,10 +30,14 @@
30
30
  "license": "MIT",
31
31
  "description": "Production-ready end-to-end encrypted chat SDK with WhatsApp-style features",
32
32
  "dependencies": {
33
- "buffer": "^6.0.3"
33
+ "buffer": "^6.0.3",
34
+ "events": "^3.3.0"
34
35
  },
35
36
  "devDependencies": {
37
+ "@types/jest": "^29.5.14",
36
38
  "@types/node": "^24.10.1",
39
+ "jest": "^29.5.0",
40
+ "ts-jest": "^29.1.0",
37
41
  "ts-node": "^10.9.2",
38
42
  "tsup": "^8.0.0",
39
43
  "typescript": "^5.9.3"
@@ -1,5 +1,6 @@
1
1
  import type { User } from "../models/user.js";
2
2
  import type { Message } from "../models/message.js";
3
+ import type { MediaAttachment } from "../models/mediaTypes.js";
3
4
  import { deriveSharedSecret, encryptMessage, decryptMessage } from "../crypto/e2e.js";
4
5
  import type { KeyPair } from "../crypto/keys.js";
5
6
  import { generateUUID } from "../crypto/uuid.js";
@@ -68,6 +69,49 @@ export class ChatSession {
68
69
  };
69
70
  }
70
71
 
72
+ /**
73
+ * Encrypt a media message for this session
74
+ */
75
+ async encryptMedia(
76
+ plaintext: string,
77
+ media: MediaAttachment,
78
+ senderId: string
79
+ ): Promise<Message> {
80
+ if (!this.sharedSecret) {
81
+ await this.initialize();
82
+ }
83
+
84
+ if (!this.sharedSecret) {
85
+ throw new Error("Failed to initialize session");
86
+ }
87
+
88
+ // Encrypt the message text (could be caption)
89
+ const { ciphertext, iv } = encryptMessage(plaintext, this.sharedSecret);
90
+
91
+ // Encrypt the media data
92
+ const { ciphertext: encryptedMediaData } = encryptMessage(
93
+ media.data,
94
+ this.sharedSecret
95
+ );
96
+
97
+ // Create encrypted media attachment
98
+ const encryptedMedia: MediaAttachment = {
99
+ ...media,
100
+ data: encryptedMediaData,
101
+ };
102
+
103
+ return {
104
+ id: generateUUID(),
105
+ senderId,
106
+ receiverId: senderId === this.userA.id ? this.userB.id : this.userA.id,
107
+ ciphertext,
108
+ iv,
109
+ timestamp: Date.now(),
110
+ type: "media",
111
+ media: encryptedMedia,
112
+ };
113
+ }
114
+
71
115
  /**
72
116
  * Decrypt a message in this session
73
117
  */
@@ -85,4 +129,41 @@ export class ChatSession {
85
129
 
86
130
  return decryptMessage(message.ciphertext, message.iv, this.sharedSecret);
87
131
  }
132
+
133
+ /**
134
+ * Decrypt a media message in this session
135
+ */
136
+ async decryptMedia(message: Message, user: User): Promise<{ text: string; media: MediaAttachment }> {
137
+ if (!message.media) {
138
+ throw new Error("Message does not contain media");
139
+ }
140
+
141
+ // Re-initialize if needed
142
+ if (!this.sharedSecret ||
143
+ (user.id !== this.userA.id && user.id !== this.userB.id)) {
144
+ await this.initializeForUser(user);
145
+ }
146
+
147
+ if (!this.sharedSecret) {
148
+ throw new Error("Failed to initialize session");
149
+ }
150
+
151
+ // Decrypt the message text
152
+ const text = decryptMessage(message.ciphertext, message.iv, this.sharedSecret);
153
+
154
+ // Decrypt the media data
155
+ const decryptedMediaData = decryptMessage(
156
+ message.media.data,
157
+ message.iv,
158
+ this.sharedSecret
159
+ );
160
+
161
+ // Create decrypted media attachment
162
+ const decryptedMedia: MediaAttachment = {
163
+ ...message.media,
164
+ data: decryptedMediaData,
165
+ };
166
+
167
+ return { text, media: decryptedMedia };
168
+ }
88
169
  }
@@ -1,5 +1,6 @@
1
1
  import type { Group } from "../models/group.js";
2
2
  import type { Message } from "../models/message.js";
3
+ import type { MediaAttachment } from "../models/mediaTypes.js";
3
4
  import { deriveGroupKey } from "../crypto/group.js";
4
5
  import { encryptMessage, decryptMessage } from "../crypto/e2e.js";
5
6
  import { base64ToBuffer } from "../crypto/utils.js";
@@ -43,6 +44,49 @@ export class GroupSession {
43
44
  };
44
45
  }
45
46
 
47
+ /**
48
+ * Encrypt a media message for this group
49
+ */
50
+ async encryptMedia(
51
+ plaintext: string,
52
+ media: MediaAttachment,
53
+ senderId: string
54
+ ): Promise<Message> {
55
+ if (!this.groupKey) {
56
+ await this.initialize();
57
+ }
58
+
59
+ if (!this.groupKey) {
60
+ throw new Error("Failed to initialize group session");
61
+ }
62
+
63
+ // Encrypt the message text (could be caption)
64
+ const { ciphertext, iv } = encryptMessage(plaintext, this.groupKey);
65
+
66
+ // Encrypt the media data
67
+ const { ciphertext: encryptedMediaData } = encryptMessage(
68
+ media.data,
69
+ this.groupKey
70
+ );
71
+
72
+ // Create encrypted media attachment
73
+ const encryptedMedia: MediaAttachment = {
74
+ ...media,
75
+ data: encryptedMediaData,
76
+ };
77
+
78
+ return {
79
+ id: generateUUID(),
80
+ senderId,
81
+ groupId: this.group.id,
82
+ ciphertext,
83
+ iv,
84
+ timestamp: Date.now(),
85
+ type: "media",
86
+ media: encryptedMedia,
87
+ };
88
+ }
89
+
46
90
  /**
47
91
  * Decrypt a message in this group
48
92
  */
@@ -57,4 +101,39 @@ export class GroupSession {
57
101
 
58
102
  return decryptMessage(message.ciphertext, message.iv, this.groupKey);
59
103
  }
104
+
105
+ /**
106
+ * Decrypt a media message in this group
107
+ */
108
+ async decryptMedia(message: Message): Promise<{ text: string; media: MediaAttachment }> {
109
+ if (!message.media) {
110
+ throw new Error("Message does not contain media");
111
+ }
112
+
113
+ if (!this.groupKey) {
114
+ await this.initialize();
115
+ }
116
+
117
+ if (!this.groupKey) {
118
+ throw new Error("Failed to initialize group session");
119
+ }
120
+
121
+ // Decrypt the message text
122
+ const text = decryptMessage(message.ciphertext, message.iv, this.groupKey);
123
+
124
+ // Decrypt the media data
125
+ const decryptedMediaData = decryptMessage(
126
+ message.media.data,
127
+ message.iv,
128
+ this.groupKey
129
+ );
130
+
131
+ // Create decrypted media attachment
132
+ const decryptedMedia: MediaAttachment = {
133
+ ...message.media,
134
+ data: decryptedMediaData,
135
+ };
136
+
137
+ return { text, media: decryptedMedia };
138
+ }
60
139
  }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * SDK Configuration Constants
3
+ */
4
+
5
+ // Cryptography
6
+ export const SUPPORTED_CURVE = "prime256v1";
7
+ export const ALGORITHM = "aes-256-gcm";
8
+ export const IV_LENGTH = 12; // 96 bits for GCM
9
+ export const SALT_LENGTH = 16;
10
+ export const KEY_LENGTH = 32; // 256 bits
11
+ export const TAG_LENGTH = 16;
12
+ export const PBKDF2_ITERATIONS = 100000;
13
+
14
+ // Validation
15
+ export const USERNAME_MIN_LENGTH = 3;
16
+ export const USERNAME_MAX_LENGTH = 20;
17
+ export const MESSAGE_MAX_LENGTH = 10000;
18
+ export const GROUP_NAME_MAX_LENGTH = 100;
19
+ export const GROUP_MIN_MEMBERS = 2;
20
+ export const GROUP_MAX_MEMBERS = 256;
21
+
22
+ // Transport
23
+ export const RECONNECT_MAX_ATTEMPTS = 5;
24
+ export const RECONNECT_BASE_DELAY = 1000; // 1 second
25
+ export const RECONNECT_MAX_DELAY = 30000; // 30 seconds
26
+ export const HEARTBEAT_INTERVAL = 30000; // 30 seconds
27
+ export const CONNECTION_TIMEOUT = 10000; // 10 seconds
28
+
29
+ // Message Queue
30
+ export const MAX_QUEUE_SIZE = 1000;
31
+ export const MESSAGE_RETRY_ATTEMPTS = 3;
32
+ export const MESSAGE_RETRY_DELAY = 2000; // 2 seconds
33
+
34
+ // Events
35
+ export const EVENTS = {
36
+ MESSAGE_SENT: 'message:sent',
37
+ MESSAGE_RECEIVED: 'message:received',
38
+ MESSAGE_FAILED: 'message:failed',
39
+ CONNECTION_STATE_CHANGED: 'connection:state',
40
+ SESSION_CREATED: 'session:created',
41
+ GROUP_CREATED: 'group:created',
42
+ ERROR: 'error',
43
+ USER_CREATED: 'user:created',
44
+ } as const;
45
+
46
+ // Connection States
47
+ export enum ConnectionState {
48
+ DISCONNECTED = 'disconnected',
49
+ CONNECTING = 'connecting',
50
+ CONNECTED = 'connected',
51
+ RECONNECTING = 'reconnecting',
52
+ FAILED = 'failed',
53
+ }
54
+
55
+ // Message Status
56
+ export enum MessageStatus {
57
+ PENDING = 'pending',
58
+ SENT = 'sent',
59
+ DELIVERED = 'delivered',
60
+ FAILED = 'failed',
61
+ }
package/src/crypto/e2e.ts CHANGED
@@ -11,26 +11,6 @@
11
11
  const TAG_LENGTH = 16;
12
12
  const PBKDF2_ITERATIONS = 100000;
13
13
 
14
- /**
15
- * Derive a shared secret using ECDH key exchange
16
- */
17
- // export function deriveSharedSecret(local: KeyPair, remotePublicKey: string): Buffer {
18
- // const ecdh = createECDH(SUPPORTED_CURVE);
19
- // ecdh.setPrivateKey(base64ToBuffer(local.privateKey));
20
-
21
- // const remotePublicKeyBuffer = base64ToBuffer(remotePublicKey);
22
- // const sharedSecret = ecdh.computeSecret(remotePublicKeyBuffer);
23
-
24
- // // Derive a symmetric key from the shared secret using PBKDF2
25
- // // Use a deterministic salt based on both public keys for consistency
26
- // const salt = Buffer.concat([
27
- // base64ToBuffer(local.publicKey),
28
- // base64ToBuffer(remotePublicKey)
29
- // ]).slice(0, SALT_LENGTH);
30
- // const derivedKey = pbkdf2Sync(sharedSecret, salt, PBKDF2_ITERATIONS, KEY_LENGTH, "sha256");
31
-
32
- // return derivedKey;
33
- // }
34
14
 
35
15
  export function deriveSharedSecret(local: KeyPair, remotePublicKey: string): Buffer {
36
16
  const ecdh = createECDH(SUPPORTED_CURVE);