Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup filtration code #235

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 62 additions & 83 deletions src/filtration_system/mod.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,26 @@
use std::sync::mpsc::channel;

use crate::checkers::CheckerTypes;
use crate::decoders::atbash_decoder::AtbashDecoder;
use crate::decoders::base32_decoder::Base32Decoder;
use crate::decoders::base58_bitcoin_decoder::Base58BitcoinDecoder;
use crate::decoders::base58_monero_decoder::Base58MoneroDecoder;
use crate::decoders::binary_decoder::BinaryDecoder;
use crate::decoders::hexadecimal_decoder::HexadecimalDecoder;
use crate::DecoderResult;

use crate::decoders::base58_flickr_decoder::Base58FlickrDecoder;
use crate::decoders::base58_ripple_decoder::Base58RippleDecoder;

use crate::decoders::crack_results::CrackResult;
use crate::decoders::interface::{Crack, Decoder};
///! Proposal: https://broadleaf-angora-7db.notion.site/Filtration-System-7143b36a42f1466faea3077bfc7e859e
///! Given a filter object, return an array of decoders/crackers which have been filtered
///
use crate::decoders::base64_decoder::Base64Decoder;
use crate::decoders::base64_url_decoder::Base64URLDecoder;
use crate::decoders::base65536_decoder::Base65536Decoder;
use crate::decoders::base91_decoder::Base91Decoder;
use crate::decoders::caesar_decoder::CaesarDecoder;
use crate::decoders::citrix_ctx1_decoder::CitrixCTX1Decoder;
use crate::decoders::crack_results::CrackResult;
use crate::decoders::interface::{Crack, Decoder};
use crate::decoders::morse_code::MorseCodeDecoder;
use crate::decoders::railfence_decoder::RailfenceDecoder;
use crate::decoders::reverse_decoder::ReverseDecoder;
use crate::decoders::url_decoder::URLDecoder;

/// Import all of the decoders
use crate::decoders::{
atbash_decoder::AtbashDecoder, base32_decoder::Base32Decoder,
base58_bitcoin_decoder::Base58BitcoinDecoder, base58_flickr_decoder::Base58FlickrDecoder,
base58_monero_decoder::Base58MoneroDecoder, base58_ripple_decoder::Base58RippleDecoder,
base64_decoder::Base64Decoder, base64_url_decoder::Base64URLDecoder,
base65536_decoder::Base65536Decoder, base91_decoder::Base91Decoder,
binary_decoder::BinaryDecoder, caesar_decoder::CaesarDecoder,
citrix_ctx1_decoder::CitrixCTX1Decoder, hexadecimal_decoder::HexadecimalDecoder,
morse_code::MorseCodeDecoder, railfence_decoder::RailfenceDecoder,
reverse_decoder::ReverseDecoder, url_decoder::URLDecoder,
};

