New
This commit is contained in:
@@ -37,13 +37,14 @@ import {
|
||||
import { LinkButton } from "ente-base/components/LinkButton";
|
||||
import { LoadingIndicator } from "ente-base/components/loaders";
|
||||
import { useBaseContext } from "ente-base/context";
|
||||
import { sharedCryptoWorker } from "ente-base/crypto";
|
||||
import type { B64EncryptionResult } from "ente-base/crypto/libsodium";
|
||||
import { decryptBox } from "ente-base/crypto";
|
||||
import { clearLocalStorage } from "ente-base/local-storage";
|
||||
import log from "ente-base/log";
|
||||
import {
|
||||
haveAuthenticatedSession,
|
||||
saveMasterKeyInSessionAndSafeStore,
|
||||
stashKeyEncryptionKeyInSessionStore,
|
||||
unstashKeyEncryptionKeyFromSession,
|
||||
updateSessionFromElectronSafeStorageIfNeeded,
|
||||
} from "ente-base/session";
|
||||
import { CustomError } from "ente-shared/error";
|
||||
@@ -53,7 +54,6 @@ import {
|
||||
isFirstLogin,
|
||||
setIsFirstLogin,
|
||||
} from "ente-shared/storage/localStorage/helpers";
|
||||
import { getKey, removeKey, setKey } from "ente-shared/storage/sessionStorage";
|
||||
import { t } from "i18next";
|
||||
import { useRouter } from "next/router";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
@@ -120,8 +120,7 @@ const Page: React.FC = () => {
|
||||
void router.push(appHomeRoute);
|
||||
return;
|
||||
}
|
||||
const kekEncryptedAttributes: B64EncryptionResult =
|
||||
getKey("keyEncryptionKey");
|
||||
const kek = await unstashKeyEncryptionKeyFromSession();
|
||||
const keyAttributes: KeyAttributes = getData("keyAttributes");
|
||||
const srpAttributes: SRPAttributes = getData("srpAttributes");
|
||||
|
||||
@@ -129,26 +128,18 @@ const Page: React.FC = () => {
|
||||
setSessionValidityCheck(validateSession());
|
||||
}
|
||||
|
||||
if (kekEncryptedAttributes && keyAttributes) {
|
||||
removeKey("keyEncryptionKey");
|
||||
const cryptoWorker = await sharedCryptoWorker();
|
||||
const kek = await cryptoWorker.decryptBox(
|
||||
{
|
||||
encryptedData: kekEncryptedAttributes.encryptedData,
|
||||
nonce: kekEncryptedAttributes.nonce,
|
||||
},
|
||||
kekEncryptedAttributes.key,
|
||||
);
|
||||
const key = await cryptoWorker.decryptBox(
|
||||
if (kek && keyAttributes) {
|
||||
const masterKey = await decryptBox(
|
||||
{
|
||||
encryptedData: keyAttributes.encryptedKey,
|
||||
nonce: keyAttributes.keyDecryptionNonce,
|
||||
},
|
||||
kek,
|
||||
);
|
||||
void postVerification(key, kek, keyAttributes);
|
||||
void postVerification(masterKey, kek, keyAttributes);
|
||||
return;
|
||||
}
|
||||
|
||||
if (keyAttributes) {
|
||||
if (
|
||||
(!user?.token && !user?.encryptedToken) ||
|
||||
@@ -184,7 +175,6 @@ const Page: React.FC = () => {
|
||||
// before we let the user in.
|
||||
if (sessionValidityCheck) await sessionValidityCheck;
|
||||
|
||||
const cryptoWorker = await sharedCryptoWorker();
|
||||
const {
|
||||
keyAttributes,
|
||||
encryptedToken,
|
||||
@@ -200,9 +190,7 @@ const Page: React.FC = () => {
|
||||
setIsFirstLogin(true);
|
||||
|
||||
if (passkeySessionID) {
|
||||
const sessionKeyAttributes =
|
||||
await cryptoWorker.generateKeyAndEncryptToB64(kek);
|
||||
setKey("keyEncryptionKey", sessionKeyAttributes);
|
||||
await stashKeyEncryptionKeyInSessionStore(kek);
|
||||
const user = getData("user");
|
||||
await setLSUser({
|
||||
...user,
|
||||
@@ -219,9 +207,7 @@ const Page: React.FC = () => {
|
||||
openPasskeyVerificationURL({ passkeySessionID, url });
|
||||
throw Error(CustomError.TWO_FACTOR_ENABLED);
|
||||
} else if (twoFactorSessionID) {
|
||||
const sessionKeyAttributes =
|
||||
await cryptoWorker.generateKeyAndEncryptToB64(kek);
|
||||
setKey("keyEncryptionKey", sessionKeyAttributes);
|
||||
await stashKeyEncryptionKeyInSessionStore(kek);
|
||||
const user = getData("user");
|
||||
await setLSUser({
|
||||
...user,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getToken } from "ente-shared/storage/localStorage/helpers";
|
||||
import { z } from "zod/v4";
|
||||
import { decryptBox, decryptBoxBytes, encryptBox, generateKey } from "./crypto";
|
||||
import { decryptBox, encryptBox, generateKey } from "./crypto";
|
||||
import { isDevBuild } from "./env";
|
||||
import log from "./log";
|
||||
import { getAuthToken } from "./token";
|
||||
@@ -63,7 +63,6 @@ export const haveCredentialsInSession = () =>
|
||||
* See also {@link ensureMasterKeyFromSession}, which is usually what we need.
|
||||
*/
|
||||
export const masterKeyFromSession = async () => {
|
||||
// TODO: Same value as the deprecated getKey("encryptionKey")
|
||||
const value = sessionStorage.getItem("encryptionKey");
|
||||
if (!value) return undefined;
|
||||
|
||||
@@ -139,8 +138,6 @@ export const updateSessionFromElectronSafeStorageIfNeeded = async () => {
|
||||
log.error("Failed to read master key from safe storage", e);
|
||||
}
|
||||
if (masterKey) {
|
||||
// Do not use `saveMasterKeyInSessionStore`, that will (unnecessarily)
|
||||
// overwrite the OS safe storage again.
|
||||
await saveKeyInSessionStore("encryptionKey", masterKey);
|
||||
}
|
||||
};
|
||||
@@ -178,6 +175,10 @@ export const stashKeyEncryptionKeyInSessionStore = (kek: string) =>
|
||||
* Return the decrypted user's key encryption key ("kek") from session storage
|
||||
* if present, otherwise return `undefined`.
|
||||
*
|
||||
* The key (if it was present) is also removed from session storage.
|
||||
*
|
||||
* @returns the previously stashed key (if any) as a base64 string.
|
||||
*
|
||||
* [Note: Stashing KEK in session store]
|
||||
*
|
||||
* During login, if the user has set a second factor (passkey or TOTP), then we
|
||||
@@ -187,11 +188,10 @@ export const stashKeyEncryptionKeyInSessionStore = (kek: string) =>
|
||||
* second factor redirect can happen to a separate accounts app altogether.
|
||||
*
|
||||
* So instead, we stash the encrypted kek in session store (using
|
||||
* {@link stashKeyEncryptionKeyInSessionStore}), and after redirect, retrieve
|
||||
* it (after clearing it) using {@link unstashKeyEncryptionKeyFromSession}.
|
||||
* {@link stashKeyEncryptionKeyInSessionStore}), and after redirect, retrieve it
|
||||
* (after clearing it) using {@link unstashKeyEncryptionKeyFromSession}.
|
||||
*/
|
||||
export const unstashKeyEncryptionKeyFromSession = async () => {
|
||||
// TODO: Same value as the deprecated getKey("keyEncryptionKey")
|
||||
const value = sessionStorage.getItem("keyEncryptionKey");
|
||||
if (!value) return undefined;
|
||||
|
||||
@@ -200,5 +200,5 @@ export const unstashKeyEncryptionKeyFromSession = async () => {
|
||||
const { encryptedData, key, nonce } = SessionKeyData.parse(
|
||||
JSON.parse(value),
|
||||
);
|
||||
return decryptBoxBytes({ encryptedData, nonce }, key);
|
||||
return decryptBox({ encryptedData, nonce }, key);
|
||||
};
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
export type SessionKey = "encryptionKey" | "keyEncryptionKey";
|
||||
|
||||
export const setKey = (key: SessionKey, value: object) =>
|
||||
sessionStorage.setItem(key, JSON.stringify(value));
|
||||
|
||||
export const getKey = (key: SessionKey) => {
|
||||
const value = sessionStorage.getItem(key);
|
||||
return value && JSON.parse(value);
|
||||
};
|
||||
|
||||
export const removeKey = (key: SessionKey) => sessionStorage.removeItem(key);
|
||||
Reference in New Issue
Block a user