Search code examples
securityrustpasswordscommand-line-interfacebrute-force

Password generator for a brute force application usin Rust or CLI tool


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.


Solution

  • 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}");
        }
    }
    
    

    playground

    Explaining the algorithm

    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.