Merge branch 'main' into download-album
This commit is contained in:
commit
22b170399f
|
@ -16,9 +16,9 @@ export interface VerifyMasterPasswordFormProps {
|
|||
keyAttributes: KeyAttributes;
|
||||
callback: (
|
||||
key: string,
|
||||
passphrase: string,
|
||||
kek: string,
|
||||
keyAttributes: KeyAttributes
|
||||
keyAttributes: KeyAttributes,
|
||||
passphrase?: string
|
||||
) => void;
|
||||
buttonText: string;
|
||||
submitButtonProps?: ButtonProps;
|
||||
|
@ -74,12 +74,17 @@ export default function VerifyMasterPasswordForm({
|
|||
keyAttributes.keyDecryptionNonce,
|
||||
kek
|
||||
);
|
||||
callback(key, passphrase, kek, keyAttributes);
|
||||
callback(key, kek, keyAttributes, passphrase);
|
||||
} catch (e) {
|
||||
logError(e, 'user entered a wrong password');
|
||||
throw Error(CustomError.INCORRECT_PASSWORD);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.message === CustomError.TWO_FACTOR_ENABLED) {
|
||||
// two factor enabled, user has been redirected to two factor page
|
||||
return;
|
||||
}
|
||||
logError(e, 'failed to verify passphrase');
|
||||
switch (e.message) {
|
||||
case CustomError.WEAK_DEVICE:
|
||||
setFieldError(t('WEAK_DEVICE'));
|
||||
|
|
|
@ -10,7 +10,12 @@ import {
|
|||
} from 'utils/storage/localStorage';
|
||||
import { useRouter } from 'next/router';
|
||||
import { PAGES } from 'constants/pages';
|
||||
import { SESSION_KEYS, getKey, setKey } from 'utils/storage/sessionStorage';
|
||||
import {
|
||||
SESSION_KEYS,
|
||||
getKey,
|
||||
removeKey,
|
||||
setKey,
|
||||
} from 'utils/storage/sessionStorage';
|
||||
import {
|
||||
decryptAndStoreToken,
|
||||
generateAndSaveIntermediateKeyAttributes,
|
||||
|
@ -42,6 +47,7 @@ import { APPS, getAppName } from 'constants/apps';
|
|||
import { addLocalLog } from 'utils/logging';
|
||||
import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker';
|
||||
import { B64EncryptionResult } from 'types/crypto';
|
||||
import { CustomError } from 'utils/error';
|
||||
|
||||
export default function Credentials() {
|
||||
const router = useRouter();
|
||||
|
@ -79,6 +85,7 @@ export default function Credentials() {
|
|||
LS_KEYS.KEY_ATTRIBUTES
|
||||
);
|
||||
if (kekEncryptedAttributes && keyAttributes) {
|
||||
removeKey(SESSION_KEYS.KEY_ENCRYPTION_KEY);
|
||||
const cryptoWorker = await ComlinkCryptoWorker.getInstance();
|
||||
const kek = await cryptoWorker.decryptB64(
|
||||
kekEncryptedAttributes.encryptedData,
|
||||
|
@ -90,8 +97,7 @@ export default function Credentials() {
|
|||
keyAttributes.keyDecryptionNonce,
|
||||
kek
|
||||
);
|
||||
await saveKeyInSessionStore(SESSION_KEYS.ENCRYPTION_KEY, key);
|
||||
router.push(PAGES.GALLERY);
|
||||
useMasterPassword(key, kek, keyAttributes, kek);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -122,45 +128,61 @@ export default function Credentials() {
|
|||
appContext.showNavBar(true);
|
||||
}, []);
|
||||
|
||||
const getKeyAttributes = async (kek: string) => {
|
||||
const cryptoWorker = await ComlinkCryptoWorker.getInstance();
|
||||
const { keyAttributes, encryptedToken, token, id, twoFactorSessionID } =
|
||||
await loginViaSRP(srpAttributes, kek);
|
||||
setData(LS_KEYS.KEY_ATTRIBUTES, keyAttributes);
|
||||
if (twoFactorSessionID) {
|
||||
const sessionKeyAttributes =
|
||||
await cryptoWorker.generateKeyAndEncryptToB64(kek);
|
||||
setKey(SESSION_KEYS.KEY_ENCRYPTION_KEY, sessionKeyAttributes);
|
||||
const user = getData(LS_KEYS.USER);
|
||||
setData(LS_KEYS.USER, {
|
||||
...user,
|
||||
twoFactorSessionID,
|
||||
isTwoFactorEnabled: true,
|
||||
});
|
||||
setIsFirstLogin(true);
|
||||
router.push(PAGES.TWO_FACTOR_VERIFY);
|
||||
return null;
|
||||
} else {
|
||||
const user = getData(LS_KEYS.USER);
|
||||
setData(LS_KEYS.USER, {
|
||||
...user,
|
||||
token,
|
||||
encryptedToken,
|
||||
id,
|
||||
isTwoFactorEnabled: false,
|
||||
});
|
||||
return keyAttributes;
|
||||
}
|
||||
};
|
||||
const getKeyAttributes: VerifyMasterPasswordFormProps['getKeyAttributes'] =
|
||||
async (kek: string) => {
|
||||
try {
|
||||
const cryptoWorker = await ComlinkCryptoWorker.getInstance();
|
||||
const {
|
||||
keyAttributes,
|
||||
encryptedToken,
|
||||
token,
|
||||
id,
|
||||
twoFactorSessionID,
|
||||
} = await loginViaSRP(srpAttributes, kek);
|
||||
setData(LS_KEYS.KEY_ATTRIBUTES, keyAttributes);
|
||||
if (twoFactorSessionID) {
|
||||
const sessionKeyAttributes =
|
||||
await cryptoWorker.generateKeyAndEncryptToB64(kek);
|
||||
setKey(
|
||||
SESSION_KEYS.KEY_ENCRYPTION_KEY,
|
||||
sessionKeyAttributes
|
||||
);
|
||||
const user = getData(LS_KEYS.USER);
|
||||
setData(LS_KEYS.USER, {
|
||||
...user,
|
||||
twoFactorSessionID,
|
||||
isTwoFactorEnabled: true,
|
||||
});
|
||||
setIsFirstLogin(true);
|
||||
router.push(PAGES.TWO_FACTOR_VERIFY);
|
||||
throw Error(CustomError.TWO_FACTOR_ENABLED);
|
||||
} else {
|
||||
const user = getData(LS_KEYS.USER);
|
||||
setData(LS_KEYS.USER, {
|
||||
...user,
|
||||
token,
|
||||
encryptedToken,
|
||||
id,
|
||||
isTwoFactorEnabled: false,
|
||||
});
|
||||
return keyAttributes;
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.message !== CustomError.TWO_FACTOR_ENABLED) {
|
||||
logError(e, 'getKeyAttributes failed');
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
const useMasterPassword: VerifyMasterPasswordFormProps['callback'] = async (
|
||||
key,
|
||||
passphrase,
|
||||
kek,
|
||||
keyAttributes
|
||||
keyAttributes,
|
||||
passphrase
|
||||
) => {
|
||||
try {
|
||||
if (isFirstLogin()) {
|
||||
if (isFirstLogin() && passphrase) {
|
||||
await generateAndSaveIntermediateKeyAttributes(
|
||||
passphrase,
|
||||
keyAttributes,
|
||||
|
|
|
@ -202,7 +202,7 @@ export async function generateKeyAndEncryptToB64(data: string) {
|
|||
}
|
||||
|
||||
export async function encryptUTF8(data: string, key: string) {
|
||||
const b64Data = await toB64(await fromString(data));
|
||||
const b64Data = await toB64(await fromUTF8(data));
|
||||
return await encryptToB64(b64Data, key);
|
||||
}
|
||||
|
||||
|
@ -281,7 +281,7 @@ export async function deriveKey(
|
|||
return await toB64(
|
||||
sodium.crypto_pwhash(
|
||||
sodium.crypto_secretbox_KEYBYTES,
|
||||
await fromString(passphrase),
|
||||
await fromUTF8(passphrase),
|
||||
await fromB64(salt),
|
||||
opsLimit,
|
||||
memLimit,
|
||||
|
@ -315,7 +315,7 @@ export async function deriveInteractiveKey(passphrase: string, salt: string) {
|
|||
const key = await toB64(
|
||||
sodium.crypto_pwhash(
|
||||
sodium.crypto_secretbox_KEYBYTES,
|
||||
await fromString(passphrase),
|
||||
await fromUTF8(passphrase),
|
||||
await fromB64(salt),
|
||||
sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE,
|
||||
sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE,
|
||||
|
@ -402,10 +402,15 @@ export async function toURLSafeB64(input: Uint8Array) {
|
|||
return sodium.to_base64(input, sodium.base64_variants.URLSAFE);
|
||||
}
|
||||
|
||||
export async function fromString(input: string) {
|
||||
export async function fromUTF8(input: string) {
|
||||
await sodium.ready;
|
||||
return sodium.from_string(input);
|
||||
}
|
||||
|
||||
export async function toUTF8(input: string) {
|
||||
await sodium.ready;
|
||||
return sodium.to_string(await fromB64(input));
|
||||
}
|
||||
export async function toHex(input: string) {
|
||||
await sodium.ready;
|
||||
return sodium.to_hex(await fromB64(input));
|
||||
|
|
|
@ -71,6 +71,7 @@ export const CustomError = {
|
|||
NON_PREVIEWABLE_FILE: 'non previewable file',
|
||||
PROCESSING_FAILED: 'processing failed',
|
||||
EXPORT_RECORD_JSON_PARSING_FAILED: 'export record json parsing failed',
|
||||
TWO_FACTOR_ENABLED: 'two factor enabled',
|
||||
};
|
||||
|
||||
export function parseUploadErrorCodes(error) {
|
||||
|
|
|
@ -17,6 +17,13 @@ export const getKey = (key: SESSION_KEYS) => {
|
|||
return JSON.parse(sessionStorage.getItem(key));
|
||||
};
|
||||
|
||||
export const removeKey = (key: SESSION_KEYS) => {
|
||||
if (typeof sessionStorage === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
sessionStorage.removeItem(key);
|
||||
};
|
||||
|
||||
export const clearKeys = () => {
|
||||
if (typeof sessionStorage === 'undefined') {
|
||||
return null;
|
||||
|
|
|
@ -151,8 +151,11 @@ export class DedicatedCryptoWorker {
|
|||
return libsodium.generateSubKey(key, subKeyLength, subKeyID, context);
|
||||
}
|
||||
|
||||
async fromString(string: string) {
|
||||
return libsodium.fromString(string);
|
||||
async fromUTF8(string: string) {
|
||||
return libsodium.fromUTF8(string);
|
||||
}
|
||||
async toUTF8(data: string) {
|
||||
return libsodium.toUTF8(data);
|
||||
}
|
||||
|
||||
async toB64(data: Uint8Array) {
|
||||
|
|
Loading…
Reference in a new issue