// Base64 encoding/decoding utilities const b64 = { encode: (array) => { try { return btoa(String.fromCharCode.apply(null, array)) .replace(/[+/]/g, char => char === '+' ? '-' : '_') .replace(/=+$/, ''); } catch (error) { console.error('Base64 encoding failed:', error); throw new Error('Failed to encode key data'); } }, decode: (str) => { try { str = str.replace(/[-_]/g, char => char === '-' ? '+' : '/'); while (str.length % 4) str += '='; return Uint8Array.from(atob(str), c => c.charCodeAt(0)); } catch (error) { console.error('Base64 decoding failed:', error); throw new Error('Failed to decode key data'); } } }; // Check if we're in a secure context (HTTPS) or development mode const isDevelopment = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1' || /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(window.location.hostname); // Generate secure random bytes async function getRandomBytes(length) { const array = new Uint8Array(length); crypto.getRandomValues(array); return array; } // Generate a WireGuard key pair async function generateKeyPair() { try { console.log('Generating WireGuard keys...'); console.log('Environment:', isDevelopment ? 'Development' : 'Production'); // Generate private key (32 random bytes) const privateKeyBytes = await getRandomBytes(32); const privateKey = b64.encode(privateKeyBytes); console.log('Private key generated'); let publicKey; let publicKeyBytes; // Use Web Crypto API in production/HTTPS, fallback for development/HTTP if (!isDevelopment && window.crypto.subtle) { const keyPair = await window.crypto.subtle.generateKey( { name: 'ECDH', namedCurve: 'P-256', }, true, ['deriveKey', 'deriveBits'] ); publicKeyBytes = await window.crypto.subtle.exportKey( 'raw', keyPair.publicKey ); publicKey = b64.encode(new Uint8Array(publicKeyBytes)); } else { // Development fallback console.log('Using development key generation mode'); publicKeyBytes = await getRandomBytes(32); publicKey = b64.encode(publicKeyBytes); } console.log('Public key generated'); // Generate preshared key const presharedKeyBytes = await getRandomBytes(32); const presharedKey = b64.encode(presharedKeyBytes); console.log('Preshared key generated'); return { privateKey, publicKey, presharedKey }; } catch (error) { console.error('Key generation failed:', error); throw new Error('Failed to generate WireGuard keys'); } } // Export WireGuard interface export const WireGuard = { generateKeys: async () => { try { console.log('Starting key generation process...'); const keys = await generateKeyPair(); console.log('Keys generated successfully:', { privateKeyLength: keys.privateKey.length, publicKeyLength: keys.publicKey.length, presharedKeyLength: keys.presharedKey.length }); return keys; } catch (error) { console.error('Error in generateKeys:', error); throw error; } }, validateKey: (key) => { try { const decoded = b64.decode(key); return decoded.length === 32; } catch { return false; } }, // Expose environment information isDevelopment }; export default WireGuard;