import { toHex } from "@utils"; import { aesGcmEncrypt, aesGcmDecrypt } from "@utils/crypto"; import { AppDispatch } from "@app/App"; import * as actions from "@actions/WalletManagerActions"; import { loadWallets } from "../wallets/Wallet"; export function browseAsGuest(dispatch: AppDispatch): void { dispatch(actions.browseAsGuest()); } /** Verifies that the given password is correct, and dispatches the login * action to the Redux store. */ export async function login(dispatch: AppDispatch, salt: string | undefined, tester: string | undefined, password: string): Promise<void> { if (!password) throw new Error("masterPassword.errorPasswordRequired"); if (!salt || !tester) throw new Error("masterPassword.errorPasswordUnset"); try { // Attempt to decrypt the tester with the given password const testerDec = await aesGcmDecrypt(tester, password); // Verify that the decrypted tester is equal to the salt, if not, the // provided master password is incorrect. if (testerDec !== salt) throw new Error("masterPassword.errorPasswordIncorrect"); } catch (e) { // OperationError usually means decryption failure if (e.name === "OperationError") throw new Error("masterPassword.errorPasswordIncorrect"); else throw e; } // Load the wallets, dispatching the wallets to the Redux store loadWallets(dispatch, password); // Dispatch the login state changes to the Redux store dispatch(actions.login(password)); } /** Generates a salt and tester, sets the master password, and dispatches the * action to the Redux store. */ export async function setMasterPassword(dispatch: AppDispatch, password: string): Promise<void> { if (!password) throw new Error("Password is required."); // Generate the salt (to be encrypted with the master password) const salt = window.crypto.getRandomValues(new Uint8Array(32)); const saltHex = toHex(salt); // Generate the encryption tester const tester = await aesGcmEncrypt(saltHex, password); // Store them in local storage localStorage.setItem("salt", saltHex); localStorage.setItem("tester", tester); // Dispatch the login state changes to the Redux store dispatch(actions.setMasterPassword(saltHex, tester, password)); }