diff --git a/src/pages/generate/index.tsx b/src/pages/generate/index.tsx index ab263deaf..1b6693484 100644 --- a/src/pages/generate/index.tsx +++ b/src/pages/generate/index.tsx @@ -61,10 +61,19 @@ export default function Generate() { const cryptoWorker = await new CryptoWorker(); const key: string = await cryptoWorker.generateMasterKey(); const kekSalt: string = await cryptoWorker.generateSaltToDeriveKey(); - const kek: KEK = await cryptoWorker.deriveSensitiveKey( - passphrase, - kekSalt - ); + let kek: KEK; + try { + kek = await cryptoWorker.deriveSensitiveKey( + passphrase, + kekSalt + ); + } catch (e) { + setFieldError( + 'confirm', + constants.PASSWORD_GENERATION_FAILED + ); + return; + } const encryptedKeyAttributes: B64EncryptionResult = await cryptoWorker.encryptToB64( key, kek.key @@ -118,8 +127,9 @@ export default function Generate() { 'passphrase', `${constants.UNKNOWN_ERROR} ${e.message}` ); + } finally { + setLoading(false); } - setLoading(false); }; return ( diff --git a/src/utils/crypto/libsodium.ts b/src/utils/crypto/libsodium.ts index 6920d3f34..c2f0f98bb 100644 --- a/src/utils/crypto/libsodium.ts +++ b/src/utils/crypto/libsodium.ts @@ -275,21 +275,23 @@ export async function deriveKey( export async function deriveSensitiveKey(passphrase: string, salt: string) { await sodium.ready; - const key = await toB64( - sodium.crypto_pwhash( - sodium.crypto_secretbox_KEYBYTES, - await fromString(passphrase), - await fromB64(salt), - sodium.crypto_pwhash_OPSLIMIT_SENSITIVE, - sodium.crypto_pwhash_MEMLIMIT_SENSITIVE, - sodium.crypto_pwhash_ALG_DEFAULT - ) - ); - return { - key: key, - opsLimit: sodium.crypto_pwhash_OPSLIMIT_SENSITIVE, - memLimit: sodium.crypto_pwhash_MEMLIMIT_SENSITIVE, - }; + const minMemLimit = sodium.crypto_pwhash_MEMLIMIT_MIN; + let opsLimit = sodium.crypto_pwhash_OPSLIMIT_SENSITIVE; + let memLimit = sodium.crypto_pwhash_MEMLIMIT_SENSITIVE; + while (memLimit > minMemLimit) { + try { + const key = await deriveKey(passphrase, salt, opsLimit, memLimit); + return { + key, + opsLimit, + memLimit, + }; + } catch (e) { + opsLimit = opsLimit * 2; + memLimit = memLimit / 2; + } + } + throw null; } export async function deriveIntermediateKey(passphrase: string, salt: string) { diff --git a/src/utils/strings/englishConstants.tsx b/src/utils/strings/englishConstants.tsx index 8574d0f27..c9c19818f 100644 --- a/src/utils/strings/englishConstants.tsx +++ b/src/utils/strings/englishConstants.tsx @@ -156,6 +156,7 @@ const englishConstants = { SESSION_EXPIRED: 'login', SYNC_FAILED: 'failed to sync with remote server, please refresh page to try again', + PASSWORD_GENERATION_FAILED: `your browser was unable to generate a strong enough password that meets ente's encryption standards, please try using the mobile app or another browser`, }; export default englishConstants;