From 4d949d153bfce06eff78ea0670065690fa306fe6 Mon Sep 17 00:00:00 2001 From: bunnie Date: Wed, 15 Nov 2023 19:14:08 +0800 Subject: [PATCH] Add option to generat number-only passwords (#446) This commit adds explicit selection knobs for all possible types of characters and symbols. A side effect is there is also now an error loop to handle the case that none of the knobs are selected. The user cannot proceed with generation until at least one type is selected. When no alphabetic characters are selected, "exclude similar" is now false, which allows all of the numbers to be picked from. Normally, 1, 0, etc. are avoided to make it easier for humans to read/copy the passwords without ambiguity. This does reduce the total entropy slightly, but ideally you are using the password generator with a long setting (20 or so characters) so you're well beyond the worry of losing entropy due to dropping the few similar characters. --- apps/vault/locales/i18n.json | 7 ++++ apps/vault/src/actions.rs | 76 ++++++++++++++++++++++-------------- 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/apps/vault/locales/i18n.json b/apps/vault/locales/i18n.json index ea86bce41..16b2a587f 100644 --- a/apps/vault/locales/i18n.json +++ b/apps/vault/locales/i18n.json @@ -363,6 +363,13 @@ "ja": "これはどのタイプの OTP レコードですか (わからない場合は、おそらく TOTP です)。", "zh": "这是哪种类型的 OTP 记录(如果您不知道,可能是 TOTP)?" }, + "vault.newitem.lowercase": { + "en": "Lowercase letters", + "en-tts": "Lowercase letters", + "fr": "Lettres minuscules", + "ja": "小文字", + "zh": "小写字母" + }, "vault.newitem.name": { "en": "Please name the credential:", "en-tts": "Please name the credential", diff --git a/apps/vault/src/actions.rs b/apps/vault/src/actions.rs index d3301dafd..bf2c35856 100644 --- a/apps/vault/src/actions.rs +++ b/apps/vault/src/actions.rs @@ -248,32 +248,40 @@ impl<'a> ActionManager<'a> { let mut upper = false; let mut number = false; let mut symbol = false; - self.modals - .add_list(vec![ - t!("vault.newitem.uppercase", locales::LANG), - t!("vault.newitem.numbers", locales::LANG), - t!("vault.newitem.symbols", locales::LANG), - ]).expect("couldn't create configuration modal"); - match self.modals.get_checkbox(t!("vault.newitem.configure_generator", locales::LANG)) { - Ok(options) => { - for opt in options { - if opt == t!("vault.newitem.uppercase", locales::LANG) {upper = true;} - if opt == t!("vault.newitem.numbers", locales::LANG) {number = true;} - if opt == t!("vault.newitem.symbols", locales::LANG) {symbol = true;} + let mut lower = false; + while !upper && !number && !symbol && !lower { + self.modals + .add_list(vec![ + t!("vault.newitem.lowercase", locales::LANG), + t!("vault.newitem.uppercase", locales::LANG), + t!("vault.newitem.numbers", locales::LANG), + t!("vault.newitem.symbols", locales::LANG), + ]).expect("couldn't create configuration modal"); + match self.modals.get_checkbox(t!("vault.newitem.configure_generator", locales::LANG)) { + Ok(options) => { + for opt in options { + if opt == t!("vault.newitem.lowercase", locales::LANG) {lower = true;} + if opt == t!("vault.newitem.uppercase", locales::LANG) {upper = true;} + if opt == t!("vault.newitem.numbers", locales::LANG) {number = true;} + if opt == t!("vault.newitem.symbols", locales::LANG) {symbol = true;} + } } + _ => {log::error!("Modal selection error"); self.action_active.store(false, Ordering::SeqCst); return} + } + if upper == false && lower == false && symbol == false && number == false { + self.modals.show_notification(t!("vault.error.nothing_selected", locales::LANG), None).ok(); } - _ => {log::error!("Modal selection error"); self.action_active.store(false, Ordering::SeqCst); return} } #[cfg(feature="ux-swap-delay")] self.tt.sleep_ms(SWAP_DELAY_MS).unwrap(); let pg2 = PasswordGenerator { length: length as usize, numbers: number, - lowercase_letters: true, + lowercase_letters: lower, uppercase_letters: upper, symbols: symbol, spaces: false, - exclude_similar_characters: true, + exclude_similar_characters: upper || lower, strict: true, }; approved = false; @@ -774,32 +782,40 @@ impl<'a> ActionManager<'a> { let mut upper = false; let mut number = false; let mut symbol = false; - self.modals - .add_list(vec![ - t!("vault.newitem.uppercase", locales::LANG), - t!("vault.newitem.numbers", locales::LANG), - t!("vault.newitem.symbols", locales::LANG), - ]).expect("couldn't create configuration modal"); - match self.modals.get_checkbox(t!("vault.newitem.configure_generator", locales::LANG)) { - Ok(options) => { - for opt in options { - if opt == t!("vault.newitem.uppercase", locales::LANG) {upper = true;} - if opt == t!("vault.newitem.numbers", locales::LANG) {number = true;} - if opt == t!("vault.newitem.symbols", locales::LANG) {symbol = true;} + let mut lower = false; + while !upper && !number && !symbol && !lower { + self.modals + .add_list(vec![ + t!("vault.newitem.lowercase", locales::LANG), + t!("vault.newitem.uppercase", locales::LANG), + t!("vault.newitem.numbers", locales::LANG), + t!("vault.newitem.symbols", locales::LANG), + ]).expect("couldn't create configuration modal"); + match self.modals.get_checkbox(t!("vault.newitem.configure_generator", locales::LANG)) { + Ok(options) => { + for opt in options { + if opt == t!("vault.newitem.lowercase", locales::LANG) {lower = true;} + if opt == t!("vault.newitem.uppercase", locales::LANG) {upper = true;} + if opt == t!("vault.newitem.numbers", locales::LANG) {number = true;} + if opt == t!("vault.newitem.symbols", locales::LANG) {symbol = true;} + } } + _ => {log::error!("Modal selection error"); self.action_active.store(false, Ordering::SeqCst); return} + } + if upper == false && lower == false && symbol == false && number == false { + self.modals.show_notification(t!("vault.error.nothing_selected", locales::LANG), None).ok(); } - _ => {log::error!("Modal selection error"); self.action_active.store(false, Ordering::SeqCst); return} } #[cfg(feature="ux-swap-delay")] self.tt.sleep_ms(SWAP_DELAY_MS).unwrap(); let pg2 = PasswordGenerator { length: length as usize, numbers: number, - lowercase_letters: true, + lowercase_letters: lower, uppercase_letters: upper, symbols: symbol, spaces: false, - exclude_similar_characters: true, + exclude_similar_characters: upper || lower, strict: true, }; approved = false;