use crate::types::{CrackResult, PasswordCracker};
use anyhow::Result;
use openssl::pkcs12::Pkcs12;
use rayon::prelude::*;
use std::sync::{Arc, Mutex};
pub struct BruteforceCracker {
min_len: u8,
max_len: u8,
charset: String,
}
impl BruteforceCracker {
pub fn new(min_len: u8, max_len: u8, charset: String) -> Self {
Self {
min_len,
max_len,
charset,
}
}
fn process_chunk(chunk: &[String], pkcs12: &Pkcs12, result: &Arc<Mutex<CrackResult>>) -> bool {
for password in chunk {
{
let result_guard = result.lock().unwrap();
if result_guard.password.is_some() {
return true;
}
result_guard.increment_attempts();
}
if super::check_password(pkcs12, password, result) {
return true;
}
}
false
}
}
impl PasswordCracker for BruteforceCracker {
fn crack(&self, pkcs12: &Arc<Pkcs12>, result: &Arc<Mutex<CrackResult>>) -> Result<()> {
println!(
"Generating passwords with length between {} and {}",
self.min_len, self.max_len
);
let charset: Vec<char> = self.charset.chars().collect();
println!("Charset: {:?}", charset);
for len in self.min_len..=self.max_len {
let mut combinations = Vec::new();
super::generate_combinations(
&charset,
len,
&String::with_capacity(len as usize),
&mut combinations,
);
if combinations
.par_chunks(super::CHUNK_SIZE)
.find_any(|chunk| Self::process_chunk(chunk, pkcs12, result))
.is_some()
{
break;
}
}
Ok(())
}
}