encodex 0.2.0

Implementation of and cryptanalysis tool for legacy and modern codes, ciphers and hashes.
Documentation
// Copyright (C) 2023  Fabian Moos
// This file is part of encodex.
//
// encodex is free software: you can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// encodex is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
// even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with encodex. If not,
// see <https://www.gnu.org/licenses/>.
//

//! All implemented ciphers.
//!
//! Ciphers use at least a key and sometimes additional credentials to encrypt a plaintext into a
//! ciphertext. By encrypting the plaintext ciphers provide confidentiality, because only the person
//! that knows the key can decrypt the ciphertext back into the plaintext.
//!
//! Different ciphers use different credentials and even different keys to provide different levels
//! of confidentiality.
//!
//! More information about a specific cipher can be found in their respective module's
//! documentation.

#[cfg(feature = "shift_cipher")]
pub mod shift_cipher;

use super::{
    CryptoError,
    CryptographicAtom,
};



/// Trait for ciphers.
///
/// Every cipher in this crate implements this trait. That ensures that all ciphers can be treated
/// in a generic way.
pub trait Cipher: CryptographicAtom + Decrypt + Encrypt + Key {}

/// Trait for the decrypt operation of a [`Cipher`] object.
pub trait Decrypt {
    /// Decrypts a ciphertext into a plaintext.
    fn decrypt(
        &mut self,
        ciphertext: &Vec<u8>,
    ) -> Result<Vec<u8>, CryptoError>;
}

/// Trait for the encrypt operation of a [`Cipher`] object.
pub trait Encrypt {
    /// Encrypts a plaintext into a ciphertext.
    fn encrypt(
        &mut self,
        plaintext: &Vec<u8>,
    ) -> Result<Vec<u8>, CryptoError>;
}

/// Trait for key operations on [`Cipher`] objects.
pub trait Key {
    /// Returns the key of a [`Cipher`].
    ///
    /// If no key has been set yet, this method **should** return [`None`].
    fn get_key(
        &self
    ) -> Option<&Vec<u8>>;
    /// Sets the `key` for a [`Cipher`].
    ///
    /// If the key is invalid and cannot be turned into a valid key, an error **should** be
    /// returned. E.g. a key that is too long can maybe just be truncated to fit the required key
    /// size.
    fn set_key(
        &mut self,
        key: &Vec<u8>,
    ) -> Result<(), CryptoError>;
}



/// Shifts the numerical value of a byte. This especially means, that this function does not perform
/// a bit shift.
///
/// # Panics
///
/// This function panics if a `modulo` of `0` is given as argument.
#[cfg(any(feature = "shift_cipher", test))]
fn shift_byte(
    value: u8,
    distance: u8,
    shift_left: bool,
    modulo: u8,
) -> u8 {
    let value = value % modulo;
    let distance = distance % modulo;
    if shift_left {
        (value + (modulo - distance)) % modulo
    } else {
        (value + distance) % modulo
    }
}



/// Test vectors for module [`cipher`](crate::cipher).
#[cfg(any(test, feature = "doc_tests"))]
mod tests {
    use super::*;

    /// Tests the [`shift_byte`] function.
    ///
    /// This test checks if a shift with underflow is done correctly when the `value` is higher than
    /// the given `modulo`.
    #[cfg_attr(not(feature = "doc_tests"), test)]
    fn test_01() {
        assert_eq![shift_byte(7, 3, true, 5), 4];
    }

    /// Tests the [`shift_byte`] function.
    ///
    /// This test checks if a shift with underflow is done correctly when all values are lower than
    /// the given `modulo`.
    #[cfg_attr(not(feature = "doc_tests"), test)]
    fn test_02() {
        assert_eq![shift_byte(3, 4, true, 255), 254];
    }

    /// Tests the [`shift_byte`] function.
    ///
    /// This test checks if a shift is done correctly when the shift `distance` is higher than the
    /// modulo.
    #[cfg_attr(not(feature = "doc_tests"), test)]
    fn test_03() {
        assert_eq![shift_byte(7, 37, true, 13), 9]
    }

    /// Tests the [`shift_byte`] function.
    ///
    /// This test checks if a shift is done correctly when neither `value` nor `distance` nor its
    /// sum is higher than the modulo.
    #[cfg_attr(not(feature = "doc_tests"), test)]
    fn test_04() {
        assert_eq![shift_byte(1, 100, false, 255), 101];
    }

    /// Tests the [`shift_byte`] function.
    ///
    /// This test checks if a shift with overflow is done correctly when the sum of `value` and
    /// `distance` is higher than `modulo`.
    #[cfg_attr(not(feature = "doc_tests"), test)]
    fn test_05() {
        assert_eq![shift_byte(200, 55, false, 201), 54];
    }

    /// Tests the [`shift_byte`] function.
    ///
    /// This test checks if a shift with overflow is done correctly when both, `value` and
    /// `distance`, are higher than `modulo`.
    #[cfg_attr(not(feature = "doc_tests"), test)]
    fn test_06() {
        assert_eq![shift_byte(255, 105, false, 100), 60];
    }
}