1use crate::checkers::CheckerTypes;
2use crate::decoders::interface::check_string_success;
3
4use super::crack_results::CrackResult;
5use super::interface::Crack;
6use super::interface::Decoder;
7
8use log::{debug, info, trace};
9
10pub struct MorseCodeDecoder;
14
15impl Crack for Decoder<MorseCodeDecoder> {
16 fn new() -> Decoder<MorseCodeDecoder> {
17 Decoder {
18 name: "Morse Code",
19 description: "Morse code is a method used in telecommunication to encode text characters as standardized sequences of two different signal durations, called dots and dashes, or dits and dahs.",
20 link: "https://en.wikipedia.org/wiki/Morse_code",
21 tags: vec!["morseCode", "decoder", "signals"],
22 popularity: 0.5,
23 phantom: std::marker::PhantomData,
24 }
25 }
26
27 fn crack(&self, text: &str, checker: &CheckerTypes) -> CrackResult {
31 trace!("Trying Morse Code with text {:?}", text);
32 let text = normalise_morse_string(text);
34 let decoded_text: Option<String> = text.split(' ').map(morse_to_alphanumeric).collect();
35
36 trace!("Decoded text for morse code: {:?}", decoded_text);
37 let mut results = CrackResult::new(self, text.to_string());
38
39 if decoded_text.is_none() {
40 debug!("Failed to decode Morse Code because a character was not in the dictionary");
41 return results;
42 }
43
44 let decoded_text = decoded_text.unwrap();
45 if !check_string_success(&decoded_text, &text) {
46 info!(
47 "Failed to decode morse code because check_string_success returned false on string {}",
48 decoded_text
49 );
50 return results;
51 }
52
53 let checker_result = checker.check(&decoded_text);
54 results.unencrypted_text = Some(vec![decoded_text]);
55
56 results.update_checker(&checker_result);
57
58 results
59 }
60 fn get_tags(&self) -> &Vec<&str> {
62 &self.tags
63 }
64 fn get_name(&self) -> &str {
66 self.name
67 }
68}
69
70fn normalise_morse_string(text: &str) -> String {
72 text.to_lowercase()
74 .replace(['\n', '\r'], "")
75 .replace("\\n", "")
76 .replace("\\r", "")
77 .replace('\\', "")
78}
79
80fn morse_to_alphanumeric(text: &str) -> Option<&str> {
82 trace!("Starting to map morse code to alphanumeric");
83 let result = match text {
84 ".-" => "A",
85 "-..." => "B",
86 "-.-." => "C",
87 "-.." => "D",
88 "." => "E",
89 "..-." => "F",
90 "--." => "G",
91 "...." => "H",
92 ".." => "I",
93 ".---" => "J",
94 "-.-" => "K",
95 ".-.." => "L",
96 "--" => "M",
97 "-." => "N",
98 "---" => "O",
99 ".--." => "P",
100 "--.-" => "Q",
101 ".-." => "R",
102 "..." => "S",
103 "-" => "T",
104 "..-" => "U",
105 "...-" => "V",
106 ".--" => "W",
107 "-..-" => "X",
108 "-.--" => "Y",
109 "--.." => "Z",
110
111 ".----" => "1",
112 "..---" => "2",
113 "...--" => "3",
114 "....-" => "4",
115 "....." => "5",
116 "-...." => "6",
117 "--..." => "7",
118 "---.." => "8",
119 "----." => "9",
120 "-----" => "0",
121
122 ".-..." => "&",
123 ".--.-." => "@",
124 "---..." => ":",
125 "--..--" => ",",
126 ".-.-.-" => ".",
127 ".----." => "'",
128 ".-..-." => "\"",
129 "..--.." => "?",
130 "-..-." => "/",
131 "-...-" => "=",
132 ".-.-." => "+",
133 "-....-" => "-",
134 "-.--." => "(",
135 "-.--.-" => ")",
136 "/" => " ",
137 "-.-.--" => "!",
138 " " => " ",
139 "" => "",
140 "\n" => " ",
143 "\r" => " ",
144 _ => return None,
145 };
146
147 Some(result)
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153 use crate::checkers::athena::Athena;
154 use crate::checkers::checker_type::{Check, Checker};
155 use crate::checkers::CheckerTypes;
156 use crate::decoders::interface::Crack;
157
158 fn get_athena_checker() -> CheckerTypes {
160 let athena_checker = Checker::<Athena>::new();
161 CheckerTypes::CheckAthena(athena_checker)
162 }
163
164 #[test]
165 fn test_morse_code() {
166 let decoder = Decoder::<MorseCodeDecoder>::new();
167 let result = decoder.crack(
168 ".---- ----. ..--- .-.-.- .---- -.... ---.. .-.-.- ----- .-.-.- .----",
169 &get_athena_checker(),
170 );
171 assert_eq!(result.unencrypted_text.unwrap()[0], "192.168.0.1");
172 }
173 #[test]
174 fn test_morse_code_new_line() {
175 let decoder = Decoder::<MorseCodeDecoder>::new();
176 let result = decoder.crack(
177 ".---- ----. ..--- .-.-.- .---- -.... ---.. .-.-.- ----- .-.-.- .----\n",
178 &get_athena_checker(),
179 );
180 assert_eq!(result.unencrypted_text.unwrap()[0], "192.168.0.1");
181 }
182 #[test]
183 fn test_morse_code_new_line_with_space() {
184 let decoder = Decoder::<MorseCodeDecoder>::new();
185 let result = decoder.crack(
186 ".---- ----. ..--- .-.-.- .---- -.... ---.. .-.-.- ----- .-.-.- .---- \n",
187 &get_athena_checker(),
188 );
189 assert_eq!(result.unencrypted_text.unwrap()[0], "192.168.0.1");
190 }
191 #[test]
192 fn test_morse_code_carrage_arrage_return_with_space() {
193 let decoder = Decoder::<MorseCodeDecoder>::new();
194 let result = decoder.crack(
195 ".---- ----. ..--- .-.-.- .---- -.... ---.. .-.-.- ----- .-.-.- .---- \r",
196 &get_athena_checker(),
197 );
198 assert_eq!(result.unencrypted_text.unwrap()[0], "192.168.0.1");
199 }
200
201 #[test]
202 fn test_morse_code_both_new_line_and_carrage_return() {
203 let decoder = Decoder::<MorseCodeDecoder>::new();
204 let result = decoder.crack(
205 ".---- ----. \n..--- .-.-.- \r.---- -.... ---.. .-.-.- ----- .-.-.- .---- \r",
206 &get_athena_checker(),
207 );
208 assert_eq!(result.unencrypted_text.unwrap()[0], "192.168.0.1");
209 }
210
211 #[test]
212 #[ignore]
214 fn test_morse_code_backslash() {
215 let decoder = Decoder::<MorseCodeDecoder>::new();
216 let result = decoder.crack(
217 r".... . .-.. .-.. ---\.-- --- .-. .-.. -.. -.-.--",
218 &get_athena_checker(),
219 );
220 assert_eq!(result.unencrypted_text.unwrap()[0], "hello world!");
221 }
222 #[test]
223 #[ignore]
227 fn test_morse_code_line_feed() {
228 let decoder = Decoder::<MorseCodeDecoder>::new();
229 let result = decoder.crack(
230 r".... . .-.. .-.. ---
231 .-- --- .-. .-.. -.. -.-.--",
232 &get_athena_checker(),
233 );
234 assert_eq!(result.unencrypted_text.unwrap()[0], "hello world!");
235 }
236 #[test]
237 #[ignore]
240 fn test_morse_code_comma() {
241 let decoder = Decoder::<MorseCodeDecoder>::new();
242 let result = decoder.crack(
243 r".... . .-.. .-.. ---,.-- --- .-. .-.. -.. -.-.--",
244 &get_athena_checker(),
245 );
246 assert_eq!(result.unencrypted_text.unwrap()[0], "hello world!");
247 }
248
249 #[test]
250 #[ignore]
253 fn test_morse_code_colon() {
254 let decoder = Decoder::<MorseCodeDecoder>::new();
255 let result = decoder.crack(
256 r".... . .-.. .-.. ---:.-- --- .-. .-.. -.. -.-.--",
257 &get_athena_checker(),
258 );
259 assert_eq!(result.unencrypted_text.unwrap()[0], "hello world!");
260 }
261}