Skip to content

Commit

Permalink
Simple counter to stop the searcher when max depth is reached (#58)
Browse files Browse the repository at this point in the history
* feat: stop the search if max depth is reached

* feat: set max depth from config

* feat: test for max depth

* feat: updated bfs to use get_config

* feat: pass down max_depth as function parameter to bfs

* feat: max_depth is optional, we can set it to None to indicate there is no limit
  • Loading branch information
swanandx authored Nov 12, 2022
1 parent d539fc8 commit aa0708d
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 8 deletions.
5 changes: 5 additions & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ pub struct Opts {
/// Turn off human checker
#[clap(short, long)]
disable_human_checker: bool,

/// Maximum number of decodings to perform on a string
#[clap(short, long, default_value = "10000")]
max_depth: u32,
}

/// Parse CLI Arguments turns a Clap Opts struct, seen above
Expand Down Expand Up @@ -54,6 +58,7 @@ fn cli_args_into_config_struct(opts: Opts) -> (String, Config) {
// default is false, we want default to be true
human_checker_on: !opts.disable_human_checker,
offline_mode: true,
max_depth: Some(opts.max_depth),
},
)
}
4 changes: 4 additions & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ pub struct Config {
pub human_checker_on: bool,
/// Is the program being run in offline mode?
pub offline_mode: bool,
/// Number of times decoding shall be perfomed
/// Setting it to [`None`] means we will go infinitely in depth
pub max_depth: Option<u32>,
}

/// Cell for storing global Config
Expand Down Expand Up @@ -58,6 +61,7 @@ impl Default for Config {
lemmeknow_config: LEMMEKNOW_DEFAULT_CONFIG,
human_checker_on: false,
offline_mode: false,
max_depth: Some(10_000), // TODO: Set this to some better value
}
}
}
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ pub fn perform_cracking(text: &str, config: Config) -> Option<String> {
// let search_tree = searchers::Tree::new(text.to_string());
// Perform the search algorithm
// It will either return a failure or success.
let max_depth = config.max_depth;
config::set_global_config(config);
searchers::search_for_plaintext(text)
searchers::search_for_plaintext(text, max_depth)
}

#[cfg(test)]
Expand Down
25 changes: 20 additions & 5 deletions src/searchers/bfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ use crate::{decoders::crack_results::CrackResult, filtration_system::MyResults};

/// Breadth first search is our search algorithm
/// https://en.wikipedia.org/wiki/Breadth-first_search
pub fn bfs(input: &str) -> Option<String> {
pub fn bfs(input: &str, max_depth: Option<u32>) -> Option<String> {
let mut seen_strings = HashSet::new();
// all strings to search through
let mut current_strings = vec![input.to_string()];

let mut exit_result: Option<CrackResult> = None;

let mut curr_depth: u32 = 1; // as we have input string, so we start from 1

// loop through all of the strings in the vec
while !current_strings.is_empty() {
while !current_strings.is_empty() && max_depth.map_or(true, |x| curr_depth <= x) {
trace!("Number of potential decodings: {}", current_strings.len());
trace!("Current depth is {:?}; [ {:?} max ]", curr_depth, max_depth);

let mut new_strings: Vec<String> = vec![];

Expand Down Expand Up @@ -51,6 +54,7 @@ pub fn bfs(input: &str) -> Option<String> {
}

current_strings = new_strings;
curr_depth += 1;

trace!("Refreshed the vector, {:?}", current_strings);
}
Expand All @@ -68,7 +72,7 @@ mod tests {
// let result = bfs("Q0FOQVJZOiBoZWxsbw==");
// assert!(result.is_some());
// assert!(result.unwrap() == "CANARY: hello");
let result = bfs("b2xsZWg=");
let result = bfs("b2xsZWg=", None);
assert!(result.is_some());
assert!(result.unwrap() == "hello");
}
Expand All @@ -84,9 +88,20 @@ mod tests {
fn non_deterministic_like_behaviour_regression_test() {
// text was too long, so we put \ to escape the \n
// and put the rest of string on next line.
let result = bfs("UFRCRVRWVkNiRlZMTVVkYVVFWjZVbFZPU0\
dGMU1WVlpZV2d4VkRVNWJWWnJjRzFVUlhCc1pYSlNWbHBPY0VaV1ZXeHJWRWd4TUZWdlZsWlg=");
let result = bfs(
"UFRCRVRWVkNiRlZMTVVkYVVFWjZVbFZPU0\
dGMU1WVlpZV2d4VkRVNWJWWnJjRzFVUlhCc1pYSlNWbHBPY0VaV1ZXeHJWRWd4TUZWdlZsWlg=",
None,
);
assert!(result.is_some());
assert_eq!(result.unwrap(), "https://www.google.com");
}

#[test]
fn max_depth_test() {
// text is encoded with base64 5 times
let result = bfs("VjFaV2ExWXlUWGxUYTJoUVVrUkJPUT09", Some(4));
// It goes only upto depth 4, so it can't find the plaintext
assert!(result.is_none());
}
}
4 changes: 2 additions & 2 deletions src/searchers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ mod bfs;
/// We can return an Option? An Enum? And then match on that
/// So if we return CrackSuccess we return
/// Else if we return an array, we add it to the children and go again.
pub fn search_for_plaintext(input: &str) -> Option<String> {
pub fn search_for_plaintext(input: &str, max_depth: Option<u32>) -> Option<String> {
// Change this to select which search algorithm we want to use.
bfs::bfs(input)
bfs::bfs(input, max_depth)
}

/// Performs the decodings by getting all of the decoders
Expand Down

0 comments on commit aa0708d

Please sign in to comment.