算法详解

TEA在加密的过程中要加密的明文使用2个32位无符号整数(2×4字节),秘钥为4个32位无符号整数(4×4字节),更长的明文可通过分为多个4字节为单位的小组分别进行加密(循环)

加密流程示意图:

实战识别

在逆向分析实战中判断TEA算法的可从其3行核心加密中出现的右移4左移5,两行各有3个小括号互相异或的加密流程单次加密循环32次以及运算中出现的sumdelta变量看出

代码实现

下面是TEA算法加密过程的C语言函数实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdint.h>
void encrypt(uint32_t* temp, uint32_t* key) // 解密函数
{
uint32_t v0 = temp[0], v1 = temp[1];
int sum = 0; // 初始sum值,注意此处要修改为delta的32倍
uint32_t delta = 0x9e3779b9; // 和加密函数一致的delta常量
for (int i = 0; i < 32; i++) {
sum += delta;
v0 += ((v1 << 4) + key[0]) ^ (v1 + sum) ^ ((v1 >> 5) + key[1]);
v1 += ((v0 << 4) + key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + key[3]);// 不要修改算式!
}
temp[0] = v0;
temp[1] = v1;
}

下面是TEA算法解密过程的C语言代码实现

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 <stdio.h>
#include <stdint.h>
void decrypt(uint32_t* temp, uint32_t* key) // 解密函数
{
uint32_t v0 = temp[0], v1 = temp[1];
int sum = 0x9e3779b9 * 32; // 初始sum值,注意此处要修改为delta的32倍
uint32_t delta = 0x9e3779b9; // 和加密函数一致的delta常量
for (int i = 0; i < 32; i++) {
v1 -= ((v0 << 4) + key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + key[3]);// 不要修改算式!
v0 -= ((v1 << 4) + key[0]) ^ (v1 + sum) ^ ((v1 >> 5) + key[1]);
sum -= delta;
}
temp[0] = v0;
temp[1] = v1;
}
int main() {
uint32_t key[4] =
{
// 此处存放密钥
};
uint32_t temp[2]; // 存储每组密文
uint8_t flag[32] =
{
// 此处存放要解密的数据
};
for (int i = 0; i < 32; i += 8)// 有多少字节的密文,就填i<多少(此处为32)
{
temp[0] = *(uint32_t*)&flag[i];
temp[1] = *(uint32_t*)&flag[i + 4];

decrypt(temp, key);// 调用解密函数

for (int j = 0; j < 2; j++) // 输出解密后的数据
{
for (int m = 0; m < 4; m++)
{
printf("%c", temp[j] & 0xff); // 按字节输出,恢复原始字符
temp[j] >>= 8;
}
}
}
return 0;
}

魔改

魔改TEA的一些方法:

  1. 腾讯TEA

    TEA的变种,标准TEA中使用的32轮加密,而腾讯只用了16轮。

  2. CBC模式的TEA

将明文分组与前一个密文分组进行异或运算,然后再进行加密,对于第一组的话就设置一个初始值来和第一组明文异或。

每一轮是取v0和v1,data1, data2和v0,v1异或,异或之后的data1和data2传入指针进行tea加密,之后再将加密之后的赋值回的v0和v1。

逆向方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void encrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i;

data1 ^= v0;
data2 ^= v1;
v0 = data1;
v1 = data2;

uint32_t delta = 0x6e75316c;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++)
{
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) ^ (sum + i);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) ^ (sum + i);
}
data1 = v0;
data2 = v1;
}

例题

[HGAME 2023 week1]a_cup_of_tea