ares/decoders/
base91_decoder.rs1use crate::checkers::CheckerTypes;
2use crate::decoders::interface::check_string_success;
3
4use super::crack_results::CrackResult;
5use super::interface::Crack;
11use super::interface::Decoder;
12
13use log::{debug, info, trace};
14
15pub struct Base91Decoder;
34
35impl Crack for Decoder<Base91Decoder> {
36 fn new() -> Decoder<Base91Decoder> {
37 Decoder {
38 name: "Base91",
39 description: "basE91 is an advanced method for encoding binary data as ASCII characters. It is similar to UUencode or base64, but is more efficient.",
40 link: "https://base91.sourceforge.net/",
41 tags: vec!["base91", "decoder", "base"],
42 popularity: 0.3,
43 phantom: std::marker::PhantomData,
44 }
45 }
46
47 fn crack(&self, text: &str, checker: &CheckerTypes) -> CrackResult {
51 trace!("Trying Base91 with text {:?}", text);
52 let decoded_text = decode_base91_no_error_handling(text);
53 let mut results = CrackResult::new(self, text.to_string());
54
55 if decoded_text.is_none() {
56 debug!("Failed to decode base91 because Base91Decoder::decode_base91_no_error_handling returned None");
57 return results;
58 }
59
60 let decoded_text = decoded_text.unwrap();
61 if !check_string_success(&decoded_text, text) {
62 info!(
63 "Failed to decode base91 because check_string_success returned false on string {}",
64 decoded_text
65 );
66 return results;
67 }
68
69 let checker_result = checker.check(&decoded_text);
70 results.unencrypted_text = Some(vec![decoded_text]);
71
72 results.update_checker(&checker_result);
73
74 results
75 }
76 fn get_tags(&self) -> &Vec<&str> {
78 &self.tags
79 }
80 fn get_name(&self) -> &str {
82 self.name
83 }
84}
85
86fn decode_base91_no_error_handling(text: &str) -> Option<String> {
88 let decoded_text = base91::slice_decode(text.as_bytes());
91 return Some(String::from_utf8_lossy(&decoded_text).to_string());
92}
93
94#[cfg(test)]
95mod tests {
96 use super::Base91Decoder;
97 use crate::{
98 checkers::{
99 athena::Athena,
100 checker_type::{Check, Checker},
101 CheckerTypes,
102 },
103 decoders::interface::{Crack, Decoder},
104 };
105
106 fn get_athena_checker() -> CheckerTypes {
108 let athena_checker = Checker::<Athena>::new();
109 CheckerTypes::CheckAthena(athena_checker)
110 }
111
112 #[test]
113 fn successful_decoding() {
114 let base91_decoder = Decoder::<Base91Decoder>::new();
115
116 let result = base91_decoder.crack("TPwJh>Io2Tv!lE", &get_athena_checker());
117 let decoded_str = &result
118 .unencrypted_text
119 .expect("No unencrypted text for base91");
120 assert_eq!(decoded_str[0], "hello world");
121 }
122
123 #[test]
124 fn base91_decode_empty_string() {
125 let base91_decoder = Decoder::<Base91Decoder>::new();
128 let result = base91_decoder
129 .crack("", &get_athena_checker())
130 .unencrypted_text;
131 assert!(result.is_none());
132 }
133
134 #[test]
135 fn base91_decode_handles_panics() {
136 let base91_decoder = Decoder::<Base91Decoder>::new();
137 let result = base91_decoder
138 .crack("😈", &get_athena_checker())
139 .unencrypted_text;
140 if result.is_some() {
141 panic!("Decode_base91 did not return an option with Some<t>.")
142 } else {
143 assert_eq!(true, true);
147 }
148 }
149
150 #[test]
151 fn base91_handle_panic_if_empty_string() {
152 let base91_decoder = Decoder::<Base91Decoder>::new();
153 let result = base91_decoder
154 .crack("", &get_athena_checker())
155 .unencrypted_text;
156 if result.is_some() {
157 assert_eq!(true, true);
158 }
159 }
160
161 #[test]
162 fn base91_work_if_string_not_base91() {
163 let base91_decoder = Decoder::<Base91Decoder>::new();
169 let result = base91_decoder
170 .crack("hello good day!", &get_athena_checker())
171 .unencrypted_text;
172 if result.is_some() {
173 assert_eq!(true, true);
174 }
175 }
176
177 #[test]
178 fn base91_handle_panic_if_emoji() {
179 let base91_decoder = Decoder::<Base91Decoder>::new();
180 let result = base91_decoder
181 .crack("😂", &get_athena_checker())
182 .unencrypted_text;
183 if result.is_some() {
184 assert_eq!(true, true);
185 }
186 }
187}