TEA

简介

TEA加密是一种经典的块加密,使用64位密文和128位(4个uint_32t)密钥,并使用Feistel框架进行加密
Feistel框架指的是将密文分成两个等长块,每轮加密对两个块分别施加轮加密函数并进行交换,这点在TEA中体现为v0的累加值由v1计算得到,反之亦然
注意使用TEA加密时如果密文小于64位(bit)要填充0字节占位,否则由于指针类型转换会将垃圾数据引入加密,当密文大于64位时要将密文分块分别执行TEA加密

特征

应主要关注其Feistel网络结构而不是关注常量,因为TEA加密的加密计算方式,计算轮次,累加常量均可以魔改,但是密文被分为两个块并在每轮加密中采用相似的加密函数这个特点是不会变的,同时关注每轮中v0,v1分别由v1,v0计算得到,密钥通常为128位即4个uint_32t

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
void teaEncrypt(uint32_t *v, uint32_t *k)
{
uint32_t sum = 0, v0 = v[0], v1 = v[1]; // 将输入分为两个32位的块
uint32_t delta = 0x9E3779B9; //初始常量,可以为任何数
for (int i = 0; i < 32; i++)
{
v0 += ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]); // 轮加密函数
sum += delta;
v1 += ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]); // 轮加密函数
}
v[0] = v0; // 应用修改
v[1] = v1;
}

解密

因为TEA加密是由Feistel框架设计来的,所以解密Feistel密码的方式对TEA也适用,我们只需根据加密完的最后状态,反向执行同样轮次的轮加密,就能解出明文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void teaDecrypt(uint32_t *v, uint32_t *k)
{
uint32_t sum = 0, v0 = v[0], v1 = v[1];
uint32_t delta = 0x9E3779B9;
sum = delta * 32; // 获取最终状态的累加和
for (int i = 0; i < 32; i++)
{
v1 -= ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]); // 因为v1是最后被计算的,所以解密时要先计算v1
sum -= delta; // 累加改为递减
v0 -= ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
}
v[0] = v0;
v[1] = v1;
}

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <bits/stdc++.h>
using namespace std;
void teaEncrypt(uint32_t *v, uint32_t *k)
{
uint32_t sum = 0, v0 = v[0], v1 = v[1];
uint32_t delta = 0x9E3779B9;
for (int i = 0; i < 32; i++)
{
v0 += ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
sum += delta;
v1 += ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
}
v[0] = v0;
v[1] = v1;
}
void teaDecrypt(uint32_t *v, uint32_t *k)
{
uint32_t sum = 0, v0 = v[0], v1 = v[1];
uint32_t delta = 0x9E3779B9;
sum = delta * 32;
for (int i = 0; i < 32; i++)
{
v1 -= ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
sum -= delta;
v0 -= ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
}
v[0] = v0;
v[1] = v1;
}
int main()
{
uint32_t key[4] = {0x01234567, 0x89ABCDEF, 0xFEDCBA98, 0x76543210};
char plaintext[] = "Eleven11";
teaEncrypt((uint32_t *)plaintext, key);
for (int i = 0; i < 8; i++)
printf("%02X ", plaintext[i] & 0xFF);
printf("\n");
teaDecrypt((uint32_t *)plaintext, key);
for (int i = 0; i < 8; i++)
printf("%c", plaintext[i]);

return 0;
}

refernce

TEA-wikipedia
Feistel network-wikipedia

Author

SGSG

Posted on

2025-04-08

Updated on

2025-04-18

Licensed under