// Base64 encoding/decoding utilities with error handling const b64 = { encode: (array) => { try { return btoa(String.fromCharCode.apply(null, array)); } catch (error) { console.error('Base64 encoding failed:', error); throw new Error('Failed to encode key data'); } }, decode: (str) => { try { 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'); } } }; // Key storage management const keyStorage = { store: (userId, keyData) => { try { const data = { privateKey: keyData.privateKey, publicKey: keyData.publicKey, createdAt: new Date().toISOString() }; localStorage.setItem(`vpn_keys_${userId}`, JSON.stringify(data)); } catch (error) { console.error('Failed to store keys:', error); throw new Error('Failed to save key data'); } }, retrieve: (userId) => { try { const data = localStorage.getItem(`vpn_keys_${userId}`); return data ? JSON.parse(data) : null; } catch (error) { console.error('Failed to retrieve keys:', error); throw new Error('Failed to retrieve key data'); } }, remove: (userId) => { try { localStorage.removeItem(`vpn_keys_${userId}`); } catch (error) { console.error('Failed to remove keys:', error); } } }; // Main key generation function async function generateKeyPair() { try { const keyPair = await window.crypto.subtle.generateKey( { name: 'X25519', namedCurve: 'X25519', }, true, ['deriveKey', 'deriveBits'] ); const privateKey = await window.crypto.subtle.exportKey('raw', keyPair.privateKey); const publicKey = await window.crypto.subtle.exportKey('raw', keyPair.publicKey); return { privateKey: b64.encode(new Uint8Array(privateKey)), publicKey: b64.encode(new Uint8Array(publicKey)) }; } catch (error) { console.error('Key generation failed:', error); throw new Error('Failed to generate WireGuard keys'); } } // Key validation function function validateKey(key) { try { const decoded = b64.decode(key); return decoded.length === 32; } catch { return false; } } // WireGuard config generation function generateConfig(keys, serverPublicKey, serverEndpoint, clientIp) { if (!keys || !serverPublicKey || !serverEndpoint || !clientIp) { throw new Error('Missing required configuration parameters'); } return `[Interface] PrivateKey = ${keys.privateKey} Address = ${clientIp}/24 DNS = 1.1.1.1 [Peer] PublicKey = ${serverPublicKey} Endpoint = ${serverEndpoint}:51820 AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25`; } // Main interface for key management export const WireGuard = { generateKeys: async () => { return await generateKeyPair(); }, saveKeys: (userId, keyPair) => { if (!validateKey(keyPair.publicKey) || !validateKey(keyPair.privateKey)) { throw new Error('Invalid key data'); } keyStorage.store(userId, keyPair); }, getKeys: (userId) => { return keyStorage.retrieve(userId); }, removeKeys: (userId) => { keyStorage.remove(userId); }, generateConfig, validateKey }; export default WireGuard;