tc_tea/
ecb_impl.rs

1// Tencent chooses 16 rounds instead of traditional 32 rounds.
2const ROUNDS: u32 = 16;
3const DELTA: u32 = 0x9e3779b9;
4
5/// Perform a single round of encrypting/decrypting wrapping arithmetics
6fn ecb_single_round(value: u32, sum: u32, key1: u32, key2: u32) -> u32 {
7    let left = value.wrapping_shl(4).wrapping_add(key1);
8    let right = value.wrapping_shr(5).wrapping_add(key2);
9    let mid = sum.wrapping_add(value);
10
11    left ^ mid ^ right
12}
13
14fn parse_tea_u64(state: u64) -> (u32, u32) {
15    let y = (state >> 32) as u32;
16    let z = state as u32;
17    (y, z)
18}
19
20fn make_tea_u64(y: u32, z: u32) -> u64 {
21    (y as u64) << 32 | (z as u64)
22}
23
24/// Perform a 16 round TEA ECB encryption.
25pub fn encrypt(block: u64, key: &[u32; 4]) -> u64 {
26    let (mut y, mut z) = parse_tea_u64(block);
27    let mut sum = 0_u32;
28
29    for _ in 0..ROUNDS {
30        sum = sum.wrapping_add(DELTA);
31
32        y = y.wrapping_add(ecb_single_round(z, sum, key[0], key[1]));
33        z = z.wrapping_add(ecb_single_round(y, sum, key[2], key[3]));
34    }
35
36    make_tea_u64(y, z)
37}
38
39/// Perform a 16 round TEA ECB decryption.
40pub fn decrypt(block: u64, key: &[u32; 4]) -> u64 {
41    let (mut y, mut z) = parse_tea_u64(block);
42    let mut sum = DELTA.wrapping_mul(ROUNDS);
43
44    for _ in 0..ROUNDS {
45        z = z.wrapping_sub(ecb_single_round(y, sum, key[2], key[3]));
46        y = y.wrapping_sub(ecb_single_round(z, sum, key[0], key[1]));
47
48        sum = sum.wrapping_sub(DELTA);
49    }
50
51    make_tea_u64(y, z)
52}