Fix Secret Key decode rejecting valid keys; verify build
The first base32 symbol carries 3 data bits (26 symbols = 130 bits, 2 spare), but decode only accepted values 0-3, so ~half of generated keys failed to parse. Adds an edge-case test, rustfmt config, Cargo.lock, and on-demand cross targets instead of installing all seven in rust-toolchain.toml. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -27,16 +27,12 @@ const AMBIGUOUS: &str = "0O1lI|";
|
||||
|
||||
/// Generates a password with at least one character from each enabled class.
|
||||
pub fn generate_password(opts: &PasswordOptions) -> String {
|
||||
let classes: Vec<Vec<char>> = [
|
||||
(opts.lowercase, LOWER),
|
||||
(opts.uppercase, UPPER),
|
||||
(opts.digits, DIGITS),
|
||||
(opts.symbols, SYMBOLS),
|
||||
]
|
||||
.into_iter()
|
||||
.filter(|(on, _)| *on)
|
||||
.map(|(_, set)| set.chars().filter(|c| !(opts.avoid_ambiguous && AMBIGUOUS.contains(*c))).collect())
|
||||
.collect();
|
||||
let classes: Vec<Vec<char>> =
|
||||
[(opts.lowercase, LOWER), (opts.uppercase, UPPER), (opts.digits, DIGITS), (opts.symbols, SYMBOLS)]
|
||||
.into_iter()
|
||||
.filter(|(on, _)| *on)
|
||||
.map(|(_, set)| set.chars().filter(|c| !(opts.avoid_ambiguous && AMBIGUOUS.contains(*c))).collect())
|
||||
.collect();
|
||||
let classes = if classes.is_empty() { vec![LOWER.chars().collect()] } else { classes };
|
||||
let length = opts.length.clamp(classes.len().max(8), 128);
|
||||
let all: Vec<char> = classes.iter().flatten().copied().collect();
|
||||
@@ -70,7 +66,8 @@ mod tests {
|
||||
assert!(p.chars().any(|c| c.is_ascii_digit()));
|
||||
assert!(!p.chars().any(|c| AMBIGUOUS.contains(c)));
|
||||
}
|
||||
let digits_only = PasswordOptions { length: 6, lowercase: false, uppercase: false, symbols: false, ..Default::default() };
|
||||
let digits_only =
|
||||
PasswordOptions { length: 6, lowercase: false, uppercase: false, symbols: false, ..Default::default() };
|
||||
assert_eq!(generate_password(&digits_only).len(), 8); // minimum length 8
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,8 @@ fn hmac_bytes<M: Mac + hmac::digest::KeyInit>(key: &[u8], msg: &[u8]) -> Vec<u8>
|
||||
}
|
||||
|
||||
fn decode_b32(s: &str) -> Result<Vec<u8>, TotpError> {
|
||||
let cleaned: String = s.chars().filter(|c| !c.is_whitespace() && *c != '=' && *c != '-').collect::<String>().to_ascii_uppercase();
|
||||
let cleaned: String =
|
||||
s.chars().filter(|c| !c.is_whitespace() && *c != '=' && *c != '-').collect::<String>().to_ascii_uppercase();
|
||||
BASE32_NOPAD.decode(cleaned.as_bytes()).map_err(|_| TotpError::Invalid)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user