典中典之TEA加密

Last updated on December 29, 2023 pm

典中典之TEA加密

平均每三道题就有一道TEA,这里直接总结一下TEA的脚本,顺便复习一下TEA加密.

原始人TEA

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
49
50
51
52
#include <stdio.h>
#include <stdint.h>

//加密函数
void encrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i;
uint32_t delta = 0x9e3779b9;//Delta
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);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
}
v[0] = v0; v[1] = v1;
}

//解密函数
void decrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i;
uint32_t delta = 0x9e3779b9;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i<32; i++) {
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
}
v[0] = v0; v[1] = v1;
}

int main()
{
// v为要加解密的数据,两个32位的数据
uint32_t v[2] = { 1,2 };
// k为加解密密钥,4个32位无符号整数,密钥长度为128位
uint32_t k[4] = { 1,2,3,4 };
int n = sizeof(v) / sizeof(uint32_t);
printf("加密前原始数据:0x%x 0x%x\n", v[0], v[1]);
encrypt(v, k);
printf("加密后的数据:0x%x 0x%x\n", v[0], v[1]);
decrypt(v, k);
printf("解密后的数据:0x%x 0x%x\n", v[0], v[1]);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < sizeof(uint32_t)/sizeof(uint8_t); j++)
{
printf("%c", (v[i] >> (j * 8)) & 0xFF);
}
}
printf("\n");
return 0;
}

XTEA

相较于TEA,参数的运算变得更加复杂,秘钥作为参数时更加随机。

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
49
50
51
52
#include <stdio.h>
#include <stdint.h>

//加密函数
void encrypt(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9;
for (i = 0; i < num_rounds; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
}
v[0] = v0; v[1] = v1;
}

//解密函数
void decrypt(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta*num_rounds;
for (i = 0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0; v[1] = v1;
}

int main()
{
// v为要加解密的数据,两个32位无符号整数
uint32_t v[2] = { 1,2 };
// k为加解密密钥,4个32位无符号整数,密钥长度为128位
uint32_t k[4] = { 1,2,3,4 };
int n = sizeof(v) / sizeof(uint32_t);
// num_rounds,建议取值为32
unsigned int r = 32;
printf("加密前原始数据:0x%x 0x%x\n", v[0], v[1]);
encrypt(r,v, k);
printf("加密后的数据:0x%x 0x%x\n", v[0], v[1]);
decrypt(r,v, k);
printf("解密后的数据:0x%x 0x%x\n", v[0], v[1]);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < sizeof(uint32_t) / sizeof(uint8_t); j++)
{
printf("%c", (v[i] >> (j * 8)) & 0xFF);
}
}
printf("\n");
return 0;
}

XXTEA

相较TEA和XTEA有较大的区别,而且实际上CTF里见得较多的都是魔改XXTEA,毕竟上面两个太简单了

  1. 增加了参数e = (sum >> 2) & 3,秘钥作为参数的值由e和当前轮数决定
  2. 总加密轮数rounds=6 + 52 / n;这个轮数公式,由加密数据的个数决定,可以在不同的数据个数下,保持加密速度和安全的平衡
  3. 每次加密不再限于两个32位数据,能加密任意个数的32位数据.

XXTEA中的每个数都由其自身,他的上一个数和下一个数所影响,比如v[2]的值是由v[2]自增,以及当时的v[1]和v[3]所影响的(这里的当时是指当时的v[1]和v[3]的值,你懂吧),
你可能会想v[0]和最后一个数怎么得出的呢(这里假设最后一个数是v[4]),v[0]是由其自增,当时的v[4]和v[1]决定的,v[4]则是由v[4]自增,当时的v[3]和v[0]决定的.
你看代码就懂了,解密也是由这个原理倒推的

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void encrypt(uint32_t *v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
//加密

rounds = 6 + 52 / n;//rounds的值是6 + 52 / n的原因是,这个公式可以在不同的数据长度下,保持速度和安全的平衡。
sum = 0;
z = v[n - 1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;//e的值会影响加密或解密中的混合运算,即MX的定义。
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);

//解密
}
void decrypt(uint32_t *v, int n, uint32_t const key[4]){
uint32_t y, z, sum;
unsigned p, rounds, e;

rounds = 6 + 52 / n;
sum = rounds*DELTA; //可以通过轮数求出每轮的DELTA
y = v[0];
do
{
e = (sum >> 2) & 3;//可以通过每轮的DELTA求出每轮的e
for (p = n - 1; p>0; p--)//解密就是加密的逆运算
{
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}

int main()
{

uint32_t v[6] = {0x40cea5bc,0xe7b2b2f4, 0x129d12a9,0x5bc810ae, 0x1d06d73d,0xdcf870dc};
// k为加解密密钥,4个32位无符号整数,密钥长度为128位
uint32_t k[4] = { 1,2,3,4 };

//n的绝对值表示v的长度,取正表示加密,取负表示解密
int n = sizeof(v) / sizeof(uint32_t);

printf("加密前原始数据:0x%x 0x%x\n", v[0], v[1]);
encrypt(v, n, k);
printf("加密后的数据:0x%x 0x%x\n", v[0], v[1]);
decrypt(v, n, k);
printf("解密后的数据:0x%x 0x%x\n", v[0], v[1]);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < sizeof(uint32_t) / sizeof(uint8_t); j++)
{
printf("%x", (v[i] >> (j * 8)) & 0xFF);
}
}
printf("\n");
return 0;
}


典中典之TEA加密
https://txpoki.github.io/2023/12/29/TEA/
Author
John Doe
Posted on
December 29, 2023
Updated on
December 29, 2023
Licensed under