mobilecoder-mcp 2.0.0 → 2.1.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.
package/dist/agent.d.ts CHANGED
@@ -3,15 +3,27 @@ export declare class ZKRelayAgent {
3
3
  private ptyProcess;
4
4
  private secretCode;
5
5
  private roomId;
6
- private encryptionKey;
6
+ private masterKey;
7
+ private sessionKey;
8
+ private sessionCounter;
9
+ private seenNonces;
10
+ private nonceCleanupInterval;
11
+ private keyRotationInterval;
7
12
  private spinner;
8
13
  constructor();
9
14
  private setupSecurity;
15
+ private deriveSessionKey;
16
+ private rotateKey;
17
+ private startSecurityMaintenance;
10
18
  private initPTY;
11
19
  private connectToRelay;
20
+ private encrypt;
21
+ private decrypt;
12
22
  private handleIncomingMessage;
23
+ private handleToolCall;
13
24
  private sendSecurePayload;
14
25
  private sendEnvInfo;
15
26
  private printBanner;
27
+ destroy(): void;
16
28
  }
17
29
  //# sourceMappingURL=agent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAWA,qBAAa,YAAY;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,OAAO,CAAwC;;IASvD,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,OAAO;IAkBf,OAAO,CAAC,cAAc;IA+DtB,OAAO,CAAC,qBAAqB;IAmC7B,OAAO,CAAC,iBAAiB;IAqBzB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,WAAW;CAYtB"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAoBA,qBAAa,YAAY;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAS;IAGvB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,oBAAoB,CAA+B;IAC3D,OAAO,CAAC,mBAAmB,CAA+B;IAE1D,OAAO,CAAC,OAAO,CAAwC;;IAUvD,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,OAAO;IAkBf,OAAO,CAAC,cAAc;IAwCtB,OAAO,CAAC,OAAO;IAiBf,OAAO,CAAC,OAAO;IAyBf,OAAO,CAAC,qBAAqB;YAyEf,cAAc;IAyC5B,OAAO,CAAC,iBAAiB;IAqCzB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,WAAW;IAeZ,OAAO;CAMjB"}
package/dist/agent.js CHANGED
@@ -1,32 +1,72 @@
1
1
  import { io } from 'socket.io-client';
2
2
  import * as os from 'os';
3
3
  import * as pty from 'node-pty';
4
- import CryptoJS from 'crypto-js';
4
+ import * as crypto from 'crypto';
5
5
  import chalk from 'chalk';
6
6
  import ora from 'ora';
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
7
9
  // 🚨 BURAYI KENDİ DOMAIN ADRESİNLE DEĞİŞTİR!
8
10
  const RELAY_SERVER_URL = 'https://api.mobilecoder.xyz';
