mirror of
https://github.com/jixunmoe/tc_tea_rust
synced 2026-03-08 04:29:49 +00:00
74 lines
2.2 KiB
Rust
74 lines
2.2 KiB
Rust
use byteorder::{ByteOrder, BE};
|
|
|
|
// Tencent chooses 16 rounds instead of traditional 32 rounds.
|
|
const ROUNDS: u32 = 16;
|
|
const DELTA: u32 = 0x9e3779b9;
|
|
|
|
/// Perform a single round of encrypting/decrypting wrapping arithmetics
|
|
fn ecb_single_round(value: u32, sum: u32, key1: u32, key2: u32) -> u32 {
|
|
let left = value.wrapping_shl(4).wrapping_add(key1);
|
|
let right = value.wrapping_shr(5).wrapping_add(key2);
|
|
let mid = sum.wrapping_add(value);
|
|
|
|
left ^ mid ^ right
|
|
}
|
|
|
|
/// Perform a 16 round TEA ECB encryption.
|
|
pub fn encrypt(block: &mut [u8; 8], k: &[u32; 4]) {
|
|
let mut y = BE::read_u32(&block[..4]);
|
|
let mut z = BE::read_u32(&block[4..]);
|
|
let mut sum = 0_u32;
|
|
|
|
for _ in 0..ROUNDS {
|
|
sum = sum.wrapping_add(DELTA);
|
|
|
|
y = y.wrapping_add(ecb_single_round(z, sum, k[0], k[1]));
|
|
z = z.wrapping_add(ecb_single_round(y, sum, k[2], k[3]));
|
|
}
|
|
|
|
BE::write_u32(&mut block[..4], y);
|
|
BE::write_u32(&mut block[4..], z);
|
|
}
|
|
|
|
/// Perform a 16 round TEA ECB decryption.
|
|
pub fn decrypt(block: &mut [u8; 8], key: &[u32; 4]) {
|
|
let mut y = BE::read_u32(&block[..4]);
|
|
let mut z = BE::read_u32(&block[4..]);
|
|
let mut sum = DELTA.wrapping_mul(ROUNDS);
|
|
|
|
for _ in 0..ROUNDS {
|
|
z = z.wrapping_sub(ecb_single_round(y, sum, key[2], key[3]));
|
|
y = y.wrapping_sub(ecb_single_round(z, sum, key[0], key[1]));
|
|
|
|
sum = sum.wrapping_sub(DELTA);
|
|
}
|
|
|
|
BE::write_u32(&mut block[..4], y);
|
|
BE::write_u32(&mut block[4..], z);
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_decryption() {
|
|
let mut data: [u8; 8] = [0x56, 0x27, 0x6b, 0xa9, 0x80, 0xb9, 0xec, 0x16];
|
|
let key: [u32; 4] = [0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f00];
|
|
let expected: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
|
|
|
|
decrypt(&mut data, &key);
|
|
assert_eq!(data, expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_encryption() {
|
|
let mut data: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
|
|
let key: [u32; 4] = [0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f00];
|
|
let expected: [u8; 8] = [0x56, 0x27, 0x6b, 0xa9, 0x80, 0xb9, 0xec, 0x16];
|
|
|
|
encrypt(&mut data, &key);
|
|
assert_eq!(data, expected);
|
|
}
|
|
}
|