From 91d4e77a482fdf3c83b43c246a6206196c2dc839 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 12 Apr 2026 19:57:30 +0300 Subject: [PATCH] chore(standalone): remove async encryption --- .../src/services/encryption/crypto.ts | 2 - .../services/encryption/data_encryption.ts | 112 +----------------- .../encryption/password_encryption.ts | 4 +- .../src/services/protected_session.ts | 29 ----- 4 files changed, 3 insertions(+), 144 deletions(-) diff --git a/packages/trilium-core/src/services/encryption/crypto.ts b/packages/trilium-core/src/services/encryption/crypto.ts index 150eafedc3..809c131acf 100644 --- a/packages/trilium-core/src/services/encryption/crypto.ts +++ b/packages/trilium-core/src/services/encryption/crypto.ts @@ -1,8 +1,6 @@ export interface Cipher { update(data: Uint8Array): Uint8Array; final(): Uint8Array; - /** Async finalization for browser environments where Web Crypto API is async-only */ - finalizeAsync?(): Promise; } export interface ScryptOptions { diff --git a/packages/trilium-core/src/services/encryption/data_encryption.ts b/packages/trilium-core/src/services/encryption/data_encryption.ts index 2280c62446..ffae2c1e9d 100644 --- a/packages/trilium-core/src/services/encryption/data_encryption.ts +++ b/packages/trilium-core/src/services/encryption/data_encryption.ts @@ -108,118 +108,8 @@ function decryptString(dataKey: Uint8Array, cipherText: string) { return decodeUtf8(buffer); } -/** - * Async version of encrypt that works in both Node.js and browser environments. - * Uses finalizeAsync() for browser compatibility when available. - */ -async function encryptAsync(key: Uint8Array, plainText: Uint8Array | string): Promise { - if (!key) { - throw new Error("No data key!"); - } - - const plainTextUint8Array = ArrayBuffer.isView(plainText) ? plainText : encodeUtf8(plainText); - - const iv = getCrypto().randomBytes(16); - const cipher = getCrypto().createCipheriv("aes-128-cbc", pad(key), pad(iv)); - - const digest = shaArray(plainTextUint8Array).slice(0, 4); - const digestWithPayload = concat2(digest, plainTextUint8Array); - - // Use async finalization if available (browser), otherwise sync (Node.js) - let encryptedData: Uint8Array; - if (cipher.finalizeAsync) { - // Browser: update() buffers data, finalizeAsync() encrypts and returns all - cipher.update(digestWithPayload); - encryptedData = await cipher.finalizeAsync(); - } else { - // Node.js: update() and final() both return encrypted chunks - encryptedData = concat2(cipher.update(digestWithPayload), cipher.final()); - } - - const encryptedDataWithIv = concat2(iv, encryptedData); - - return encodeBase64(encryptedDataWithIv); -} - -/** - * Async version of decrypt that works in both Node.js and browser environments. - * Uses finalizeAsync() for browser compatibility when available. - */ -async function decryptAsync(key: Uint8Array, cipherText: string | Uint8Array): Promise { - if (cipherText === null) { - return null; - } - - if (!key) { - return encodeUtf8("[protected]"); - } - - try { - const cipherTextStr = typeof cipherText === "string" ? cipherText : decodeUtf8(cipherText); - const cipherTextUint8ArrayWithIv = decodeBase64(cipherTextStr); - - // old encrypted data can have IV of length 13, see some details here: https://github.com/zadam/trilium/issues/3017 - const ivLength = cipherTextUint8ArrayWithIv.length % 16 === 0 ? 16 : 13; - - const iv = cipherTextUint8ArrayWithIv.slice(0, ivLength); - const cipherTextUint8Array = cipherTextUint8ArrayWithIv.slice(ivLength); - - const decipher = getCrypto().createDecipheriv("aes-128-cbc", pad(key), pad(iv)); - - // Use async finalization if available (browser), otherwise sync (Node.js) - let decryptedBytes: Uint8Array; - if (decipher.finalizeAsync) { - // Browser: update() buffers data, finalizeAsync() decrypts and returns all - decipher.update(cipherTextUint8Array); - decryptedBytes = await decipher.finalizeAsync(); - } else { - // Node.js: update() and final() both return decrypted chunks - decryptedBytes = concat2(decipher.update(cipherTextUint8Array), decipher.final()); - } - - const digest = decryptedBytes.slice(0, 4); - const payload = decryptedBytes.slice(4); - - const computedDigest = shaArray(payload).slice(0, 4); - - if (!arraysIdentical(digest, computedDigest)) { - return false; - } - - return payload; - } catch (e: any) { - // recovery from https://github.com/zadam/trilium/issues/510 - if (e.message?.includes("WRONG_FINAL_BLOCK_LENGTH") || e.message?.includes("wrong final block length")) { - getLog().info("Caught WRONG_FINAL_BLOCK_LENGTH, returning cipherText instead"); - - return (ArrayBuffer.isView(cipherText) ? cipherText : Uint8Array.from(cipherText)); - } - throw e; - } -} - -/** - * Async version of decryptString that works in both Node.js and browser environments. - */ -async function decryptStringAsync(dataKey: Uint8Array, cipherText: string): Promise { - const buffer = await decryptAsync(dataKey, cipherText); - - if (buffer === null) { - return null; - } else if (buffer === false) { - getLog().error(`Could not decrypt string. Uint8Array: ${buffer}`); - - throw new Error("Could not decrypt string."); - } - - return decodeUtf8(buffer); -} - export default { encrypt, decrypt, - decryptString, - encryptAsync, - decryptAsync, - decryptStringAsync + decryptString }; diff --git a/packages/trilium-core/src/services/encryption/password_encryption.ts b/packages/trilium-core/src/services/encryption/password_encryption.ts index f027ea494d..9b9062e8d8 100644 --- a/packages/trilium-core/src/services/encryption/password_encryption.ts +++ b/packages/trilium-core/src/services/encryption/password_encryption.ts @@ -31,7 +31,7 @@ export async function setDataKey( plainTextDataKey: string | Uint8Array ): Promise { const passwordDerivedKey = await scryptService.getPasswordDerivedKey(password); - const newEncryptedDataKey = await data_encryption.encryptAsync(passwordDerivedKey, plainTextDataKey); + const newEncryptedDataKey = data_encryption.encrypt(passwordDerivedKey, plainTextDataKey); options.setOption("encryptedDataKey", newEncryptedDataKey); } @@ -41,7 +41,7 @@ export async function setDataKey( export async function getDataKey(password: string): Promise { const passwordDerivedKey = await scryptService.getPasswordDerivedKey(password); const encryptedDataKey = options.getOption("encryptedDataKey"); - return data_encryption.decryptAsync(passwordDerivedKey, encryptedDataKey); + return data_encryption.decrypt(passwordDerivedKey, encryptedDataKey); } export default { diff --git a/packages/trilium-core/src/services/protected_session.ts b/packages/trilium-core/src/services/protected_session.ts index da59875241..f336fbccc4 100644 --- a/packages/trilium-core/src/services/protected_session.ts +++ b/packages/trilium-core/src/services/protected_session.ts @@ -29,15 +29,6 @@ function encrypt(plainText: string | Uint8Array) { return dataEncryptionService.encrypt(dataKey, plainText); } -async function encryptAsync(plainText: string | Uint8Array): Promise { - const dataKey = getDataKey(); - if (plainText === null || dataKey === null) { - return null; - } - - return dataEncryptionService.encryptAsync(dataKey, plainText); -} - function decrypt(cipherText: string | Uint8Array): Uint8Array | null { const dataKey = getDataKey(); if (cipherText === null || dataKey === null) { @@ -47,15 +38,6 @@ function decrypt(cipherText: string | Uint8Array): Uint8Array | null { return dataEncryptionService.decrypt(dataKey, cipherText) || null; } -async function decryptAsync(cipherText: string | Uint8Array): Promise { - const dataKey = getDataKey(); - if (cipherText === null || dataKey === null) { - return null; - } - - return (await dataEncryptionService.decryptAsync(dataKey, cipherText)) || null; -} - function decryptString(cipherText: string): string | null { const dataKey = getDataKey(); if (dataKey === null) { @@ -64,14 +46,6 @@ function decryptString(cipherText: string): string | null { return dataEncryptionService.decryptString(dataKey, cipherText); } -async function decryptStringAsync(cipherText: string): Promise { - const dataKey = getDataKey(); - if (dataKey === null) { - return null; - } - return dataEncryptionService.decryptStringAsync(dataKey, cipherText); -} - let lastProtectedSessionOperationDate: number | null = null; function touchProtectedSession() { @@ -89,11 +63,8 @@ export default { resetDataKey, isProtectedSessionAvailable, encrypt, - encryptAsync, decrypt, - decryptAsync, decryptString, - decryptStringAsync, touchProtectedSession, getLastProtectedSessionOperationDate };