diff --git a/web/packages/accounts/services/user.ts b/web/packages/accounts/services/user.ts index 1cd6e67766..602b67e979 100644 --- a/web/packages/accounts/services/user.ts +++ b/web/packages/accounts/services/user.ts @@ -59,10 +59,13 @@ export const ensureLocalUser = (): LocalUser => ensureExpectedLoggedInValue(localUser()); /** - * A helper function that throws an error if a value that is expected to be - * truthy when the user is logged in is instead falsey. + * A function throws an error if a value that is expected to be truthy when the + * user is logged in is instead falsey. + * + * This is meant as a convenience wrapper to assert that a value we expect when + * the user is logged in is indeed there. */ -const ensureExpectedLoggedInValue = (t: T | undefined): T => { +export const ensureExpectedLoggedInValue = (t: T | undefined): T => { if (!t) throw new Error("Not logged in"); return t; }; diff --git a/web/packages/base/crypto/index.ts b/web/packages/base/crypto/index.ts index 9de7798a0f..b09d12fca5 100644 --- a/web/packages/base/crypto/index.ts +++ b/web/packages/base/crypto/index.ts @@ -441,7 +441,7 @@ export const boxSealOpen = ( export const boxSealOpenBytes = ( encryptedData: string, keyPair: KeyPair, -): Promise => +): Promise => inWorker() ? ei._boxSealOpenBytes(encryptedData, keyPair) : sharedWorker().then((w) => diff --git a/web/packages/base/crypto/libsodium.ts b/web/packages/base/crypto/libsodium.ts index f629106607..906e8246b7 100644 --- a/web/packages/base/crypto/libsodium.ts +++ b/web/packages/base/crypto/libsodium.ts @@ -767,7 +767,7 @@ export const boxSeal = async (data: string, publicKey: string) => { export const boxSealOpenBytes = async ( encryptedData: string, { publicKey, privateKey }: KeyPair, -) => { +): Promise => { await sodium.ready; return sodium.crypto_box_seal_open( await fromB64(encryptedData), diff --git a/web/packages/new/photos/services/user.ts b/web/packages/new/photos/services/user.ts index 2f63f0ea53..bd8634dce7 100644 --- a/web/packages/new/photos/services/user.ts +++ b/web/packages/new/photos/services/user.ts @@ -1,11 +1,25 @@ import { ensureSavedKeyAttributes } from "ente-accounts/services/user"; -import { sharedCryptoWorker } from "ente-base/crypto"; +import { boxSealOpenBytes, decryptBox } from "ente-base/crypto"; +import type { KeyPair } from "ente-base/crypto/types"; import { authenticatedRequestHeaders, ensureOk } from "ente-base/http"; import { apiURL } from "ente-base/origins"; import { ensureMasterKeyFromSession } from "ente-base/session"; import { nullToUndefined } from "ente-utils/transform"; import { z } from "zod/v4"; +/** + * Return the public/private keypair of the currently logged in user. + */ +export const ensureUserKeyPair = async (): Promise => { + const { encryptedSecretKey, secretKeyDecryptionNonce, publicKey } = + ensureSavedKeyAttributes(); + const privateKey = await decryptBox( + { encryptedData: encryptedSecretKey, nonce: secretKeyDecryptionNonce }, + await ensureMasterKeyFromSession(), + ); + return { publicKey, privateKey }; +}; + /** * Fetch the public key from remote for the user (if any) who has registered * with remote with the given {@link email}. @@ -84,25 +98,10 @@ export const getAccountDeleteChallenge = async () => { */ export const decryptDeleteAccountChallenge = async ( encryptedChallenge: string, -) => { - const cryptoWorker = await sharedCryptoWorker(); - const masterKey = await ensureMasterKeyFromSession(); - const keyAttributes = ensureSavedKeyAttributes(); - const secretKey = await cryptoWorker.decryptBox( - { - encryptedData: keyAttributes.encryptedSecretKey, - nonce: keyAttributes.secretKeyDecryptionNonce, - }, - masterKey, +) => + new TextDecoder().decode( + await boxSealOpenBytes(encryptedChallenge, await ensureUserKeyPair()), ); - const b64DecryptedChallenge = await cryptoWorker.boxSealOpen( - encryptedChallenge, - keyAttributes.publicKey, - secretKey, - ); - const utf8DecryptedChallenge = atob(b64DecryptedChallenge); - return utf8DecryptedChallenge; -}; /** * Delete the logged in user's account on remote.