|
|
@ -159,7 +159,7 @@ export const nextDerivationPath = (origDerivPath: string) => { |
|
|
|
}; |
|
|
|
|
|
|
|
// Base64 encoding/decoding utilities for browser
|
|
|
|
function base64ToArrayBuffer(base64: string): Uint8Array { |
|
|
|
export function base64ToArrayBuffer(base64: string): Uint8Array { |
|
|
|
const binaryString = atob(base64); |
|
|
|
const bytes = new Uint8Array(binaryString.length); |
|
|
|
for (let i = 0; i < binaryString.length; i++) { |
|
|
@ -168,7 +168,7 @@ function base64ToArrayBuffer(base64: string): Uint8Array { |
|
|
|
return bytes; |
|
|
|
} |
|
|
|
|
|
|
|
function arrayBufferToBase64(buffer: ArrayBuffer): string { |
|
|
|
export function arrayBufferToBase64(buffer: ArrayBuffer): string { |
|
|
|
const binary = String.fromCharCode(...new Uint8Array(buffer)); |
|
|
|
return btoa(binary); |
|
|
|
} |
|
|
@ -178,7 +178,7 @@ const IV_LENGTH = 12; |
|
|
|
const KEY_LENGTH = 256; |
|
|
|
const ITERATIONS = 100000; |
|
|
|
|
|
|
|
// Encryption helper function
|
|
|
|
// Message encryption helper function, used for onboarding meeting messages
|
|
|
|
export async function encryptMessage(message: string, password: string) { |
|
|
|
const encoder = new TextEncoder(); |
|
|
|
const salt = crypto.getRandomValues(new Uint8Array(SALT_LENGTH)); |
|
|
@ -226,7 +226,7 @@ export async function encryptMessage(message: string, password: string) { |
|
|
|
return btoa(JSON.stringify(result)); |
|
|
|
} |
|
|
|
|
|
|
|
// Decryption helper function
|
|
|
|
// Message decryption helper function, used for onboarding meeting messages
|
|
|
|
export async function decryptMessage(encryptedJson: string, password: string) { |
|
|
|
const decoder = new TextDecoder(); |
|
|
|
const { salt, iv, encrypted } = JSON.parse(atob(encryptedJson)); |
|
|
@ -311,17 +311,17 @@ export async function testMessageEncryptionDecryption() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Simple encryption/decryption using Node's crypto
|
|
|
|
// Simple encryption using Node's crypto, used for the initial encryption of the identity and mnemonic
|
|
|
|
export async function simpleEncrypt( |
|
|
|
text: string, |
|
|
|
secret: string, |
|
|
|
): Promise<string> { |
|
|
|
secret: ArrayBuffer, |
|
|
|
): Promise<ArrayBuffer> { |
|
|
|
const iv = crypto.getRandomValues(new Uint8Array(16)); |
|
|
|
|
|
|
|
// Derive a 256-bit key from the secret using SHA-256
|
|
|
|
const keyData = await crypto.subtle.digest( |
|
|
|
"SHA-256", |
|
|
|
new TextEncoder().encode(secret), |
|
|
|
secret, |
|
|
|
); |
|
|
|
const key = await crypto.subtle.importKey( |
|
|
|
"raw", |
|
|
@ -342,14 +342,15 @@ export async function simpleEncrypt( |
|
|
|
result.set(iv); |
|
|
|
result.set(new Uint8Array(encrypted), iv.length); |
|
|
|
|
|
|
|
return btoa(String.fromCharCode(...result)); |
|
|
|
return result.buffer; |
|
|
|
} |
|
|
|
|
|
|
|
// Simple decryption using Node's crypto, used for the default decryption of identity and mnemonic
|
|
|
|
export async function simpleDecrypt( |
|
|
|
encryptedText: string, |
|
|
|
secret: string, |
|
|
|
encryptedText: ArrayBuffer, |
|
|
|
secret: ArrayBuffer, |
|
|
|
): Promise<string> { |
|
|
|
const data = Uint8Array.from(atob(encryptedText), (c) => c.charCodeAt(0)); |
|
|
|
const data = new Uint8Array(encryptedText); |
|
|
|
|
|
|
|
// Extract IV and encrypted data
|
|
|
|
const iv = data.slice(0, 16); |
|
|
@ -358,7 +359,7 @@ export async function simpleDecrypt( |
|
|
|
// Derive the same 256-bit key from the secret using SHA-256
|
|
|
|
const keyData = await crypto.subtle.digest( |
|
|
|
"SHA-256", |
|
|
|
new TextEncoder().encode(secret), |
|
|
|
secret, |
|
|
|
); |
|
|
|
const key = await crypto.subtle.importKey( |
|
|
|
"raw", |
|
|
@ -381,18 +382,20 @@ export async function simpleDecrypt( |
|
|
|
export async function testSimpleEncryptionDecryption() { |
|
|
|
try { |
|
|
|
const testMessage = "Hello, this is a test message! 🚀"; |
|
|
|
const testSecret = "myTestSecret123"; |
|
|
|
const testSecret = crypto.getRandomValues(new Uint8Array(32)); |
|
|
|
|
|
|
|
logger.log("Original message:", testMessage); |
|
|
|
|
|
|
|
// Test encryption
|
|
|
|
logger.log("Encrypting..."); |
|
|
|
const encrypted = await simpleEncrypt(testMessage, testSecret); |
|
|
|
logger.log("Encrypted result:", encrypted); |
|
|
|
const encryptedBase64 = arrayBufferToBase64(encrypted); |
|
|
|
logger.log("Encrypted result:", encryptedBase64); |
|
|
|
|
|
|
|
// Test decryption
|
|
|
|
logger.log("Decrypting..."); |
|
|
|
const decrypted = await simpleDecrypt(encrypted, testSecret); |
|
|
|
const encryptedArrayBuffer = base64ToArrayBuffer(encryptedBase64); |
|
|
|
const decrypted = await simpleDecrypt(encryptedArrayBuffer, testSecret); |
|
|
|
logger.log("Decrypted result:", decrypted); |
|
|
|
|
|
|
|
// Verify
|
|
|
@ -403,7 +406,7 @@ export async function testSimpleEncryptionDecryption() { |
|
|
|
// Test with wrong secret
|
|
|
|
logger.log("\nTesting with wrong secret..."); |
|
|
|
try { |
|
|
|
await simpleDecrypt(encrypted, "wrongSecret"); |
|
|
|
await simpleDecrypt(encryptedArrayBuffer, new Uint8Array(32)); |
|
|
|
logger.log("Incorrectly decrypted with wrong secret ❌"); |
|
|
|
} catch (error) { |
|
|
|
logger.log("Correctly failed to decrypt with wrong secret ✅"); |
|
|
|