XXTEA

简介

省流:TEA的超大杯版

XXTEA是XTEA的改进版,与它的前身不同,XXTEA大量魔改了原来的加密结构,首先是采用了非对称Feistel网络结构,数据不再被分为两个32位块,同时也不再一次只处理64位的数据,而是直接把所有数据分为多个32位块,然后用CBC模式循环加密,令块数为n,则一轮加密指的是将这n个块的数据各变换一次,总的加密轮次由round=6+52/n给出,注意这个公式仅仅是为了在安全性和性能之间做出平衡,理论上加密的轮次并没有要求。加密函数MX也进行了修改,更换了计算方式和密钥选择方式。

特征

标准版本的XXTEA加密循环轮次由数据规模n绝定,当然rounds=6+52/n这个公式完全可以魔改,然后是每轮加密中的CBC结构特征,以及128位密钥

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#define MX ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))
void xxteaEncrtpy(uint32_t *v, size_t n, uint32_t *k)
{
uint32_t y, z, sum;
uint32_t p, rounds, e;
uint32_t delta = 0x9E3779B9;
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do
{
sum += delta;
e = (sum >> 2) & 3; // 引入非线性计算,使得每次取出的key值缺少规律
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX; // 每个块加密是增加的偏移量实际上由上一个块(z)和下一个块(y)的值和sum共同决定
}
y = v[0]; // 此处其实是循环加密的端点,当然可以对下标取模把这部分写进循环里
z = v[n - 1] += MX;
} while (--rounds); // 实际上是把相同的操作重复round轮
}

解密

虽然整个结构进行了大程度魔改,但仍是Fesitel网络,所以只要想办法把运算逆转过来就能解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void xxteaDecrypt(uint32_t *v, size_t n, uint32_t *k)
{
uint32_t y, z, sum;
uint32_t p, rounds, e;
uint32_t delta = 0x9E3779B9;
rounds = 6 + 52 / n;
sum = rounds * delta;
y = v[0]; // n-1号块的下一个块是0号块
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--) // 反向循环
{
z = v[p - 1]; // 因为是反着循环,所以这里是上一个块
y = v[p] -= MX; // 这里是也是取上一个和下一个块的值作为参数
}
z = v[n - 1]; // 0号块的上一个块是n-1号块
y = v[0] -= MX;
sum -= delta;
} while (--rounds);
}

完整代码

代码中加密数据长度正好为64位,注意当长度不为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
49
50
51
52
53
54
55
56
57
58
59
#include <bits/stdc++.h>
using namespace std;
#define MX ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))
void xxteaEncrtpy(uint32_t *v, size_t n, uint32_t *k)
{
uint32_t y, z, sum;
uint32_t p, rounds, e;
uint32_t delta = 0x9E3779B9;
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do
{
sum += delta;
e = (sum >> 2) & 3; // 引入非线性计算,使得每次取出的key值缺少规律
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX; // 每个块加密是增加的偏移量实际上由上一个块(z)和下一个块(y)的值和sum共同决定
}
y = v[0]; // 此处其实是循环加密的端点,当然可以对下标取模写进循环里
z = v[n - 1] += MX;
} while (--rounds); // 实际上是把相同的操作重复round轮
}
void xxteaDecrypt(uint32_t *v, size_t n, uint32_t *k)
{
uint32_t y, z, sum;
uint32_t p, rounds, e;
uint32_t delta = 0x9E3779B9;
rounds = 6 + 52 / n;
sum = rounds * delta;
y = v[0]; // n-1号块的下一个块是0号块
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--) // 反向循环
{
z = v[p - 1]; // 因为是反着循环,所以这里是上一个块
y = v[p] -= MX; // 这里是也是取上一个和下一个块的值作为参数
}
z = v[n - 1]; // 0号块的上一个块是n-1号块
y = v[0] -= MX;
sum -= delta;
} while (--rounds);
}
int main()
{
uint32_t k[4] = {0x01234567, 0x89abcdef, 0xfedcba98, 0x76543210};
char v[] = "Eleven11";
xxteaEncrtpy((uint32_t *)v, strlen(v) / 4, k);
for (int i = 0; i < 8; i++)
printf("%c", v[i] & 0xFF);
printf("\n");
xxteaDecrypt((uint32_t *)v, strlen(v) / 4, k);
for (int i = 0; i < 8; i++)
printf("%c", v[i]);
printf("\n");
return 0;
}

reference

XXTEA-wikipedia

Author

SGSG

Posted on

2025-04-08

Updated on

2025-04-18

Licensed under