mirror of
https://github.com/jixunmoe/tc_tea_rust
synced 2026-03-07 20:19:49 +00:00
refactor: use u64 instead of u8[8] buffer; allow user to override salt.
This commit is contained in:
@@ -17,12 +17,13 @@ categories = ["cryptography"]
|
|||||||
maintenance = { status = "as-is" }
|
maintenance = { status = "as-is" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
byteorder = "1.5.0"
|
||||||
thiserror = "1.0.63"
|
thiserror = "1.0.63"
|
||||||
rand = { version = "0.8.5" }
|
rand = { version = "0.8.5", optional = true }
|
||||||
rand_chacha = { version = "0.3.1", optional = true }
|
rand_chacha = { version = "0.3.1", optional = true }
|
||||||
rand_pcg = { version = "0.3.1", optional = true }
|
rand_pcg = { version = "0.3.1", optional = true }
|
||||||
byteorder = "1.5.0"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rand_pcg"]
|
default = ["random", "random_secure"]
|
||||||
secure_random = ["rand/getrandom", "rand/rand_chacha", "rand_chacha"]
|
random = ["rand", "rand_pcg"]
|
||||||
|
random_secure = ["rand/getrandom", "rand/rand_chacha", "rand_chacha"]
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ pub fn encrypt<'a>(
|
|||||||
let copy_to_header_len = min(16 - header_len, plain.len());
|
let copy_to_header_len = min(16 - header_len, plain.len());
|
||||||
let (plain_header, plain) = plain.split_at(copy_to_header_len);
|
let (plain_header, plain) = plain.split_at(copy_to_header_len);
|
||||||
|
|
||||||
header[0] = (header[0] & 0b1111_1000) | ((pad_len as u8) & 0b0000_0111);
|
header[0] = (header[0] & !7) | ((pad_len as u8) & 7);
|
||||||
header[header_len..header_len + copy_to_header_len].copy_from_slice(plain_header);
|
header[header_len..header_len + copy_to_header_len].copy_from_slice(plain_header);
|
||||||
|
|
||||||
// Access to slice of "cipher" from inner scope
|
// Access to slice of "cipher" from inner scope
|
||||||
|
|||||||
86
src/lib.rs
86
src/lib.rs
@@ -3,13 +3,11 @@
|
|||||||
//! Notably, it uses a different round number and uses a "tweaked" CBC mode.
|
//! Notably, it uses a different round number and uses a "tweaked" CBC mode.
|
||||||
|
|
||||||
use byteorder::{ByteOrder, BE};
|
use byteorder::{ByteOrder, BE};
|
||||||
use rand::RngCore;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
pub mod cbc;
|
pub mod cbc;
|
||||||
pub mod ecb;
|
pub mod ecb;
|
||||||
mod ecb_impl;
|
mod ecb_impl;
|
||||||
use rand::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Error, Debug, PartialEq)]
|
#[derive(Error, Debug, PartialEq)]
|
||||||
pub enum TcTeaError {
|
pub enum TcTeaError {
|
||||||
@@ -50,48 +48,70 @@ pub fn parse_key(key: &[u8]) -> Result<[u32; 4], TcTeaError> {
|
|||||||
Ok(parsed)
|
Ok(parsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encrypts an arbitrary length sized data in the following way:
|
/// Generate salt for encryption function (or fixed salt if we are not using them)
|
||||||
///
|
fn generate_salt() -> [u8; 10] {
|
||||||
/// * PadLen (1 byte)
|
#[cfg(not(feature = "random"))]
|
||||||
/// * Padding (variable, 0-7byte)
|
{
|
||||||
/// * Salt (2 bytes)
|
// Chosen by fair dice roll.
|
||||||
/// * Body (? bytes)
|
// Guaranteed to be random.
|
||||||
/// * Zero (7 bytes)
|
[0xA5, 0x6E, 0x35, 0xBC, 0x7C, 0x31, 0x04, 0x55, 0xA0, 0xBF]
|
||||||
///
|
}
|
||||||
/// Returned bytes will always have a length multiple of 8.
|
|
||||||
///
|
#[cfg(feature = "random")]
|
||||||
/// PadLen/Padding/Salt are randomly bytes, with a minimum of 21 bits (3 * 8 - 3) randomness.
|
{
|
||||||
|
use rand::RngCore;
|
||||||
|
use rand::prelude::*;
|
||||||
|
|
||||||
|
let mut salt = [0u8; 10];
|
||||||
|
|
||||||
|
#[cfg(not(feature = "random_secure"))]
|
||||||
|
rand_pcg::Pcg32::from_entropy().fill_bytes(&mut salt);
|
||||||
|
|
||||||
|
#[cfg(feature = "random_secure")]
|
||||||
|
rand_chacha::ChaCha20Rng::from_entropy().fill_bytes(&mut salt);
|
||||||
|
|
||||||
|
salt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encrypts given plain text using tc_tea.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// If random number generator fails, it will panic.
|
/// If random number generator fails, it will panic.
|
||||||
pub fn encrypt<T: AsRef<[u8]>>(plaintext: T, key: &[u8]) -> Result<Vec<u8>, TcTeaError> {
|
pub fn encrypt<T, K>(plaintext: T, key: K) -> Result<Vec<u8>, TcTeaError>
|
||||||
let key = parse_key(key)?;
|
where
|
||||||
|
T: AsRef<[u8]>,
|
||||||
|
K: AsRef<[u8]>,
|
||||||
|
{
|
||||||
|
encrypt_with_salt(plaintext, key, &generate_salt())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encrypts given plain text using tc_tea.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// If random number generator fails, it will panic.
|
||||||
|
pub fn encrypt_with_salt<T, K>(plaintext: T, key: K, salt: &[u8; 10]) -> Result<Vec<u8>, TcTeaError>
|
||||||
|
where
|
||||||
|
T: AsRef<[u8]>,
|
||||||
|
K: AsRef<[u8]>,
|
||||||
|
{
|
||||||
|
let key = parse_key(key.as_ref())?;
|
||||||
let plaintext = plaintext.as_ref();
|
let plaintext = plaintext.as_ref();
|
||||||
let cipher_len = get_encrypted_size(plaintext.len());
|
let cipher_len = get_encrypted_size(plaintext.len());
|
||||||
let mut cipher = vec![0u8; cipher_len];
|
let mut cipher = vec![0u8; cipher_len];
|
||||||
|
|
||||||
let mut salt = [0u8; 10];
|
|
||||||
#[cfg(feature = "secure_random")]
|
|
||||||
rand_chacha::ChaCha20Rng::from_entropy().fill_bytes(&mut salt);
|
|
||||||
#[cfg(not(feature = "secure_random"))]
|
|
||||||
rand_pcg::Pcg32::from_entropy().fill_bytes(&mut salt);
|
|
||||||
|
|
||||||
cbc::encrypt(&mut cipher, plaintext, &key, &salt)?;
|
cbc::encrypt(&mut cipher, plaintext, &key, &salt)?;
|
||||||
Ok(cipher)
|
Ok(cipher)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decrypts a byte array containing the following:
|
/// Decrypts tc_tea encrypted data.
|
||||||
///
|
pub fn decrypt<T, K>(encrypted: T, key: K) -> Result<Vec<u8>, TcTeaError>
|
||||||
/// * PadLen (1 byte)
|
where
|
||||||
/// * Padding (variable, 0-7byte)
|
T: AsRef<[u8]>,
|
||||||
/// * Salt (2 bytes)
|
K: AsRef<[u8]>,
|
||||||
/// * Body (? bytes)
|
{
|
||||||
/// * Zero (7 bytes)
|
let key = parse_key(key.as_ref())?;
|
||||||
///
|
|
||||||
/// PadLen is taken from the last 3 bit of the first byte.
|
|
||||||
pub fn decrypt<T: AsRef<[u8]>>(encrypted: T, key: &[u8]) -> Result<Vec<u8>, TcTeaError> {
|
|
||||||
let key = parse_key(key)?;
|
|
||||||
let encrypted = encrypted.as_ref();
|
let encrypted = encrypted.as_ref();
|
||||||
let mut plain = vec![0u8; encrypted.len()];
|
let mut plain = vec![0u8; encrypted.len()];
|
||||||
let result = cbc::decrypt(&mut plain, encrypted, &key)?;
|
let result = cbc::decrypt(&mut plain, encrypted, &key)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user