cryptatools_core/cryptography/classical/encryption/transpositional_ciphers/columnar_transposition.rs
1use std::sync::Arc;
2
3use crate::utils::alphabets::Alphabet;
4use crate::utils::alphabets::split_bytes_by_characters_representation;
5use crate::utils::alphabets::uniffy_opcode_group;
6
7pub struct ColumnarTranspositionAlgorithm {
8 alphabet: Arc<Alphabet>,
9}
10
11impl ColumnarTranspositionAlgorithm {
12 pub fn new(alphabet: Arc<Alphabet>) -> Self {
13 ColumnarTranspositionAlgorithm {
14 alphabet: alphabet
15 }
16 }
17
18 /// Encrypt the `plain_text` with the columnar transposition encryption algorithm `key`.
19 ///
20 /// An array with lines of size `key` is created with the `plain_text` argument. The cipher text is producted as output with reading the plain text, column by column, from top to bot, from lefgt to right.
21 /// The custom alphabet has been put in the constructor of the struct CaesarNumberAlgorithm.
22 ///
23 /// ```
24 /// use cryptatools_core::utils::alphabets::Alphabet;
25 /// use cryptatools_core::utils::convert::{Encode, Decode};
26 /// use cryptatools_core::cryptography::classical::encryption::transpositional_ciphers::columnar_transposition::ColumnarTranspositionAlgorithm;
27 ///
28 /// let printable_ascii_alphabet = Alphabet::new_empty().ascii_printable_only_encoding();
29 /// let key = 6;
30 /// let plain_text = "all work and no play makes johnny a dull boy".replace(" ", "").to_uppercase();
31 /// let plain_text_opcodes = Encode::encode(&printable_ascii_alphabet, String::from(plain_text));
32 /// let mut columnar = ColumnarTranspositionAlgorithm::new(printable_ascii_alphabet.into());
33 /// let cipher_text_opcodes = columnar.encrypt(plain_text_opcodes, 6);
34 /// let ascii_plain_text = Decode::from_u8_to_ascii(cipher_text_opcodes);
35 ///
36 /// assert_eq!(ascii_plain_text, "AKPKNLLALENLLNASYBWDYJAOONMODYROAHU");
37 /// ```
38 pub fn encrypt(&self, plain_text: Vec<u8>, key: u32) -> Vec<u8> {
39 let plain_text_group = split_bytes_by_characters_representation(&self.alphabet, plain_text);
40 let columns: Vec<Vec<u8>> = (0..key)
41 .flat_map(|collumn| (collumn..plain_text_group.len() as u32)
42 .step_by(key as usize)
43 .map(|i| plain_text_group[i as usize].clone()))
44 .collect();
45
46 uniffy_opcode_group(columns)
47 }
48
49 /// Decrypt the `cipher_text` with the columnar transposition encryption algorithm `key`.
50 ///
51 /// Exatcly same operation as `encrypt` method.
52 ///
53 /// ```
54 /// use cryptatools_core::utils::alphabets::Alphabet;
55 /// use cryptatools_core::utils::convert::{Encode, Decode};
56 /// use cryptatools_core::cryptography::classical::encryption::transpositional_ciphers::columnar_transposition::ColumnarTranspositionAlgorithm;
57 ///
58 /// let printable_ascii_alphabet = Alphabet::new_empty().ascii_printable_only_encoding();
59 /// let mut columnar = ColumnarTranspositionAlgorithm::new(printable_ascii_alphabet.into());
60 /// let cipher_text_ascii = String::from("AKPKNLLALENLLNASYBWDYJAOONMODYROAHU");
61 /// let opcodes_plain_text = Encode::from_ascii_to_u8(cipher_text_ascii);
62 /// let key = 6;
63 /// let plain_text_opcodes = columnar.decrypt(opcodes_plain_text, key);
64 /// let ascii_plain_text = Decode::from_u8_to_ascii(plain_text_opcodes);
65 ///
66 /// assert_eq!(ascii_plain_text, "all work and no play makes johnny a dull boy".replace(" ", "").to_uppercase());
67 /// ```
68 pub fn decrypt(&self, cipher_text: Vec<u8>, key: u32) -> Vec<u8> {
69 let cipher_text_group = split_bytes_by_characters_representation(&self.alphabet, cipher_text);
70 let columns: Vec<Vec<u8>> = (0..key)
71 .flat_map(|collumn| (collumn..cipher_text_group.len() as u32)
72 .step_by(key as usize)
73 .map(|i| cipher_text_group[i as usize].clone()))
74 .collect();
75
76 uniffy_opcode_group(columns)
77 }
78}