add encryption & decryption for the sensitive identity & mnemonic in SQL DB

This commit is contained in:
2025-05-26 22:42:20 -06:00
parent 4d35760a65
commit fe77dbdcdd
8 changed files with 105 additions and 48 deletions

View File

@@ -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 ✅");