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