1use std::iter::FromIterator;
16
17use crate::{BaconCodec, errors, Steganographer};
18use crate::errors::BaconError;
19
20#[derive(Debug, Clone, PartialEq)]
21pub struct Marker {
22 start_marker: Option<String>,
23 end_marker: Option<String>,
24}
25
26impl Marker {
27 pub fn new(start_marker: Option<&str>, end_marker: Option<&str>) -> Marker {
28 Marker {
29 start_marker: start_marker.map(|marker| marker.to_string()),
30 end_marker: end_marker.map(|marker| marker.to_string()),
31 }
32 }
33
34 pub fn empty() -> Marker {
35 Marker {
36 start_marker: None,
37 end_marker: None,
38 }
39 }
40
41 pub fn is_empty(&self) -> bool {
42 self == &Self::empty()
43 }
44
45 pub fn start_marker(&self) -> &Option<String> {
46 &self.start_marker
47 }
48
49 pub fn end_marker(&self) -> &Option<String> {
50 &self.end_marker
51 }
52
53 pub fn start_marker_string(&self) -> String {
54 self.start_marker().clone().unwrap_or("".to_string())
55 }
56
57 pub fn end_marker_string(&self) -> String {
58 self.end_marker().clone().unwrap_or("".to_string())
59 }
60}
61
62pub struct MarkdownSteganographer {
63 a_marker: Marker,
64 b_marker: Marker,
65}
66
67impl MarkdownSteganographer {
68 pub fn new(a_marker: Marker, b_marker: Marker) -> errors::Result<MarkdownSteganographer> {
69 match (&a_marker.start_marker, &a_marker.end_marker, &b_marker.start_marker, &b_marker.end_marker) {
70 (Some(asm), Some(aem), Some(bsm), Some(bem))
71 if asm.contains(bsm) || asm.contains(bem) ||
72 aem.contains(bsm) || aem.contains(bem) ||
73 bsm.contains(asm) || bsm.contains(aem) ||
74 bem.contains(asm) || bem.contains(aem) => {
75 Err(BaconError::SteganographerError(format!("Cannot create a marker with {:?} and {:?}", a_marker, b_marker)))
76 }
77 (None, None, None, None) => {
78 Err(BaconError::SteganographerError(format!("Cannot create a marker with both A and B undefined")))
79 }
80 (Some(_), None, _, _) |
81 (None, Some(_), _, _) |
82 (_, _, Some(_), None) |
83 (_, _, None, Some(_)) => {
84 Err(BaconError::SteganographerError(format!("A marker should define both start and end")))
85 }
86 _ => {
87 Ok(MarkdownSteganographer {
88 a_marker,
89 b_marker,
90 })
91 }
92 }
93 }
94
95 fn find_first_occurence_of(&self, input_type: ParsedInputType, input: &str) -> Option<usize> {
96 match input_type {
97 ParsedInputType::A => {
98 self.a_marker.start_marker.as_ref()
99 .and_then(|start| input.find(start.as_str()))
100 }
101 ParsedInputType::B => {
102 self.b_marker.start_marker.as_ref()
103 .and_then(|start| input.find(start.as_str()))
104 }
105 _ => None
106 }
107 }
108
109 fn parse(&self, input: &str) -> Vec<ParsedInputElement> {
110 let mut input = input;
111 let mut input_elements: Vec<ParsedInputElement> = Vec::new();
112
113 loop {
115 let a_start_index = self.find_first_occurence_of(ParsedInputType::A, input).unwrap_or(input.len());
117 let b_start_index = self.find_first_occurence_of(ParsedInputType::B, input).unwrap_or(input.len());
118
119 let (start_index, parsed_input_type) = if a_start_index < b_start_index {
120 (a_start_index, ParsedInputType::A)
121 } else if b_start_index < a_start_index {
122 (b_start_index, ParsedInputType::B)
123 } else {
124 (input.len(), ParsedInputType::Other)
125 };
126
127 let start_size = match parsed_input_type {
128 ParsedInputType::A => self.a_marker.start_marker.as_ref().unwrap().len(),
129 ParsedInputType::B => self.b_marker.start_marker.as_ref().unwrap().len(),
130 _ => 0,
131 };
132 let tmp: &str = &input[(start_index + start_size)..input.len()];
134 let (end_opt, end_size) = match parsed_input_type {
135 ParsedInputType::A => (self.a_marker.end_marker.as_ref(), self.a_marker.end_marker_string().len()),
136 ParsedInputType::B => (self.b_marker.end_marker.as_ref(), self.b_marker.end_marker_string().len()),
137 _ => (None, 0),
138 };
139 let end_index = (end_opt
140 .and_then(|end| tmp.find(end.as_str()))
141 .unwrap_or(tmp.len() - end_size)) + end_size;
144 if end_index > 0 {
145 let input_element: &str = &tmp[0..(end_index - end_size)];
146 input_elements.push(ParsedInputElement::new(input_element.to_string(), parsed_input_type.clone()));
147 } else {
148 break;
149 }
150 if tmp.len() <= end_index {
151 input = "";
152 } else {
153 input = &tmp[end_index..tmp.len()];
154 }
155 }
156 input_elements
157 }
158
159
160 fn replace_unmarked_characters_with(input_string: String, parsed_input_elements: Vec<ParsedInputElement>, start_marker_of_parsed_input_element: &str, end_marker_of_parsed_input_element: &str, parsed_input_type: ParsedInputType) -> Vec<ParsedInputElement> {
168 let mut input_string = input_string;
169 let mut new_parsed_input_elements: Vec<ParsedInputElement> = Vec::new();
170 for pie in parsed_input_elements.into_iter() {
171 let parsed_input_element_string = format!("{}{}{}",
173 start_marker_of_parsed_input_element,
174 pie.string,
175 end_marker_of_parsed_input_element);
176 let index = input_string.find(&parsed_input_element_string).unwrap_or(input_string.len());
178 let substring: &str = &input_string[0..index];
180 for c in substring.chars() {
182 new_parsed_input_elements.push(ParsedInputElement::new(c.to_string(), parsed_input_type.clone()));
183 }
184 new_parsed_input_elements.push(pie);
186 input_string = input_string.replace(&format!("{}{}", substring, parsed_input_element_string), "");
188 }
189 for c in input_string.chars().into_iter() {
191 new_parsed_input_elements.push(ParsedInputElement::new(c.to_string(), parsed_input_type.clone()));
192 }
193
194 new_parsed_input_elements
195 }
196}
197
198impl Steganographer for MarkdownSteganographer {
199 type T = char;
200
201 fn disguise<AB>(&self, secret: &[char], public: &[char], codec: &dyn BaconCodec<ABTYPE=AB, CONTENT=char>) -> errors::Result<Vec<char>> {
202 let encoded = codec.encode(secret);
203
204 let mut disguised = String::new();
205 let mut i = 0;
206
207 for pc in public {
208 if pc.is_alphabetic() {
209 let opt = encoded.get(i);
210 if opt.is_some() && codec.is_a(opt.unwrap()) {
211 disguised.push_str(&format!("{}{}{}",
212 self.a_marker.start_marker_string(),
213 pc.clone(),
214 self.a_marker.end_marker_string()));
215 i = i + 1;
216 } else if opt.is_some() && codec.is_b(opt.unwrap()) {
217 disguised.push_str(&format!("{}{}{}",
218 self.b_marker.start_marker_string(),
219 pc.clone(),
220 self.b_marker.end_marker_string()));
221 i = i + 1;
222 } else {
223 disguised.push(pc.clone())
224 }
225 } else {
226 disguised.push(pc.clone())
227 }
228 }
229
230 Ok(disguised
231 .replace(&format!("{}{}", self.a_marker.end_marker_string(), self.a_marker.start_marker_string()), "")
232 .replace(&format!("{}{}", self.b_marker.end_marker_string(), self.b_marker.start_marker_string()), "")
233 .chars().collect())
234 }
235
236 fn reveal<AB>(&self, input: &[char], codec: &dyn BaconCodec<ABTYPE=AB, CONTENT=Self::T>) -> errors::Result<Vec<char>> {
237 let input_string: String = String::from_iter(input.iter());
238 let parsed_input_elements = self.parse(&input_string);
239 let new_parsed_input_elements: Vec<ParsedInputElement>;
240 if self.b_marker.is_empty() {
241 new_parsed_input_elements = Self::replace_unmarked_characters_with(input_string, parsed_input_elements, self.a_marker.start_marker.as_ref().unwrap_or(&"".to_string()), self.a_marker.end_marker.as_ref().unwrap_or(&"".to_string()), ParsedInputType::B);
242 } else if self.a_marker.is_empty() {
243 new_parsed_input_elements = Self::replace_unmarked_characters_with(input_string, parsed_input_elements, self.b_marker.start_marker.as_ref().unwrap_or(&"".to_string()), self.b_marker.end_marker.as_ref().unwrap_or(&"".to_string()), ParsedInputType::A);
244 } else {
245 new_parsed_input_elements = parsed_input_elements;
246 }
247 let encoded: Vec<AB> = new_parsed_input_elements.iter()
248 .map(|elem| {
249 if elem.tp == ParsedInputType::A {
250 let v: Vec<AB> = elem.string.chars()
251 .filter(|sc| sc.is_alphabetic())
252 .map(|_| codec.a())
253 .collect();
254 v
255 } else {
256 let v: Vec<AB> = elem.string.chars()
257 .filter(|sc| sc.is_alphabetic())
258 .map(|_| codec.b())
259 .collect();
260 v
261 }
262 })
263 .flat_map(|m| m)
264 .collect();
265 Ok(codec.decode(&encoded))
266 }
267}
268
269#[derive(Debug, PartialEq)]
270struct ParsedInputElement {
271 string: String,
272 tp: ParsedInputType,
273}
274
275impl ParsedInputElement {
276 fn new(string: String, tp: ParsedInputType) -> ParsedInputElement {
277 ParsedInputElement { string, tp }
278 }
279}
280
281#[derive(Clone, Debug, PartialEq)]
282enum ParsedInputType {
283 A,
284 B,
285 Other,
286}
287
288#[cfg(test)]
289mod markdown_tests {
290 use std::iter::FromIterator;
291
292 use crate::codecs::char_codec::CharCodec;
293
294 use super::*;
295
296 #[test]
297 fn markers_creation() {
298 let m1 = Marker::new(None, None);
299 assert!(m1.start_marker() == &None);
300 assert!(m1.end_marker() == &None);
301
302 let m2 = Marker::new(Some("_"), Some("_"));
303 assert!(m2.start_marker() == &Some("_".to_string()));
304 assert!(m2.end_marker() == &Some("_".to_string()));
305
306 let m3 = Marker::empty();
307 assert!(m3.start_marker() == &None);
308 assert!(m3.end_marker() == &None);
309 }
310
311 #[test]
312 fn markers_to_string() {
313 let m = Marker::new(Some("__"), Some("__"));
314 assert!(m.start_marker_string() == ("__"));
315 assert!(m.end_marker_string() == ("__"));
316 }
317
318 #[test]
319 fn steganographer_creation_failure() {
320 let res = MarkdownSteganographer::new(
321 Marker::new(
322 Some("*"),
323 Some("*")),
324 Marker::new(
325 Some("**"),
326 Some("**")));
327 assert!(res.is_err());
328 let res = MarkdownSteganographer::new(
329 Marker::new(
330 Some("*"),
331 Some("!")),
332 Marker::new(
333 Some("@"),
334 Some("**")));
335 assert!(res.is_err());
336 let res = MarkdownSteganographer::new(
337 Marker::new(
338 Some("!"),
339 Some("*")),
340 Marker::new(
341 Some("**"),
342 Some("@")));
343 assert!(res.is_err());
344 let res = MarkdownSteganographer::new(
345 Marker::new(
346 Some("**"),
347 Some("**")),
348 Marker::new(
349 Some("*"),
350 Some("*")));
351 assert!(res.is_err());
352 let res = MarkdownSteganographer::new(
353 Marker::new(
354 Some("**"),
355 Some("@")),
356 Marker::new(
357 Some("*"),
358 Some("!")));
359 assert!(res.is_err());
360 let res = MarkdownSteganographer::new(
361 Marker::new(
362 Some("@"),
363 Some("**")),
364 Marker::new(
365 Some("!"),
366 Some("*")));
367 assert!(res.is_err());
368 let res = MarkdownSteganographer::new(
369 Marker::new(
370 Some("**"),
371 Some("**")),
372 Marker::new(
373 Some("**"),
374 Some("**")));
375 assert!(res.is_err());
376 let res = MarkdownSteganographer::new(
377 Marker::empty(),
378 Marker::empty());
379 assert!(res.is_err());
380 let res = MarkdownSteganographer::new(
381 Marker::new(
382 Some("**"),
383 None),
384 Marker::new(
385 Some("**"),
386 Some("**")));
387 assert!(res.is_err());
388 let res = MarkdownSteganographer::new(
389 Marker::new(
390 None,
391 Some("**")),
392 Marker::new(
393 Some("**"),
394 Some("**")));
395 assert!(res.is_err());
396 let res = MarkdownSteganographer::new(
397 Marker::new(
398 Some("**"),
399 Some("**")),
400 Marker::new(
401 None,
402 Some("**")));
403 assert!(res.is_err());
404 let res = MarkdownSteganographer::new(
405 Marker::new(
406 Some("**"),
407 Some("**")),
408 Marker::new(
409 Some("**"),
410 None));
411 assert!(res.is_err());
412 }
413
414 #[test]
415 fn disguise_a_secret_to_a_char_array_define_b_marker() {
416 let codec = CharCodec::new('a', 'b');
417 let s = MarkdownSteganographer::new(
418 Marker::empty(),
419 Marker::new(
420 Some("*"),
421 Some("*"))).unwrap();
422
423 let public = "This is a public message that contains a secret one";
424 let output = s.disguise(
425 &['M', 'y', ' ', 's', 'e', 'c', 'r', 'e', 't'],
426 &Vec::from_iter(public.chars()),
427 &codec);
428 let string = String::from_iter(output.unwrap().iter());
429 assert!(string == "T*h*i*s* *is* a *pu*b*l*ic m*e*ss*a*ge tha*t* c*o*ntains *a* se*c*re*t* one");
430 }
431
432 #[test]
433 fn disguise_a_secret_to_a_char_array_define_a_marker() {
434 let codec = CharCodec::new('a', 'b');
435 let s = MarkdownSteganographer::new(
436 Marker::new(
437 Some("**"),
438 Some("**")),
439 Marker::empty()).unwrap();
440
441 let public = "This is a public message that contains a secret one";
442 let output = s.disguise(
443 &['M', 'y', ' ', 's', 'e', 'c', 'r', 'e', 't'],
444 &Vec::from_iter(public.chars()),
445 &codec);
446 let string = String::from_iter(output.unwrap().iter());
447 assert!(string == "**T**h**i**s is **a** pu**b**l**ic** **m**e**ss**a**ge** **tha**t **c**o**ntains** a **se**c**re**t **o**ne");
448 }
449
450 #[test]
451 fn disguise_a_secret_to_a_char_array_define_a_b_markers() {
452 let codec = CharCodec::new('a', 'b');
453 let s = MarkdownSteganographer::new(
454 Marker::new(
455 Some("*"),
456 Some("*")),
457 Marker::new(
458 Some("!"),
459 Some("!"))).unwrap();
460
461 let public = "This is a public message that contains a secret one";
462 let output = s.disguise(
463 &['M', 'y', ' ', 's', 'e', 'c', 'r', 'e', 't'],
464 &Vec::from_iter(public.chars()),
465 &codec);
466 let string = String::from_iter(output.unwrap().iter());
467 assert!(string == "*T*!h!*i*!s! !is! *a* !pu!*b*!l!*ic* *m*!e!*ss*!a!*ge* *tha*!t! *c*!o!*ntains* !a! *se*!c!*re*!t! *o*ne");
468 }
469
470 #[test]
471 fn reveal_a_secret_from_a_char_array_define_a_b_markers() {
472 let codec = CharCodec::new('a', 'b');
473 let s = MarkdownSteganographer::new(
474 Marker::new(
475 Some("*"),
476 Some("*")),
477 Marker::new(
478 Some("!"),
479 Some("!"))).unwrap();
480 let public = "*T*!h!*i*!s! !is! *a* !pu!*b*!l!*ic* *m*!e!*ss*!a!*ge* *tha*!t! *c*!o!*ntains* !a! *se*!c!*re*!t! *o*ne";
481 let output = s.reveal(
482 &Vec::from_iter(public.chars()),
483 &codec);
484 assert!(output.is_ok());
485 let string = String::from_iter(output.unwrap().iter());
486 assert!(string.starts_with("MYSECRET"));
487 }
488
489 #[test]
490 fn marker_is_empty() {
491 assert!(Marker::empty().is_empty());
492 assert!(!Marker::new(Some("*"), Some("*")).is_empty());
493 }
494
495 #[test]
496 fn reveal_a_secret_from_a_char_array_define_a_marker() {
497 let codec = CharCodec::new('a', 'b');
498 let s = MarkdownSteganographer::new(
499 Marker::new(
500 Some("**"),
501 Some("**")),
502 Marker::empty()).unwrap();
503 let public = "**T**h**i**s is **a** pu**b**l**ic** **m**e**ss**a**ge** **tha**t **c**o**ntains** a **se**c**re**t **o**ne";
504 let output = s.reveal(
505 &Vec::from_iter(public.chars()),
506 &codec);
507 assert!(output.is_ok());
508 let string = String::from_iter(output.unwrap().iter());
509 assert!(string.starts_with("MYSECRET"));
510 }
511
512 #[test]
513 fn reveal_a_secret_from_a_char_array_define_b_marker() {
514 let codec = CharCodec::new('a', 'b');
515 let s = MarkdownSteganographer::new(
516 Marker::empty(),
517 Marker::new(
518 Some("*"),
519 Some("*"))).unwrap();
520 let public = "T*h*i*s* *is* a *pu*b*l*ic m*e*ss*a*ge tha*t* c*o*ntains *a* se*c*re*t* one";
521 let output = s.reveal(
522 &Vec::from_iter(public.chars()),
523 &codec);
524 assert!(output.is_ok());
525 let string = String::from_iter(output.unwrap().iter());
526 assert!(string.starts_with("MYSECRET"));
527 }
528}