11
+ // Security Constants
12
+ const PBKDF2_ITERATIONS = 100000;
13
+ const KEY_LENGTH = 32; // 256 bits
14
+ const SALT = 'mobilecoder-salt-v2';
15
+ const KEY_ROTATION_INTERVAL = 600000; // 10 minutes
16
+ const MESSAGE_MAX_AGE = 300000; // 5 minutes
9
17
  export class ZKRelayAgent {
10
18
  socket;
11
19
  ptyProcess;
12
20
  secretCode;
13
21
  roomId;
14
- encryptionKey;
22
+ // 🔐 Güçlendirilmiş Güvenlik Değişkenleri
23
+ masterKey;
24
+ sessionKey;
25
+ sessionCounter = 0;
26
+ seenNonces = new Set();
27
+ nonceCleanupInterval = null;
28
+ keyRotationInterval = null;
15
29
  spinner = ora('Initializing Secure Tunnel...');
16
30
  constructor() {
17
31
  this.setupSecurity();
18
32
  this.initPTY();
19
33
  this.connectToRelay();
34
+ this.startSecurityMaintenance();
20
35
  }
21
- // 1. Güvenlik Katmanı: Kod Üret ve Anahtar Türet
36
+ // 1. Güvenlik Katmanı: PBKDF2 ile Güçlendirilmiş Anahtar Türetme
22
37
  setupSecurity() {
23
38
  // 6 Haneli rastgele kod (Kullanıcının göreceği)
24
39
  const randomNum = Math.floor(100000 + Math.random() * 900000);
25
40
  this.secretCode = randomNum.toString();
26
41
  // Oda ID'si: Kodun Hash'i (Sunucu sadece bunu görür, kodu göremez)
27
- this.roomId = CryptoJS.SHA256(this.secretCode).toString();
28
- // Şifreleme Anahtarı: Kodun kendisi (AES-256 için kullanılacak)
29
- this.encryptionKey = this.secretCode;
42
+ this.roomId = crypto.createHash('sha256').update(this.secretCode).digest('hex');
43
+ // 🔐 PBKDF2 ile Master Key Türetme (Brute-force'a karşı savunma)
44
+ this.masterKey = crypto.pbkdf2Sync(this.secretCode, SALT, PBKDF2_ITERATIONS, KEY_LENGTH, 'sha256');
45
+ // Session Key (PFS için rotasyonlu)
46
+ this.sessionKey = this.deriveSessionKey(0);
47
+ }
48
+ // 🔐 Session Key Türetme (Perfect Forward Secrecy)
49
+ deriveSessionKey(counter) {
50
+ return crypto.pbkdf2Sync(this.masterKey, `session-${counter}`, 10000, KEY_LENGTH, 'sha256');
51
+ }
52
+ // 🔄 Key Rotation (Her 10 dakikada bir)
53
+ rotateKey() {
54
+ this.sessionCounter++;
55
+ this.sessionKey = this.deriveSessionKey(this.sessionCounter);
56
+ console.log(chalk.cyan(`🔄 Session key rotated to #${this.sessionCounter}`));
57
+ // Notify peer about key rotation
58
+ this.sendSecurePayload('key_rotation', { counter: this.sessionCounter });
59
+ }
60
+ // 🧹 Güvenlik Bakımı
61
+ startSecurityMaintenance() {
62
+ // Nonce temizliği (5 dakikadan eski nonce'ları sil)
63
+ this.nonceCleanupInterval = setInterval(() => {
64
+ this.seenNonces.clear();
65
+ }, MESSAGE_MAX_AGE);
66
+ // Key rotation
67
+ this.keyRotationInterval = setInterval(() => {
68
+ this.rotateKey();
69
+ }, KEY_ROTATION_INTERVAL);
30
70
  }
31
71
  // 2. Terminal (PTY) Başlatma
32
72
  initPTY() {
@@ -55,8 +95,6 @@ export class ZKRelayAgent {
55
95
  this.spinner.succeed(chalk.green('Connected to Relay Node!'));
56
96
  // Odaya Katıl (Sadece Hash ID gönderilir)
57
97
  this.socket.emit('join_room', { code: this.roomId, type: 'agent' });
58
- // Note: Changed 'join_secure_room' to 'join_room' to match server implementation
59
- // Server implementation in index.ts: socket.on('join_room', (data: { code: string; type: 'agent' | 'client' }) => ...)
60
98
  this.printBanner();
61
99
  });
62
100
  this.socket.on('disconnect', () => {
@@ -68,27 +106,7 @@ export class ZKRelayAgent {
68
106
  this.sendEnvInfo();
69
107
  });
70
108
  // Mobilden şifreli veri geldiğinde
71
- // RelayManager emits 'term_data' and 'meta_data'.
72
- // Server implementation:
73
- // socket.on('term_data', ...) -> pass through term_data
74
- // socket.on('meta_data', ...) -> pass through meta_data
75
- // Agent connects to /, Server index.ts uses / (global namespace) BUT has:
76
- // const relayNamespace = io.of('/terminal');
77
- // WAIT. Previous user setup had /terminal.
78
- // My previous edit REMOVED /terminal and used RelayManager on root io.
79
- // But RelayManager implementation listens on 'relay_data'.
80
- // My RelayManager uses: socket.on('relay_data', ...)
81
- // But user snippet provided for Agent uses 'relay_encrypted' and listens on 'stream_encrypted'.
82
- // I need to align Agent and Server.
83
- // The previous edit to server/index.ts instantiates RelayManager.
84
- // RelayManager listens to 'relay_data'.
85
- // So the Agent MUST emit 'relay_data'.
86
109
  this.socket.on('relay_data', (message) => {
87
- // RelayManager checks payload structure?
88
- // Wait, RelayManager implementation:
89
- // socket.on('relay_data', (data) => { ... socket.to(room).emit('relay_data', data.payload) ... })
90
- // So client receives `payload`.
91
- // If payload is encrypted string, handle it.
92
110
  this.handleIncomingMessage(message);
93
111
  });
94
112
  // Also listen for connect_error
@@ -96,73 +114,190 @@ export class ZKRelayAgent {
96
114
  // console.error(err);
97
115
  });
98
116
  }
