I'm working on a distributed application to discover passwords using brute force and other techniques.
For the brute force part, I will need a password generator library for Rust or a command line tool. It needs to generate all possibilities using a specific character set, a certain password length, and a range.
It's important to have the option to get just a specific range because I intend to distribute these 'password batches' to different workers running in parallel.
For example, generate a 4-digit alphanumeric password getting from the 1001th to the 2000th password.
There's no library that I know of, probably because it's not too complicated to just do yourself:
fn nth_password(char_set: &[char], width: u32, n: usize) -> String {
(0..width).rev().map(|i| {
let div = n / char_set.len().pow(i);
let rem = div % char_set.len();
char_set[rem]
}).collect()
}
fn main() {
let char_set: Vec<char> = ['a'..='z', 'A'..='Z', '0'..='9']
.into_iter()
.flatten()
.collect();
for n in 1001..1021 {
let pass = nth_password(&char_set, 4, n);
println!("pass[{n}]: {pass}");
}
}
Each character is an order of magnitude. In base ten at a password length of four, you would have the 1000s place, then the 100s place, then the 10s place, and finally the 1s place.
(0..width).rev()
iterates through 3, 2, 1, 0
. We can notice that 1000
is 10^3, 100
is 10^2, 10
is 10^1, and 1
is 10^0; each number corresponds to the power of ten of the numeral place.
So the formula for the order of magnitude of place i
is 10.pow(i)
. If we divide our number n
by 10.pow(2)
, we get a number that represents how many full 100s are in the number (integer division will truncate any 10s or 1s). For the number 1234 / 10.pow(2)
results in 12
. But we just want that 2
, so we take the remainder with respect to 10: 12 % 10
.
So for base ten, our code would be
let div = n / 10.pow(i);
let rem = div % 10;
We then extrapolate that to a larger symbol set by replacing 10
with char_set.len()
, resulting in the algorithm above.