From 726dcba58b08541dc3539379ad92eba7d74ae5d7 Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Mon, 17 Feb 2025 14:48:52 -0600 Subject: [PATCH] add base32 IDs --- src/lib.rs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 609ed68..afb74c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,15 +1,32 @@ use rand::{seq::IndexedRandom as _, Rng as _}; pub fn main() { - let passphrase = create_passphrase(" ", 8); - println!("{passphrase}"); - let pin = create_pin(8); - println!("{pin}"); + println!("{}", create_passphrase(" ", 8)); + println!("{}", create_pin(8)); + println!("{}", create_base32(8)); + println!("Press Enter"); let mut input = String::new(); std::io::stdin().read_line(&mut input).ok(); } +/// Generates a Base32 string per RFC 4648, Section 6. +/// +/// Wikipedia says this is the most popular encoding, and it's what +/// `base32` in GNU coreutils uses. +/// +/// +/// This is useful for short IDs, e.g. bugs that aren't living in an issue +/// tracker. 8 characters of Base32 is 40 bits of entropy, which is +/// not enough for a password +pub fn create_base32(len: usize) -> String { + let encoding: Vec<_> = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".chars().collect(); + assert_eq!(encoding.len(), 32); + let chars = (0..len).map(|_| *encoding.choose(&mut rand::rng()).unwrap()); + String::from_iter(chars) +} + +/// Generates a diceware passphrase pub fn create_passphrase(separator: &str, len: usize) -> String { let dice = Dice::default(); let words: Vec<_> = (0..len).map(|_| dice.pick_word()).collect();