#![deny(
clippy::all,
clippy::cargo,
clippy::nursery,
// clippy::restriction,
// clippy::pedantic
)]
#![allow(
clippy::suboptimal_flops,
clippy::redundant_pub_crate,
clippy::fallible_impl_from
)]
#![deny(missing_debug_implementations)]
#![deny(rustdoc::all)]
#![allow(rustdoc::missing_doc_code_examples)]
use crate::crack::worker_threads::spawn_worker_threads;
use std::fmt::Debug;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use std::time::Instant;
pub use crack::CrackResult;
pub use parameter::*;
mod crack;
#[cfg(test)]
mod testutil;
pub mod hash_fncs;
mod parameter;
pub mod symbols;
pub trait CrackTarget: 'static + Eq + Send + Sync + Debug {}
impl<T> CrackTarget for T where T: 'static + Eq + Send + Sync + Debug {}
pub fn crack<T: CrackTarget>(param: CrackParameter<T>) -> CrackResult {
let param = InternalCrackParameter::from(param);
let param = Arc::from(param);
let done = Arc::from(AtomicBool::from(false));
let instant = Instant::now();
let handles = spawn_worker_threads(param.clone(), done);
let solution = handles
.into_iter()
.map(|h| h.join().unwrap()) .flatten()
.last();
let seconds = instant.elapsed().as_secs_f64();
let param =
Arc::try_unwrap(param).unwrap_or_else(|_| panic!("There should only be one reference!"));
if let Some(solution) = solution {
CrackResult::new_success(param, seconds, solution)
} else {
CrackResult::new_failure(param, seconds)
}
}
#[cfg(test)]
mod tests {
use crate::hash_fncs::no_hashing;
use crate::testutil::{
create_test_crack_params_full_alphabet, create_test_crack_params_full_alphabet_sha256,
create_test_crack_params_full_alphabet_sha256_fair,
};
use crate::{BasicCrackParameter, CrackParameter, TargetHashInput};
use super::*;
#[test]
#[should_panic]
fn test_crack_should_panic_1() {
let cp = CrackParameter::new(
BasicCrackParameter::new(vec!['a'].into_boxed_slice(), 4, 5, false),
no_hashing(TargetHashInput::Plaintext("a+c")),
);
let _res = crack(cp);
}
#[test]
fn test_crack_dont_find_bc_of_min_length() {
let cp = CrackParameter::new(
BasicCrackParameter::new(vec!['a'].into_boxed_slice(), 4, 3, false),
no_hashing(TargetHashInput::Plaintext("a+c")),
);
let res = crack(cp);
assert!(
!res.is_success(),
"should not find result, because of min length!"
);
}
#[test]
fn test_crack_identity() {
let input = String::from("a+c");
let target = input.clone(); let cp = create_test_crack_params_full_alphabet(&target);
let res = crack(cp);
assert!(res.is_success(), "a solution must be found!");
assert!(
input.eq(res.solution().as_ref().unwrap()),
"target and cracked result must equal!"
);
}
#[test]
fn test_crack_sha256_fair_and_unfair_mode() {
let input = "a+c";
let target =
String::from("3d7edde33628331676b39e19a3f2bdb3c583960ad8d865351a32e2ace7d8e02d");
let cp = create_test_crack_params_full_alphabet_sha256(&target);
let cp_fair = create_test_crack_params_full_alphabet_sha256_fair(&target);
let res = crack(cp);
assert!(res.is_success(), "A solution MUST be found!");
assert!(
input.eq(res.solution().as_ref().unwrap()),
"The cracked value is wrong! It's"
);
if num_cpus::get() > 1 {
assert!(cp_fair.fair_mode(), "Fair mode must be activated"); assert!(res.thread_count() > 1, "multiple threads must be used");
let res_fair = crack(cp_fair);
assert!(res_fair.is_success(), "A solution MUST be found!");
assert!(
input.eq(res.solution().as_ref().unwrap()),
"The cracked value is wrong!"
);
assert!(
res.thread_count() > res_fair.thread_count(),
"fair mode must use less treads!"
);
}
}
}