use log::trace;
use rayon::prelude::*;
Expand All @@ -50,100 +44,85 @@ impl Decoders {
/// https://doc.rust-lang.org/book/ch17-02-trait-objects.html
/// Which allows us to have multiple different structs in the same vector
/// But each struct shares the same `.crack()` method, so it's fine.
pub fn run(&self, text: &str, checker: CheckerTypes) -> MyResults {
pub fn run(&self, text: &str, checker: CheckerTypes) -> CrackResults {
trace!("Running .crack() on all decoders");
let (sender, receiver) = channel();
self.components
.into_par_iter()
.try_for_each_with(sender, |s, i| {
.try_for_each_with(sender, |s, i| -> Option<()> {
let results = i.crack(text, &checker);
if results.success {
s.send(results).expect("expected no send error!");
// returning None short-circuits the iterator
// we don't process any further as we got success
return None;
s.send(results).expect("Failed to send results!");
return None; // Short-circuit the iterator
}
s.send(results).expect("expected no send error!");
// return Some(()) to indicate that continue processing
Some(())
s.send(results).expect("Failed to send results!");
Some(()) // Continue the iterator
});

let mut all_results: Vec<CrackResult> = Vec::new();

while let Ok(result) = receiver.recv() {
// if we recv success, break.
for result in receiver.iter() {
if result.success {
return MyResults::Break(result);
return CrackResults::Break(result);
}
all_results.push(result)
all_results.push(result);
}

MyResults::Continue(all_results)
CrackResults::Continue(all_results)
}
}

/// [`Enum`] for our custom results.
/// if our checker succeed, we return `Break` variant contining [`CrackResult`]
/// else we return `Continue` with the decoded results.
pub enum MyResults {
/// Variant containing successful [`CrackResult`]
/// Enum representing the result of a cracking operation.
/// If the checker succeeds, it returns the `Break` variant containing `CrackResult`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those "[]" are for docs to link to CrackResult. [`CrackResult`] will point to docs of CrackResult.

/// Otherwise, it returns the `Continue` variant with a vector of `CrackResult` for further processing.
pub enum CrackResults {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was named that way to avoid confusion between CrackResult and CrackResults

/// Variant containing a successful `CrackResult`.
Break(CrackResult),
/// Contains [`Vec`] of [`CrackResult`] for further processing
/// Contains a vector of `CrackResult` for further processing.
Continue(Vec<CrackResult>),
}

impl MyResults {
/// named with _ to pass dead_code warning
/// as we aren't using it, it's just used in tests
pub fn _break_value(self) -> Option<CrackResult> {
impl CrackResults {
#[allow(dead_code)]
/// Returns the `CrackResult` if the checker succeeds.
pub fn break_value(self) -> Option<CrackResult> {
Comment on lines +85 to +88
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we move this impl block under mod test, as break_value is used only in tests.

match self {
MyResults::Break(val) => Some(val),
MyResults::Continue(_) => None,
CrackResults::Break(val) => Some(val),
CrackResults::Continue(_) => None,
}
}
}

/// Create a decoder and return it as a Box<dyn Crack>
macro_rules! create_decoder {
($decoder:ty) => {
Box::new(Decoder::<$decoder>::new())
};
}

/// Currently takes no args as this is just a spike to get all the basic functionality working
pub fn filter_and_get_decoders(_text_struct: &DecoderResult) -> Decoders {
trace!("Filtering and getting all decoders");
let binary = Decoder::<BinaryDecoder>::new();
let hexadecimal = Decoder::<HexadecimalDecoder>::new();
let base58_bitcoin = Decoder::<Base58BitcoinDecoder>::new();
let base58_monero = Decoder::<Base58MoneroDecoder>::new();
let base58_ripple = Decoder::<Base58RippleDecoder>::new();
let base58_flickr = Decoder::<Base58FlickrDecoder>::new();
let base64 = Decoder::<Base64Decoder>::new();
let base91 = Decoder::<Base91Decoder>::new();
let base64_url = Decoder::<Base64URLDecoder>::new();
let base65536 = Decoder::<Base65536Decoder>::new();
let citrix_ctx1 = Decoder::<CitrixCTX1Decoder>::new();
let url = Decoder::<URLDecoder>::new();
let base32 = Decoder::<Base32Decoder>::new();
let reversedecoder = Decoder::<ReverseDecoder>::new();
let morsecodedecoder = Decoder::<MorseCodeDecoder>::new();
let atbashdecoder = Decoder::<AtbashDecoder>::new();
let caesardecoder = Decoder::<CaesarDecoder>::new();
let railfencedecoder = Decoder::<RailfenceDecoder>::new();
Decoders {
components: vec![
Box::new(reversedecoder),
Box::new(base64),
Box::new(base58_bitcoin),
Box::new(base58_monero),
Box::new(base58_ripple),
Box::new(base58_flickr),
Box::new(base91),
Box::new(base65536),
Box::new(binary),
Box::new(hexadecimal),
Box::new(base32),
Box::new(morsecodedecoder),
Box::new(atbashdecoder),
Box::new(caesardecoder),
Box::new(railfencedecoder),
Box::new(citrix_ctx1),
Box::new(url),
Box::new(base64_url),
create_decoder!(ReverseDecoder),
create_decoder!(Base64Decoder),
create_decoder!(Base58BitcoinDecoder),
create_decoder!(Base58MoneroDecoder),
create_decoder!(Base58RippleDecoder),
create_decoder!(Base58FlickrDecoder),
create_decoder!(Base91Decoder),
create_decoder!(Base65536Decoder),
create_decoder!(BinaryDecoder),
create_decoder!(HexadecimalDecoder),
create_decoder!(Base32Decoder),
create_decoder!(MorseCodeDecoder),
create_decoder!(AtbashDecoder),
create_decoder!(CaesarDecoder),
create_decoder!(RailfenceDecoder),
create_decoder!(CitrixCTX1Decoder),
create_decoder!(URLDecoder),
create_decoder!(Base64URLDecoder),
Comment on lines +108 to +125
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would it be better if we can just pass in all of decoders in single macro? like

create_decoders!(ReverseDecoder, Base64Decoder, Base58.....)

which would return a array ( doesn't need to a Vec as deocders are fixed right?? ) of Decoders?

],
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/searchers/bfs.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::cli_pretty_printing::decoded_how_many_times;
use crate::filtration_system::MyResults;
use crate::filtration_system::CrackResults;
use crossbeam::channel::Sender;

use log::trace;
Expand Down Expand Up @@ -35,7 +35,7 @@ pub fn bfs(input: String, result_sender: Sender<Option<DecoderResult>>, stop: Ar
match res {
// if it's Break variant, we have cracked the text successfully
// so just stop processing further.
MyResults::Break(res) => {
CrackResults::Break(res) => {
let mut decoders_used = current_string.path;
let text = res.unencrypted_text.clone().unwrap_or_default();
decoders_used.push(res);
Expand All @@ -53,7 +53,7 @@ pub fn bfs(input: String, result_sender: Sender<Option<DecoderResult>>, stop: Ar
stop.store(true, std::sync::atomic::Ordering::Relaxed);
None // short-circuits the iterator
}
MyResults::Continue(results_vec) => {
CrackResults::Continue(results_vec) => {
new_strings.extend(results_vec.into_iter().flat_map(|mut r| {
let mut decoders_used = current_string.path.clone();
// text is a vector of strings
Expand Down
8 changes: 4 additions & 4 deletions src/searchers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::checkers::athena::Athena;
use crate::checkers::checker_type::{Check, Checker};
use crate::checkers::CheckerTypes;
use crate::config::get_config;
use crate::filtration_system::{filter_and_get_decoders, MyResults};
use crate::filtration_system::{filter_and_get_decoders, CrackResults};
use crate::{timer, DecoderResult};
/// This module provides access to the breadth first search
/// which searches for the plaintext.
Expand Down Expand Up @@ -67,7 +67,7 @@ pub fn search_for_plaintext(input: String) -> Option<DecoderResult> {
/// Performs the decodings by getting all of the decoders
/// and calling `.run` which in turn loops through them and calls
/// `.crack()`.
fn perform_decoding(text: &DecoderResult) -> MyResults {
fn perform_decoding(text: &DecoderResult) -> CrackResults {
let decoders = filter_and_get_decoders(text);
let athena_checker = Checker::<Athena>::new();
let checker = CheckerTypes::CheckAthena(athena_checker);
Expand Down Expand Up @@ -105,7 +105,7 @@ mod tests {
let result = perform_decoding(&dc);
assert!(
result
._break_value()
.break_value()
.expect("expected successful value, none found")
.success
);
Expand All @@ -116,6 +116,6 @@ mod tests {
// Some decoders like base64 return even when the string is empty.
let dc = DecoderResult::_new("");
let result = perform_decoding(&dc);
assert!(result._break_value().is_none());
assert!(result.break_value().is_none());
}
}