117
+ // 🔐 AES-256-CBC ile Şifreleme (Nonce tabanlı)
118
+ encrypt(data) {
119
+ const nonce = crypto.randomBytes(16);
120
+ const cipher = crypto.createCipheriv('aes-256-cbc', this.sessionKey, nonce);
121
+ const encrypted = Buffer.concat([
122
+ cipher.update(data, 'utf8'),
123
+ cipher.final()
124
+ ]);
125
+ return {
126
+ nonce: nonce.toString('base64'),
127
+ data: encrypted.toString('base64'),
128
+ timestamp: Date.now()
129
+ };
130
+ }
131
+ // 🔐 AES-256-CBC ile Şifre Çözme (Replay Attack Korumalı)
132
+ decrypt(packet) {
133
+ // Timestamp kontrolü (5 dakikadan eski mesajları reddet)
134
+ if (Date.now() - packet.timestamp > MESSAGE_MAX_AGE) {
135
+ throw new Error('Message too old - potential replay attack');
136
+ }
137
+ // Nonce uniqueness kontrolü (Replay attack önleme)
138
+ if (this.seenNonces.has(packet.nonce)) {
139
+ throw new Error('Replay attack detected - duplicate nonce');
140
+ }
141
+ this.seenNonces.add(packet.nonce);
142
+ const decipher = crypto.createDecipheriv('aes-256-cbc', this.sessionKey, Buffer.from(packet.nonce, 'base64'));
143
+ return Buffer.concat([
144
+ decipher.update(Buffer.from(packet.data, 'base64')),
145
+ decipher.final()
146
+ ]).toString('utf8');
147
+ }
99
148
  // Gelen veriyi çöz ve işle
