TEA家族
TEA家族
一、tea算法
1.简介:
TEA算法全称微型加密算法(Tiny Encryption Algorithm)是一种简单容易实现的加密算法,通常只需要很少的代码就可以实现。
TEA算法是由剑桥大学计算机实验室的David Wheeler和Roger Needham于1994年发明的一种分组密码算法。其特点是加密速度快,密钥长度为128比特(16字节),明文和密文块长度均为64比特(8字节)。TEA算法采用Feistel网络结构,通过一系列的线性变换和密钥轮来确保加密的安全性。
2.tea算法核心特征:
.DELTA值和十六个字节(128bit)的密钥
.可以利用ida的插件findcypto识别tea算法
.x -=0x61c88647和x +=0x9e3779b9,这两个值是等价的,可能会在反汇编中看到
3.tea加密算法原理:
1 | uint32_t v[2] = {*(uint32_t *)&input[i], *(uint32_t *)&input[i+4]}; |
这行代码将 input 数组中的字节强制转换为 uint32_t 类型。这里就体现了小端序: 如果输入字符串是 “ABCDEFGH” 在内存中存储为:’A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’ 小端序系统会将其解释为: v[0] = 0x44434241 (DCBA) v[1] = 0x48474645 (HGFE)
v[0]
的十六进制值 0x44434241
表示字符序列 'D'
, 'C'
, 'B'
, 'A'
0x44434241
在内存中的字节顺序是:0x41, 0x42, 0x43, 0x44
- 对应字符:
'A'
,'B'
,'C'
,'D'
加密后的到整数:0x56371439(必须得到这样的密文才可以还原明文,或者按照小端序存储的顺序输入密文:input[] ={0x39,0x14,0x37,0x56},在进行*(uint32_t *)&input[i]转化位32位小端序存储,得到的还是uint32_t v[i]={0x56371439},他们两个等价!! 内存中每个32位元素的顺序是不变的,一个元素的值是按小端序存储的
加密后的内存存储: 39 14 37 56
解密后的结果:0x44434241(得到的是加密还原后的uint32_t v[2]的小端序方式存储的数据,表示的字节序列为’D’,’C’,’B’,’A’)
最终结果:ABCD(小端序存储在内存中存储的数据A,B,C,D,是明文一个一个字节输入的顺序)
还原时把得到的小端序明文转化成可读的字符串:
3.1例题
加密以及小端序输出的过程:
1 | int main() { |
当你输⼊正确 flag 时会输出这样的数据: 210
0x17, 0x65, 0x54, 0x89, 0xed, 0x65, 0x46, 0x32, 0x3d, 0x58, 0xa9, 0xfd, 0xe2, 0x5e,
0x61, 0x97, 0xe4, 0x60, 0xf1, 0x91, 0x73, 0xe9, 0xe9, 0xa2, 0x59, 0xcb, 0x9a, 0x99,
0xec, 0xb1, 0xe1, 0x7d(*输出密文在小端序系统的内存中的存在方式,每32bit为一组)
内存中每个32位元素的顺序是不变的,一个元素的值是按小端序存储的
解密过程
1 | int main() |
3.2大小端序的体现:代码验证完整流程
1 |
|
输出结果:
text
1 | 原始明文: ABCD |
小端序(Little-Endian)解析:
内存布局(地址从低到高):
text
1
2 | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' |
↑i i+1 i+2 i+3 i+4 i+5 i+6 i+7强制类型转换:
&input[i]
指向'A'
的地址(i=0
)*(uint32_t *)&input[i]
会将连续的4字节'A','B','C','D'
解释为一个uint32_t
小端序的存储规则:
最低有效字节(LSB)在低地址
实际解释为
uint32_t
时,字节顺序是反的:text
'A' (0x41) → 最低字节(LSB) 'B' (0x42) 'C' (0x43) 'D' (0x44) → 最高字节(MSB)
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
- 最终 `v[0] = 0x44434241`(即 `DCBA` 的十六进制拼接)
**同理**:
- `v[1]` 读取 `'E','F','G','H'` → `0x48474645`(`HGFE`)
```c++
#include <stdio.h>
#include <stdint.h>
int main() {
char input[9] = "ABCDEFGH";
uint32_t v0 = *(uint32_t *)&input[0];
uint32_t v1 = *(uint32_t *)&input[4];
printf("v0 = 0x%08x\n", v0); // 输出: 0x44434241
printf("v1 = 0x%08x\n", v1); // 输出: 0x48474645
// 按字节分解查看
printf("v0 bytes: %c %c %c %c\n",
(v0 & 0xff), ((v0 >> 8) & 0xff), //v0 & 0xff是取最低的8位(最低有效字节)
((v0 >> 16) & 0xff), ((v0 >> 24) & 0xff));
// 输出: A B C D
return 0;
}
加密过程中,64位的明文分成两个32位(4字节)的部分即v0,v1。
例如,一个 64 位整数
0x1122334455667788
会被拆分为:
v0 = 0x11223344
(高 32 位)v1 = 0x55667788
(低 32 位)
明文按8字节为一组再进行分为两个4字节的元素。
uint32_t v*(v在这里是数组,定义了这个数组v每个元素都是32位,往后可以把每个元素如v[0],v[1]赋值给v0,v1。最后加密完再把每个v0,v1重新赋值给数组v)。
uint32_t k* 同理。
- 严格遵循无符号32位运算
3.3加密过程:
//配合dev里面的teaNSSCTF脚本食用,题目是revers,NSSCTF的TEA文件
初始化:
uint32_t k*:初始化一个每个元素都是32位的数组k,选择一个128bit的密钥,分为四个32位无符号整数k[1],k[2],k[3],k[4]赋值到数组k里面。
uint32_t v*:初始化一个每个元素都是32位的数组v,两个32位组成一组(v[0],v[1])一起参与接下来的32轮加密。 //:v[0],v[1]是明文的左右部分。
加密过程:
初始化变量:
uint32_t v0=v[0],v1=v[1]
uint32_t sum=0
uint32_t delta = 0x9e3779b9
进行32轮加密:
每轮加密包括以下内容:
sum += delta
v0 += ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
v1 += ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3])
更新v[0],v[1]:
v[0]=v0 ; v[1]=v1
加密后的结果实际上就是小端序数据!!!。数值的内存布局(小端序存储):0x17, 0x65, 0x54, 0x89。 输出的密文:0x89546517
内存中每个32位元素的顺序是不变的,一个元素的值是按小端序存储的
加密解密完整代码:
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
44
45
46
47
48
//加密函数:
void tea_enc(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1]; // v0、v1分别是明文的左、右半部分
uint32_t sum = 0; // sum用作加密过程中的一个累加变量
uint32_t delta = 0x9e3779b9; //作为sum每次累加的变化值,题目中往往会修改此值
for (int i = 0; i < 32; i++) { // tea加密进行32轮
//以下3行是核心加密过程,题目中往往会对部分细节做出修改(但由于异或的对称性质,根本不需要记,写解密函数时照抄就行了)
sum += delta;
v0 += ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
v1 += ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
}
// v0和v1只是加密的临时变量,因此加密后的内容要还给v数组
v[0] = v0;
v[1] = v1;
//加密后的结果实际上就是小端序数据!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
//解密函数:
void tea_dec(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1]; // v0、v1分别是密文的左、右半部分
uint32_t delta = 0x9e3779b9; //作为sum每次累加的变化值,题目中往往会修改此值
uint32_t sum = 32 * delta; //此处需要分析32轮加密结束后sum的值与delta的变化, 以此处加密为例子,32轮每次sum+=delta,因此最后sum=32*delta
for (int i = 0; i < 32; i++) { // tea加密进行32轮
//根据加密时的顺序颠倒下面3行的顺序,将加法改为减法(异或部分都是整体,不用管),就是逆向解密过程
v1 -= ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
v0 -= ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
sum -= delta;
}
// 因此解密后的内容要还给v数组
v[0] = v0;
v[1] = v1;
}
int main()
{
uint32_t v[2]={1,2},k[4]={2,2,3,4};
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
printf("加密前原始数据:%u %u\n",v[0],v[1]);
encrypt(v, k);
printf("加密后的数据:%u %u\n",v[0],v[1]);
decrypt(v, k);
printf("解密后的数据:%u %u\n",v[0],v[1]);
return 0;
}
二、xtea算法
1.简介:
使用与TEA相同的简单运算,但四个子密钥采取不正规的方式进行混合以阻止密钥表攻击。
2.加解密过程:
1 |
|
三、XXTEA算法
1 |
|