let offlineMode = true; // Set this based on your application's state let currentPublicKey, nextPublicKey; function arrayBufferToBase64(buffer) { let binary = ''; const bytes = new Uint8Array(buffer); for (let i = 0; i < bytes.byteLength; i++) { binary += String.fromCharCode(bytes[i]); } return window.btoa(binary); } function updatePublicKeys() { if (offlineMode) { console.log('Running in offline mode. Skipping public key update.'); return; } // Fetch the current and next public keys from the server const xhr = new XMLHttpRequest(); xhr.open('GET', 'http://localhost:9876/api/getPublicKeys', true); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { const keys = JSON.parse(xhr.responseText); currentPublicKey = keys.currentPublicKey; nextPublicKey = keys.nextPublicKey; } }; xhr.send(); } function encryptWithPublicKey(plaintext, pubKey) { if (offlineMode) { console.log('Running in offline mode. Skipping encryption.'); return Promise.resolve(plaintext); } // Implement RSA encryption with public key // Assuming pubKey is in PEM format const publicKey = new TextEncoder().encode(pubKey); const textBuffer = new TextEncoder().encode(plaintext); return window.crypto.subtle.importKey( 'spki', publicKey, { name: 'RSA-OAEP', hash: 'SHA-256' }, false, ['encrypt'] ).then(key => { return window.crypto.subtle.encrypt( { name: 'RSA-OAEP' }, key, textBuffer ); }).then(encrypted => { return arrayBufferToBase64(encrypted); }); } function sendMessage() { const xhr = new XMLHttpRequest(); const message = { text: 'Hello, server!' }; // Encrypt the message using the server's public key encryptWithPublicKey(message.text, currentPublicKey).then(encryptedMessage => { xhr.open('POST', 'http://localhost:9876/api/sendMessage', true); xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { console.log('Message sent successfully:', xhr.responseText); } }; xhr.send(JSON.stringify({text: encryptedMessage})); }); } function addMessageToChat(message, sender) { const chatWindow = document.getElementById('chat-window'); const messageDiv = document.createElement('div'); messageDiv.className = sender; // 'user' or 'server' messageDiv.textContent = message; chatWindow.appendChild(messageDiv); } function pollForMessages() { if (offlineMode) { console.log('Running in offline mode. Skipping message polling.'); return; } const xhr = new XMLHttpRequest(); xhr.open('GET', 'http://localhost:9876/api/receiveMessage', true); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { const receivedMsg = JSON.parse(xhr.responseText); addMessageToChat(receivedMsg.text, 'server'); } }; xhr.send(); } // Start polling for messages if (!offlineMode) { setInterval(pollForMessages, 2000); // Poll every 2 seconds } function main() { if (!offlineMode) { updatePublicKeys(); // Before joining the channel setInterval(updatePublicKeys, 5 * 60 * 1000); // Check for new keys every 5 minutes } }