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.
This commit is contained in:
bunnie 2023-11-15 19:14:08 +08:00
parent e2d2c49212
commit 4d949d153b
2 changed files with 53 additions and 30 deletions

View file

@ -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",

View file

@ -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;