use crate::{
AtomClass,
AtomType,
CryptoError,
};
#[cfg(any(
feature = "base16",
feature = "base32",
feature = "base32hex",
feature = "caesar",
feature = "vigenere",
feature = "hex"
))]
use crate::CaseInsensitiveCiphertext;
#[cfg(feature = "cipher")]
use crate::cipher::{
Cipher,
Key,
};
#[cfg(feature = "caesar")]
use crate::cipher::shift_cipher::CaesarContext;
#[cfg(feature = "vigenere")]
use crate::cipher::shift_cipher::VigenereContext;
#[cfg(any(
feature = "base16",
feature = "hex"
))]
use crate::code::base_encoding::Base16Context;
#[cfg(feature = "base32")]
use crate::code::base_encoding::Base32Context;
#[cfg(feature = "base32hex")]
use crate::code::base_encoding::Base32HexContext;
#[cfg(feature = "base64")]
use crate::code::base_encoding::Base64Context;
#[cfg(feature = "base64url")]
use crate::code::base_encoding::Base64UrlContext;
#[cfg(feature = "code")]
use crate::code::Code;
#[cfg(feature = "digest")]
use crate::digest::Digest;
#[cfg(any(
feature = "cipher",
feature = "code"
))]
#[derive(Clone, Copy, PartialEq)]
pub enum Direction {
ToCipher,
ToPlain,
}
#[derive(Clone)]
pub struct CryptographicAction {
crypto_class: AtomClass,
#[cfg(any(
feature = "cipher",
feature = "code"
))]
direction: Option<Direction>,
#[cfg(feature = "cipher")]
cipher: Option<Box<dyn Cipher>>,
#[cfg(feature = "code")]
code: Option<Box<dyn Code>>,
#[cfg(feature = "digest")]
digest: Option<Box<dyn Digest>>,
}
#[cfg(any(feature = "cipher", feature = "code", feature = "digest"))]
impl CryptographicAction {
pub fn execute(
&mut self,
input: &Vec<u8>,
) -> Result<Vec<u8>, CryptoError> {
match self.crypto_class {
#[cfg(feature = "cipher")]
AtomClass::Cipher => {
if self.direction == Some(Direction::ToCipher) {
self.cipher.as_mut().unwrap().encrypt(input)
} else {
self.cipher.as_mut().unwrap().decrypt(input)
}
}
#[cfg(feature = "code")]
AtomClass::Code => {
if self.direction == Some(Direction::ToCipher) {
self.code.as_mut().unwrap().encode(input)
} else {
self.code.as_mut().unwrap().decode(input)
}
}
#[cfg(feature = "digest")]
AtomClass::Digest => {
todo!["Action::execute(&mut CryptographicAction, input: Vec<u8>) -> ... for digest"];
}
}
}
#[cfg(feature = "cipher")]
pub fn new_cipher_action(
algorithm: Box<dyn Cipher>,
direction: Direction,
) -> CryptographicAction {
CryptographicAction {
crypto_class: algorithm.get_atom_class(),
direction: Some(direction),
cipher: Some(algorithm),
#[cfg(feature = "code")]
code: None,
#[cfg(feature = "digest")]
digest: None,
}
}
#[cfg(feature = "code")]
pub fn new_code_action(
algorithm: Box<dyn Code>,
direction: Direction,
) -> CryptographicAction {
CryptographicAction {
crypto_class: algorithm.get_atom_class(),
direction: Some(direction),
#[cfg(feature = "cipher")]
cipher: None,
code: Some(algorithm),
#[cfg(feature = "digest")]
digest: None,
}
}
}
impl PartialEq for CryptographicAction {
fn eq(
&self,
other: &Self,
) -> bool {
let mut is_equal = self.direction == other.direction &&
self.crypto_class == other.crypto_class;
#[cfg(feature = "cipher")] {
is_equal = is_equal && ((self.cipher.is_none() && other.cipher.is_none()) ||
(self.cipher.is_some() && other.cipher.is_some() &&
self.cipher.as_ref().unwrap().get_atom_class()
== other.cipher.as_ref().unwrap().get_atom_class() &&
self.cipher.as_ref().unwrap().get_atom_type()
== other.cipher.as_ref().unwrap().get_atom_type() &&
self.cipher.as_ref().unwrap().ciphertext_is_capitalized()
== other.cipher.as_ref().unwrap().ciphertext_is_capitalized() &&
self.cipher.as_ref().unwrap().get_key()
== other.cipher.as_ref().unwrap().get_key()));
}
#[cfg(feature = "code")] {
is_equal = is_equal && ((self.code.is_none() && other.code.is_none()) ||
(self.code.is_some() && other.code.is_some() &&
self.code.as_ref().unwrap().get_atom_class()
== other.code.as_ref().unwrap().get_atom_class() &&
self.code.as_ref().unwrap().get_atom_type()
== other.code.as_ref().unwrap().get_atom_type() &&
self.code.as_ref().unwrap().ciphertext_is_capitalized()
== other.code.as_ref().unwrap().ciphertext_is_capitalized()));
}
#[cfg(feature = "digest")] {
is_equal = is_equal && ((self.digest.is_none() && other.digest.is_none())
|| (self.digest.is_some() && other.digest.is_some()
&& self.digest.unwrap().get_atom_class() == self.digest.unwrap().get_atom_class()
&& self.digest.unwrap().get_atom_type() == self.digest.unwrap().get_atom_type()
&& self.digest.unwrap().ciphertext_is_capitalized()
== self.digest.unwrap().ciphertext_is_capitalized()))
}
is_equal
}
}
#[cfg(feature = "cipher")]
impl Clone for Box<dyn Cipher> {
fn clone(
&self
) -> Self {
match self.get_atom_type() {
#[cfg(feature = "caesar")]
AtomType::Caesar => {
let mut ctx = CaesarContext::new();
ctx.set_ciphertext_capitalization(self.ciphertext_is_capitalized().unwrap());
if let Some(key) = self.get_key() {
let _ = ctx.set_key(key);
}
Box::from(ctx)
}
#[cfg(feature = "vigenere")]
AtomType::Vigenere => {
let mut ctx = VigenereContext::new();
ctx.set_ciphertext_capitalization(self.ciphertext_is_capitalized().unwrap());
if let Some(key) = self.get_key()
{
let _ = ctx.set_key(key);
}
Box::from(ctx)
}
#[cfg(any(feature = "code", feature = "digest"))]
_ => { panic!["Inappropriate AtomType during cloning of Box<dyn Cipher>!"] }
}
}
}
#[cfg(feature = "code")]
impl Clone for Box<dyn Code> {
fn clone(
&self
) -> Self {
match self.get_atom_type() {
#[cfg(feature = "base64")]
AtomType::Base64 => {
let ctx = Base64Context::new();
Box::from(ctx)
}
#[cfg(feature = "base64url")]
AtomType::Base64Url => {
let ctx = Base64UrlContext::new();
Box::from(ctx)
}
#[cfg(feature = "base32")]
AtomType::Base32 => {
let mut ctx = Base32Context::new();
ctx.set_ciphertext_capitalization(self.ciphertext_is_capitalized().unwrap());
Box::from(ctx)
}
#[cfg(feature = "base32hex")]
AtomType::Base32Hex => {
let mut ctx = Base32HexContext::new();
ctx.set_ciphertext_capitalization(self.ciphertext_is_capitalized().unwrap());
Box::from(ctx)
}
#[cfg(any(feature = "base16", feature = "hex"))]
AtomType::Base16 => {
let mut ctx = Base16Context::new();
ctx.set_ciphertext_capitalization(self.ciphertext_is_capitalized().unwrap());
Box::from(ctx)
}
#[cfg(any(feature = "cipher", feature = "digest"))]
_ => { panic!["Inappropriate AtomType during cloning of Box<dyn Code>!"]; }
}
}
}
#[cfg(feature = "digest")]
impl Clone for Box<dyn Digest> {
fn clone(
&self
) -> Self {
todo!["Clone::clone(&Box<dyn Digest>) -> Box<dyn Digest>"];
}
}