117 lines
3.8 KiB
JavaScript
117 lines
3.8 KiB
JavaScript
// 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; |