背景与简介
实现要点与注意
- 整数宽度与溢出:两者都依赖 32 位无符号整数的“环”运算(模 2**32)。C++ 的
uint32_t
自带无符号溢出语义(自动按 32 位截断),无需像py一样手动 & 0xFFFFFFFF
。
- 端序:示例实现中的打包/拆包函数固定使用小端(倒序?)格式,保证跨平台一致。
TEA (64-bit 分组)
这里先给出简单的实现,实际上做题或者生产是需要变种的,本人目前水平太臭(,就放自己会的了。
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
|
#include <cstdint>
#include <array>
namespace tea {
static constexpr uint32_t DELTA = 0x9E3779B9u;
// key: 4×uint32_t
using Key128 = std::array<uint32_t, 4>;
// 加密一个 64-bit 块(v0,v1)
inline void encrypt_block(uint32_t &v0, uint32_t &v1, const Key128 &k, uint32_t rounds = 32) {
uint32_t sum = 0;
for (uint32_t i = 0; i < rounds; ++i) {
sum += DELTA;
v0 += ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
v1 += ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
}
}
inline void decrypt_block(uint32_t &v0, uint32_t &v1, const Key128 &k, uint32_t rounds = 32) {
uint32_t sum = DELTA * rounds;
for (uint32_t i = 0; i < rounds; ++i) {
v1 -= ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
v0 -= ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
sum -= DELTA;
}
}
} // namespace tea
|
XXTEA(任意长度 32-bit 数组)
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
|
#include <cstdint>
#include <vector>
#include <array>
namespace xxtea {
using Key128 = std::array<uint32_t, 4>;
static constexpr uint32_t DELTA = 0x9E3779B9u; // 经典常数
// v: n 个 uint32_t,n>=2
inline void encrypt(std::vector<uint32_t> &v, const Key128 &k) {
const size_t n = v.size();
if (n < 2) return;
uint32_t rounds = 6u + static_cast<uint32_t>(52u / n);
uint32_t sum = 0;
uint32_t z = v[n - 1], y;
while (rounds--) {
sum += DELTA;
uint32_t e = (sum >> 2) & 3u;
for (size_t p = 0; p < n - 1; ++p) {
y = v[p + 1];
v[p] += (((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)))
^ ((sum ^ y) + (k[(p ^ e) & 3] ^ z));
z = v[p];
}
y = v[0];
v[n - 1] += (((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)))
^ ((sum ^ y) + (k[((n - 1) ^ e) & 3] ^ z));
z = v[n - 1];
}
}
inline void decrypt(std::vector<uint32_t> &v, const Key128 &k) {
const size_t n = v.size();
if (n < 2) return;
uint32_t rounds = 6u + static_cast<uint32_t>(52u / n);
uint32_t sum = rounds * DELTA;
uint32_t z, y = v[0];
while (rounds--) {
uint32_t e = (sum >> 2) & 3u;
for (size_t p = n - 1; p > 0; --p) {
z = v[p - 1];
v[p] -= (((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)))
^ ((sum ^ y) + (k[(p ^ e) & 3] ^ z));
y = v[p];
}
z = v[n - 1];
v[0] -= (((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)))
^ ((sum ^ y) + (k[(0 ^ e) & 3] ^ z));
y = v[0];
sum -= DELTA;
}
}
} // namespace xxtea
|
实际上和tea一样,xxtea的解密≈ 加密的倒序(主要得益于异或的性质):
需要注意的是xxtea循环之后还有一步的单独处理,原因是XXTEA 的设计是一个"环形数组"运算,所以要额外处理首尾一次。
小结
- TEA 与 XXTEA 都以“移位 + 异或 + 加法”为核心,易实现且性能佳。
- TEA 面向 64-bit 分组;XXTEA 直接面向 32-bit 数组,适合任意长度。