100
149
  handleIncomingMessage(encryptedPayload) {
101
150
  try {
102
- // Payload might be wrapped { e: ... } or string
103
- let ciphertext = encryptedPayload;
104
- if (typeof encryptedPayload === 'object' && encryptedPayload.e) {
105
- ciphertext = encryptedPayload.e;
151
+ let decryptedText;
152
+ // Yeni format: { nonce, data, timestamp }
153
+ if (typeof encryptedPayload === 'object' && encryptedPayload.nonce) {
154
+ decryptedText = this.decrypt(encryptedPayload);
155
+ }
156
+ // Legacy format: { e: ciphertext } (CryptoJS uyumluluğu)
157
+ else if (typeof encryptedPayload === 'object' && encryptedPayload.e) {
158
+ // Legacy CryptoJS decrypt fallback
159
+ const CryptoJS = require('crypto-js');
160
+ const bytes = CryptoJS.AES.decrypt(encryptedPayload.e, this.secretCode);
161
+ decryptedText = bytes.toString(CryptoJS.enc.Utf8);
162
+ }
163
+ else {
164
+ return;
106
165
  }
107
- const bytes = CryptoJS.AES.decrypt(ciphertext, this.encryptionKey);
108
- const originalText = bytes.toString(CryptoJS.enc.Utf8);
109
- if (!originalText)
166
+ if (!decryptedText)
110
167
  return;
111
168
  // Veri JSON mu? (Resize komutu vs olabilir)
112
169
  try {
113
- const cmd = JSON.parse(originalText);
114
- if (cmd.type === 'resize') {
115
- this.ptyProcess.resize(cmd.cols, cmd.rows);
170
+ const cmd = JSON.parse(decryptedText);
171
+ // Handle key rotation from peer
172
+ if (cmd.type === 'key_rotation') {
173
+ this.sessionCounter = cmd.counter;
174
+ this.sessionKey = this.deriveSessionKey(this.sessionCounter);
175
+ console.log(chalk.cyan(`🔄 Key synced to session #${this.sessionCounter}`));
116
176
  return;
117
177
  }
178
+ // 1. Terminal Input (Keystrokes)
118
179
  if (cmd.type === 'input') {
119
180
  this.ptyProcess.write(cmd.data);
120
181
  return;
121
182
  }
122
- // Fallback checks
183
+ // 2. Terminal Resize
184
+ if (cmd.type === 'resize') {
185
+ this.ptyProcess.resize(cmd.cols, cmd.rows);
186
+ return;
187
+ }
188
+ // 3. Chat Commands (e.g. "ls -la")
189
+ if (cmd.type === 'command') {
190
+ this.ptyProcess.write(cmd.text + '\r');
191
+ return;
192
+ }
193
+ // 4. CLI Tool/Button Commands (e.g. "git status")
194
+ if (cmd.type === 'cli_command') {
195
+ this.ptyProcess.write(cmd.command + '\r');
196
+ return;
197
+ }
198
+ // 5. Tool Calls (File System Access)
199
+ if (cmd.type === 'tool_call') {
200
+ this.handleToolCall(cmd.tool, cmd.data, cmd.id);
201
+ return;
202
+ }
123
203
  }
124
204
  catch (e) {
125
205
  // JSON değilse saf terminal girdisidir
126
- this.ptyProcess.write(originalText);
206
+ this.ptyProcess.write(decryptedText);
127
207
  }
128
208
  }
129
209
  catch (error) {
130
210
  // Şifre çözülemezse (Yanlış anahtar vb.) sessizce yut
211
+ console.error(chalk.red('Decryption failed:'), error.message);
212
+ }
213
+ }
214
+ async handleToolCall(tool, args, id) {
215
+ try {
216
+ let result = null;
217
+ if (tool === 'list_directory') {
218
+ const dirPath = args.path ? path.resolve(args.path) : process.cwd();
219
+ const entries = await fs.promises.readdir(dirPath, { withFileTypes: true });
220
+ const files = entries.map(entry => ({
221
+ name: entry.name,
222
+ type: entry.isDirectory() ? 'directory' : 'file',
223
+ size: 0 // Simplification for speed
224
+ }));
225
+ result = { files };
226
+ }
227
+ else if (tool === 'read_file') {
228
+ const filePath = path.resolve(args.path);
229
+ const content = await fs.promises.readFile(filePath, 'utf-8');
230
+ result = { content };
231
+ }
232
+ else {
233
+ throw new Error(`Unknown tool: ${tool}`);
234
+ }
235
+ this.sendSecurePayload('tool_result', {
236
+ id,
237
+ result
238
+ });
239
+ }
240
+ catch (error) {
241
+ this.sendSecurePayload('tool_result', {
242
+ id,
243
+ error: error.message,
244
+ type: 'error'
245
+ });
131
246
  }
132
247
  }
133
248
  // Veriyi şifrele ve gönder
134
249
  sendSecurePayload(type, data) {
135
- let payloadStr = data;
136
- if (type === 'meta') {
250
+ let payloadStr = '';
251
+ if (type === 'meta' || type === 'tool_result' || type === 'key_rotation') {
137
252
  // Standardize format
138
- payloadStr = JSON.stringify(data);
253
+ if (type === 'tool_result') {
254
+ if (data.type === 'error') {
255
+ payloadStr = JSON.stringify({ ...data });
256
+ }
257
+ else {
258
+ payloadStr = JSON.stringify({ type: 'result', ...data });
259
+ }
260
+ }
261
+ else if (type === 'key_rotation') {
262
+ payloadStr = JSON.stringify({ type: 'key_rotation', ...data });
263
+ }
264
+ else {
265
+ payloadStr = JSON.stringify(data);
266
+ }
139
267
  }
140
- else if (type === 'term_data' && typeof data === 'string') {
141
- // Wrap output in { type: 'output', data: ... } for client consistency if client expects JSON
142
- // The Client handles { type: 'output' ... }
143
- payloadStr = JSON.stringify({ type: 'output', data: data });
268
+ else if (type === 'term_data') {
269
+ // Wrap output in { type: 'output', data: ... }
270
+ if (typeof data === 'string') {
271
+ payloadStr = JSON.stringify({ type: 'output', data: data });
272
+ }
273
+ else {
274
+ payloadStr = JSON.stringify(data);
275
+ }
144
276
  }
145
- const encrypted = CryptoJS.AES.encrypt(payloadStr, this.encryptionKey).toString();
146
- // RelayManager expects 'relay_data' event with { room, payload }
147
- // It emits 'relay_data' with just payload to other peer.
277
+ // Fallback if empty (shouldn't happen with above logic)
278
+ if (!payloadStr)
279
+ payloadStr = JSON.stringify(data);
280
+ // 🔐 Yeni şifreleme formatı ile gönder
281
+ const encrypted = this.encrypt(payloadStr);
148
282
  this.socket.emit('relay_data', {
149
283
  room: this.roomId,
150
- payload: { e: encrypted }
284
+ payload: encrypted
151
285
  });
152
286
  }
153
287
  sendEnvInfo() {
154
288
  const info = {
155
- type: 'host_info', // Changed to match client expectation
156
- username: os.userInfo().username, // user -> username
157
- hostname: os.hostname(), // host -> hostname
289
+ type: 'host_info',
290
+ username: os.userInfo().username,
291
+ hostname: os.hostname(),
158
292
  platform: os.platform(),
159
293
  cwd: process.cwd()
160
294
  };
161
295
  this.sendSecurePayload('meta', info);
162
296
  }
163
297
  printBanner() {
164
- console.log('\n' + chalk.bgBlue.bold(' MOBILECODER ZK-RELAY v2.0 '));
165
- console.log(chalk.gray('Secure, End-to-End Encrypted Terminal Bridge\n'));
298
+ console.log('\n' + chalk.bgBlue.bold(' MOBILECODER ZK-RELAY v2.1.0 '));
299
+ console.log(chalk.gray('🔐 PBKDF2-SHA256 + AES-256-CBC + Nonce-Based Replay Protection'));
300
+ console.log(chalk.gray('🔄 Perfect Forward Secrecy with 10-min Key Rotation\n'));
166
301
  console.log(chalk.yellow('┌──────────────────────────────────────┐'));
167
302
  console.log(chalk.yellow('│ 🔑 CONNECTION CODE (ENTER ON APP) │'));
168
303
  console.log(chalk.yellow('│ │'));
@@ -171,5 +306,16 @@ export class ZKRelayAgent {
171
306
  console.log(chalk.yellow('└──────────────────────────────────────┘'));
172
307
  console.log(chalk.cyan('\nWaiting for mobile connection...'));
173
308
  }
309
+ // Cleanup
310
+ destroy() {
311
+ if (this.nonceCleanupInterval)
312
+ clearInterval(this.nonceCleanupInterval);
313
+ if (this.keyRotationInterval)
314
+ clearInterval(this.keyRotationInterval);
315
+ if (this.socket)
316
+ this.socket.disconnect();
317
+ if (this.ptyProcess)
318
+ this.ptyProcess.kill();
319
+ }
174
320
  }
175
321
  //# sourceMappingURL=agent.js.map
package/dist/agent.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobilecoder-mcp",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Secure Zero-Knowledge Terminal Relay for MobileCoder",
5
5
  "main": "dist/agent.js",
6
6
  "bin": {
package/src/agent.ts CHANGED
@@ -2,38 +2,99 @@
2
2
  import { io, Socket } from 'socket.io-client';
3
3
  import * as os from 'os';
4
4
  import * as pty from 'node-pty';
5
- import CryptoJS from 'crypto-js';
5
+ import * as crypto from 'crypto';
6
6
  import chalk from 'chalk';
7
7
  import ora from 'ora';
8
+ import * as fs from 'fs';
9
+ import * as path from 'path';
8
10
 
9
11
  // 🚨 BURAYI KENDİ DOMAIN ADRESİNLE DEĞİŞTİR!
10
12
  const RELAY_SERVER_URL = 'https://api.mobilecoder.xyz';
11
13
 
14
+ // Security Constants
15
+ const PBKDF2_ITERATIONS = 100000;
16
+ const KEY_LENGTH = 32; // 256 bits
17
+ const SALT = 'mobilecoder-salt-v2';
18
+ const KEY_ROTATION_INTERVAL = 600000; // 10 minutes
19
+ const MESSAGE_MAX_AGE = 300000; // 5 minutes
20
+
12
21
  export class ZKRelayAgent {
13
22
  private socket: Socket;
14
23
  private ptyProcess: any;
15
24
  private secretCode: string;
16
25
  private roomId: string;
17
- private encryptionKey: string;
26
+
27
+ // 🔐 Güçlendirilmiş Güvenlik Değişkenleri
28
+ private masterKey: Buffer;
29
+ private sessionKey: Buffer;
30
+ private sessionCounter: number = 0;
31
+ private seenNonces: Set<string> = new Set();
32
+ private nonceCleanupInterval: NodeJS.Timeout | null = null;
33
+ private keyRotationInterval: NodeJS.Timeout | null = null;
34
+
18
35
  private spinner = ora('Initializing Secure Tunnel...');
19
36
 
20
37
  constructor() {
21
38
  this.setupSecurity();
22
39
  this.initPTY();
23
40
  this.connectToRelay();
41
+ this.startSecurityMaintenance();
24
42
  }
25
43
 
26
- // 1. Güvenlik Katmanı: Kod Üret ve Anahtar Türet
44
+ // 1. Güvenlik Katmanı: PBKDF2 ile Güçlendirilmiş Anahtar Türetme
27
45
  private setupSecurity() {
28
46
  // 6 Haneli rastgele kod (Kullanıcının göreceği)
29
47
  const randomNum = Math.floor(100000 + Math.random() * 900000);
30
48
  this.secretCode = randomNum.toString();
31
49
 
32
50
  // Oda ID'si: Kodun Hash'i (Sunucu sadece bunu görür, kodu göremez)
33
- this.roomId = CryptoJS.SHA256(this.secretCode).toString();
51
+ this.roomId = crypto.createHash('sha256').update(this.secretCode).digest('hex');
52
+
53
+ // 🔐 PBKDF2 ile Master Key Türetme (Brute-force'a karşı savunma)
54
+ this.masterKey = crypto.pbkdf2Sync(
55
+ this.secretCode,
56
+ SALT,
57
+ PBKDF2_ITERATIONS,
58
+ KEY_LENGTH,
59
+ 'sha256'
60
+ );
61
+
62
+ // Session Key (PFS için rotasyonlu)
63
+ this.sessionKey = this.deriveSessionKey(0);
64
+ }
65
+
66
+ // 🔐 Session Key Türetme (Perfect Forward Secrecy)
67
+ private deriveSessionKey(counter: number): Buffer {
68
+ return crypto.pbkdf2Sync(
69
+ this.masterKey,
70
+ `session-${counter}`,
71
+ 10000,
72
+ KEY_LENGTH,
73
+ 'sha256'
74
+ );
75
+ }
76
+
77
+ // 🔄 Key Rotation (Her 10 dakikada bir)
78
+ private rotateKey() {
79
+ this.sessionCounter++;
80
+ this.sessionKey = this.deriveSessionKey(this.sessionCounter);
81
+ console.log(chalk.cyan(`🔄 Session key rotated to #${this.sessionCounter}`));
34
82
 
35
- // Şifreleme Anahtarı: Kodun kendisi (AES-256 için kullanılacak)
36
- this.encryptionKey = this.secretCode;
83
+ // Notify peer about key rotation
84
+ this.sendSecurePayload('key_rotation', { counter: this.sessionCounter });
85
+ }
86
+
87
+ // 🧹 Güvenlik Bakımı
88
+ private startSecurityMaintenance() {
89
+ // Nonce temizliği (5 dakikadan eski nonce'ları sil)
90
+ this.nonceCleanupInterval = setInterval(() => {
91
+ this.seenNonces.clear();
92
+ }, MESSAGE_MAX_AGE);
93
+
94
+ // Key rotation
95
+ this.keyRotationInterval = setInterval(() => {
96
+ this.rotateKey();
97
+ }, KEY_ROTATION_INTERVAL);
37
98
  }
38
99
 
39
100
  // 2. Terminal (PTY) Başlatma
@@ -69,8 +130,6 @@ export class ZKRelayAgent {
69
130
 
70
131
  // Odaya Katıl (Sadece Hash ID gönderilir)
71
132
  this.socket.emit('join_room', { code: this.roomId, type: 'agent' });
72
- // Note: Changed 'join_secure_room' to 'join_room' to match server implementation
73
- // Server implementation in index.ts: socket.on('join_room', (data: { code: string; type: 'agent' | 'client' }) => ...)
74
133
 
75
134
  this.printBanner();
76
135
  });
@@ -80,34 +139,13 @@ export class ZKRelayAgent {
80
139
  });
81
140
 
82
141
  // Mobilden biri bağlandığında
83
- this.socket.on('peer_joined', () => { // Changed peer_connected to peer_joined based on server impl
142
+ this.socket.on('peer_joined', () => {
84
143
  console.log(chalk.green('\n📱 Mobile Client Connected via Encrypted Tunnel!'));
85
144
  this.sendEnvInfo();
86
145
  });
87
146
 
88
147
  // Mobilden şifreli veri geldiğinde
89
- // RelayManager emits 'term_data' and 'meta_data'.
90
- // Server implementation:
91
- // socket.on('term_data', ...) -> pass through term_data
92
- // socket.on('meta_data', ...) -> pass through meta_data
93
- // Agent connects to /, Server index.ts uses / (global namespace) BUT has:
94
- // const relayNamespace = io.of('/terminal');
95
- // WAIT. Previous user setup had /terminal.
96
- // My previous edit REMOVED /terminal and used RelayManager on root io.
97
- // But RelayManager implementation listens on 'relay_data'.
98
- // My RelayManager uses: socket.on('relay_data', ...)
99
- // But user snippet provided for Agent uses 'relay_encrypted' and listens on 'stream_encrypted'.
100
- // I need to align Agent and Server.
101
- // The previous edit to server/index.ts instantiates RelayManager.
102
- // RelayManager listens to 'relay_data'.
103
- // So the Agent MUST emit 'relay_data'.
104
-
105
148
  this.socket.on('relay_data', (message: { room: string, payload: any }) => {
106
- // RelayManager checks payload structure?
107
- // Wait, RelayManager implementation:
108
- // socket.on('relay_data', (data) => { ... socket.to(room).emit('relay_data', data.payload) ... })
109
- // So client receives `payload`.
110
- // If payload is encrypted string, handle it.
111
149
  this.handleIncomingMessage(message as any);
112
150
  });
113
151
 
@@ -117,68 +155,205 @@ export class ZKRelayAgent {
117
155
  });
118
156
  }
119
157
 
158
+ // 🔐 AES-256-CBC ile Şifreleme (Nonce tabanlı)
159
+ private encrypt(data: string): { nonce: string; data: string; timestamp: number } {
160
+ const nonce = crypto.randomBytes(16);
161
+ const cipher = crypto.createCipheriv('aes-256-cbc', this.sessionKey, nonce);
162
+
163
+ const encrypted = Buffer.concat([
164
+ cipher.update(data, 'utf8'),
165
+ cipher.final()
166
+ ]);
167
+
168
+ return {
169
+ nonce: nonce.toString('base64'),
170
+ data: encrypted.toString('base64'),
171
+ timestamp: Date.now()
172
+ };
173
+ }
174
+
175
+ // 🔐 AES-256-CBC ile Şifre Çözme (Replay Attack Korumalı)
176
+ private decrypt(packet: { nonce: string; data: string; timestamp: number }): string {
177
+ // Timestamp kontrolü (5 dakikadan eski mesajları reddet)
178
+ if (Date.now() - packet.timestamp > MESSAGE_MAX_AGE) {
179
+ throw new Error('Message too old - potential replay attack');
180
+ }
181
+
182
+ // Nonce uniqueness kontrolü (Replay attack önleme)
183
+ if (this.seenNonces.has(packet.nonce)) {
184
+ throw new Error('Replay attack detected - duplicate nonce');
185
+ }
186
+ this.seenNonces.add(packet.nonce);
187
+
188
+ const decipher = crypto.createDecipheriv(
189
+ 'aes-256-cbc',
190
+ this.sessionKey,
191
+ Buffer.from(packet.nonce, 'base64')
192
+ );
193
+
194
+ return Buffer.concat([
195
+ decipher.update(Buffer.from(packet.data, 'base64')),
196
+ decipher.final()
197
+ ]).toString('utf8');
198
+ }
199
+
120
200
  // Gelen veriyi çöz ve işle
121
201
  private handleIncomingMessage(encryptedPayload: any) {
122
202
  try {
123
- // Payload might be wrapped { e: ... } or string
124
- let ciphertext = encryptedPayload;
125
- if (typeof encryptedPayload === 'object' && encryptedPayload.e) {
126
- ciphertext = encryptedPayload.e;
127
- }
203
+ let decryptedText: string;
128
204
 
129
- const bytes = CryptoJS.AES.decrypt(ciphertext, this.encryptionKey);
130
- const originalText = bytes.toString(CryptoJS.enc.Utf8);
205
+ // Yeni format: { nonce, data, timestamp }
206
+ if (typeof encryptedPayload === 'object' && encryptedPayload.nonce) {
207
+ decryptedText = this.decrypt(encryptedPayload);
208
+ }
209
+ // Legacy format: { e: ciphertext } (CryptoJS uyumluluğu)
210
+ else if (typeof encryptedPayload === 'object' && encryptedPayload.e) {
211
+ // Legacy CryptoJS decrypt fallback
212
+ const CryptoJS = require('crypto-js');
213
+ const bytes = CryptoJS.AES.decrypt(encryptedPayload.e, this.secretCode);
214
+ decryptedText = bytes.toString(CryptoJS.enc.Utf8);
215
+ }
216
+ else {
217
+ return;
218
+ }
131
219
 
132
- if (!originalText) return;
220
+ if (!decryptedText) return;
133
221
 
134
222
  // Veri JSON mu? (Resize komutu vs olabilir)
135
223
  try {
136
- const cmd = JSON.parse(originalText);
137
- if (cmd.type === 'resize') {
138
- this.ptyProcess.resize(cmd.cols, cmd.rows);
224
+ const cmd = JSON.parse(decryptedText);
225
+
226
+ // Handle key rotation from peer
227
+ if (cmd.type === 'key_rotation') {
228
+ this.sessionCounter = cmd.counter;
229
+ this.sessionKey = this.deriveSessionKey(this.sessionCounter);
230
+ console.log(chalk.cyan(`🔄 Key synced to session #${this.sessionCounter}`));
139
231
  return;
140
232
  }
233
+
234
+ // 1. Terminal Input (Keystrokes)
141
235
  if (cmd.type === 'input') {
142
236
  this.ptyProcess.write(cmd.data);
143
237
  return;
144
238
  }
145
- // Fallback checks
239
+
240
+ // 2. Terminal Resize
241
+ if (cmd.type === 'resize') {
242
+ this.ptyProcess.resize(cmd.cols, cmd.rows);
243
+ return;
244
+ }
245
+
246
+ // 3. Chat Commands (e.g. "ls -la")
247
+ if (cmd.type === 'command') {
248
+ this.ptyProcess.write(cmd.text + '\r');
249
+ return;
250
+ }
251
+
252
+ // 4. CLI Tool/Button Commands (e.g. "git status")
253
+ if (cmd.type === 'cli_command') {
254
+ this.ptyProcess.write(cmd.command + '\r');
255
+ return;
256
+ }
257
+
258
+ // 5. Tool Calls (File System Access)
259
+ if (cmd.type === 'tool_call') {
260
+ this.handleToolCall(cmd.tool, cmd.data, cmd.id);
261
+ return;
262
+ }
263
+
146
264
  } catch (e) {
147
265
  // JSON değilse saf terminal girdisidir
148
- this.ptyProcess.write(originalText);
266
+ this.ptyProcess.write(decryptedText);
149
267
  }
150
268
  } catch (error) {
151
269
  // Şifre çözülemezse (Yanlış anahtar vb.) sessizce yut
270
+ console.error(chalk.red('Decryption failed:'), (error as Error).message);
271
+ }
272
+ }
273
+
274
+ private async handleToolCall(tool: string, args: any, id: string) {
275
+ try {
276
+ let result: any = null;
277
+
278
+ if (tool === 'list_directory') {
279
+ const dirPath = args.path ? path.resolve(args.path) : process.cwd();
280
+ const entries = await fs.promises.readdir(dirPath, { withFileTypes: true });
281
+
282
+ const files = entries.map(entry => ({
283
+ name: entry.name,
284
+ type: entry.isDirectory() ? 'directory' : 'file',
285
+ size: 0 // Simplification for speed
286
+ }));
287
+
288
+ result = { files };
289
+ }
290
+
291
+ else if (tool === 'read_file') {
292
+ const filePath = path.resolve(args.path);
293
+ const content = await fs.promises.readFile(filePath, 'utf-8');
294
+ result = { content };
295
+ }
296
+ else {
297
+ throw new Error(`Unknown tool: ${tool}`);
298
+ }
299
+
300
+ this.sendSecurePayload('tool_result', {
301
+ id,
302
+ result
303
+ });
304
+
305
+ } catch (error: any) {
306
+ this.sendSecurePayload('tool_result', {
307
+ id,
308
+ error: error.message,
309
+ type: 'error'
310
+ });
152
311
  }
153
312
  }
154
313
 
155
314
  // Veriyi şifrele ve gönder
156
315
  private sendSecurePayload(type: string, data: any) {
157
- let payloadStr = data;
158
- if (type === 'meta') {
316
+ let payloadStr = '';
317
+
318
+ if (type === 'meta' || type === 'tool_result' || type === 'key_rotation') {
159
319
  // Standardize format
160
- payloadStr = JSON.stringify(data);
161
- } else if (type === 'term_data' && typeof data === 'string') {
162
- // Wrap output in { type: 'output', data: ... } for client consistency if client expects JSON
163
- // The Client handles { type: 'output' ... }
164
- payloadStr = JSON.stringify({ type: 'output', data: data });
320
+ if (type === 'tool_result') {
321
+ if (data.type === 'error') {
322
+ payloadStr = JSON.stringify({ ...data });
323
+ } else {
324
+ payloadStr = JSON.stringify({ type: 'result', ...data });
325
+ }
326
+ } else if (type === 'key_rotation') {
327
+ payloadStr = JSON.stringify({ type: 'key_rotation', ...data });
328
+ } else {
329
+ payloadStr = JSON.stringify(data);
330
+ }
331
+ } else if (type === 'term_data') {
332
+ // Wrap output in { type: 'output', data: ... }
333
+ if (typeof data === 'string') {
334
+ payloadStr = JSON.stringify({ type: 'output', data: data });
335
+ } else {
336
+ payloadStr = JSON.stringify(data);
337
+ }
165
338
  }
166
339
 
167
- const encrypted = CryptoJS.AES.encrypt(payloadStr, this.encryptionKey).toString();
340
+ // Fallback if empty (shouldn't happen with above logic)
341
+ if (!payloadStr) payloadStr = JSON.stringify(data);
342
+
343
+ // 🔐 Yeni şifreleme formatı ile gönder
344
+ const encrypted = this.encrypt(payloadStr);
168
345
 
169
- // RelayManager expects 'relay_data' event with { room, payload }
170
- // It emits 'relay_data' with just payload to other peer.
171
346
  this.socket.emit('relay_data', {
172
347
  room: this.roomId,
173
- payload: { e: encrypted }
348
+ payload: encrypted
174
349
  });
175
350
  }
176
351
 
177
352
  private sendEnvInfo() {
178
353
  const info = {
179
- type: 'host_info', // Changed to match client expectation
180
- username: os.userInfo().username, // user -> username
181
- hostname: os.hostname(), // host -> hostname
354
+ type: 'host_info',
355
+ username: os.userInfo().username,
356
+ hostname: os.hostname(),
182
357
  platform: os.platform(),
183
358
  cwd: process.cwd()
184
359
  };
@@ -186,8 +361,9 @@ export class ZKRelayAgent {
186
361
  }
187
362
 
188
363
  private printBanner() {
189
- console.log('\n' + chalk.bgBlue.bold(' MOBILECODER ZK-RELAY v2.0 '));
190
- console.log(chalk.gray('Secure, End-to-End Encrypted Terminal Bridge\n'));
364
+ console.log('\n' + chalk.bgBlue.bold(' MOBILECODER ZK-RELAY v2.1.0 '));
365
+ console.log(chalk.gray('🔐 PBKDF2-SHA256 + AES-256-CBC + Nonce-Based Replay Protection'));
366
+ console.log(chalk.gray('🔄 Perfect Forward Secrecy with 10-min Key Rotation\n'));
191
367
 
192
368
  console.log(chalk.yellow('┌──────────────────────────────────────┐'));
193
369
  console.log(chalk.yellow('│ 🔑 CONNECTION CODE (ENTER ON APP) │'));
@@ -197,4 +373,12 @@ export class ZKRelayAgent {
197
373
  console.log(chalk.yellow('└──────────────────────────────────────┘'));
198
374
  console.log(chalk.cyan('\nWaiting for mobile connection...'));
199
375
  }
376
+
377
+ // Cleanup
378
+ public destroy() {
379
+ if (this.nonceCleanupInterval) clearInterval(this.nonceCleanupInterval);
380
+ if (this.keyRotationInterval) clearInterval(this.keyRotationInterval);
381
+ if (this.socket) this.socket.disconnect();
382
+ if (this.ptyProcess) this.ptyProcess.kill();
383
+ }
200
384
  }