sal-modular/crypto_vault_extension/demo/mock_sigsocket_server.js
Sameh Abouel-saad 580fd72dce feat: Implement Sign Request Manager component for handling sign requests in the popup (WIP)
- Added SignRequestManager.js to manage sign requests, including UI states for keyspace lock, mismatch, and approval.
- Implemented methods for loading state, rendering UI, and handling user interactions (approve/reject requests).
- Integrated background message listeners for keyspace unlock events and request updates.
2025-06-04 16:55:15 +03:00

233 lines
7.2 KiB
JavaScript

#!/usr/bin/env node
/**
* Mock SigSocket Server for Testing Browser Extension
*
* This is a simple WebSocket server that simulates the SigSocket protocol
* for testing the browser extension functionality.
*
* Usage:
* node mock_sigsocket_server.js
*
* The server will listen on ws://localhost:8080/ws
*/
const WebSocket = require('ws');
const http = require('http');
class MockSigSocketServer {
constructor(port = 8080) {
this.port = port;
this.clients = new Map(); // clientId -> { ws, publicKey }
this.requestCounter = 0;
this.setupServer();
}
setupServer() {
// Create HTTP server
this.httpServer = http.createServer();
// Create WebSocket server
this.wss = new WebSocket.Server({
server: this.httpServer,
path: '/ws'
});
this.wss.on('connection', (ws, req) => {
console.log('New WebSocket connection from:', req.socket.remoteAddress);
this.handleConnection(ws);
});
this.httpServer.listen(this.port, () => {
console.log(`Mock SigSocket Server listening on ws://localhost:${this.port}/ws`);
console.log('Waiting for browser extension connections...');
});
}
handleConnection(ws) {
let clientId = null;
let publicKey = null;
ws.on('message', (data) => {
try {
const message = data.toString();
console.log('Received message:', message);
// Check if this is a client introduction (hex-encoded public key)
if (!clientId && this.isHexString(message)) {
publicKey = message;
clientId = this.generateClientId();
this.clients.set(clientId, { ws, publicKey });
console.log(`Client registered: ${clientId} with public key: ${publicKey.substring(0, 16)}...`);
// Send welcome message
ws.send(JSON.stringify({
type: 'welcome',
clientId: clientId,
message: 'Connected to Mock SigSocket Server'
}));
// Schedule a test sign request after 3 seconds
setTimeout(() => {
this.sendTestSignRequest(clientId);
}, 3000);
return;
}
// Try to parse as JSON (sign response)
try {
const jsonMessage = JSON.parse(message);
this.handleSignResponse(clientId, jsonMessage);
} catch (e) {
console.log('Received non-JSON message:', message);
}
} catch (error) {
console.error('Error handling message:', error);
}
});
ws.on('close', () => {
if (clientId) {
this.clients.delete(clientId);
console.log(`Client disconnected: ${clientId}`);
}
});
ws.on('error', (error) => {
console.error('WebSocket error:', error);
});
}
handleSignResponse(clientId, response) {
console.log(`Received sign response from ${clientId}:`, response);
if (response.id && response.signature) {
console.log(`✅ Sign request ${response.id} completed successfully`);
console.log(` Signature: ${response.signature.substring(0, 32)}...`);
// Send another test request after 10 seconds
setTimeout(() => {
this.sendTestSignRequest(clientId);
}, 10000);
} else {
console.log('❌ Invalid sign response format');
}
}
sendTestSignRequest(clientId) {
const client = this.clients.get(clientId);
if (!client) {
console.log(`Client ${clientId} not found`);
return;
}
this.requestCounter++;
const requestId = `req_${this.requestCounter}_${Date.now()}`;
const testMessage = `Test message ${this.requestCounter} - ${new Date().toISOString()}`;
const messageBase64 = Buffer.from(testMessage).toString('base64');
const signRequest = {
id: requestId,
message: messageBase64
};
console.log(`📝 Sending sign request to ${clientId}:`, requestId);
console.log(` Message: "${testMessage}"`);
try {
client.ws.send(JSON.stringify(signRequest));
} catch (error) {
console.error(`Failed to send sign request to ${clientId}:`, error);
}
}
isHexString(str) {
return /^[0-9a-fA-F]+$/.test(str) && str.length >= 32; // At least 16 bytes
}
generateClientId() {
return `client_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
}
// Send a test request to all connected clients
broadcastTestRequest() {
console.log('\n📢 Broadcasting test sign request to all clients...');
for (const [clientId] of this.clients) {
this.sendTestSignRequest(clientId);
}
}
// Get server status
getStatus() {
return {
port: this.port,
connectedClients: this.clients.size,
clients: Array.from(this.clients.keys())
};
}
}
// Create and start the server
const server = new MockSigSocketServer();
// Handle graceful shutdown
process.on('SIGINT', () => {
console.log('\n🛑 Shutting down Mock SigSocket Server...');
server.httpServer.close(() => {
console.log('Server closed');
process.exit(0);
});
});
// Add some interactive commands
process.stdin.setEncoding('utf8');
console.log('\n📋 Available commands:');
console.log(' "test" - Send test sign request to all clients');
console.log(' "status" - Show server status');
console.log(' "quit" - Shutdown server');
console.log(' Type a command and press Enter\n');
process.stdin.on('readable', () => {
const chunk = process.stdin.read();
if (chunk !== null) {
const command = chunk.trim().toLowerCase();
switch (command) {
case 'test':
server.broadcastTestRequest();
break;
case 'status':
const status = server.getStatus();
console.log('\n📊 Server Status:');
console.log(` Port: ${status.port}`);
console.log(` Connected clients: ${status.connectedClients}`);
if (status.clients.length > 0) {
console.log(` Client IDs: ${status.clients.join(', ')}`);
}
console.log('');
break;
case 'quit':
case 'exit':
process.emit('SIGINT');
break;
case '':
break;
default:
console.log(`Unknown command: ${command}`);
break;
}
}
});
// Export for testing
module.exports = MockSigSocketServer;