TEA加密算法
TEA
以加密解密速度快,实现简单著称
TEA算法使用64bit(8byte)的明文分组和128bit(16byte)的密钥,它使用Feistel分组加密框架,采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。
简单的说就是,TEA加密解密是以原文以8字节(64位bit)为一组,密钥16字节(128位bit)为一组,(char为1字节,int为4字节,double为8字节)
该算法使用了一个DELTA常数作为倍数,它来源于黄金分割数与232的乘积,以保证每一轮加密都不相同。但δ的精确值似乎并不重要,这里TEA把它定义为 δ=「(√5 - 1)231」,这个δ对应的数指就是0×9E3779B9,但有时该常数会以减法的形式出现,-0x61c88647=0×9E3779B9。
代码实现
解密只需要将加密逆过来即可
| 12
 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
 
 | #include <iostream>
 
 void encrypt(uint32_t* v, uint32_t* k) {
 uint32_t v0 = v[0], v1 = v[1], sum = 0, 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++) {
 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_tea(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;
 }
 
 | 
识别特征:
- 标准DELTA常数(魔数)
- 密钥为16字节(4个DWORD)
- 加密轮数为16/32/64轮
- 加密结构中存在左4右5移位以及异或运算(v(2^n)==v<<n*)
- 加密结构中存在轮加/减相同常数的语句
对抗方式:
XTEA
TEA 算法被发现存在缺陷,作为回应,设计者提出了一个 TEA 的升级版本——XTEA。
XTEA是TEA的扩展,也称做TEAN,它使用与TEA相同的简单运算,同样是一个64位块的Feistel密码,使用128位密钥,建议64轮,但四个子密钥采取不正规的方式进行混合以阻止密钥表攻击。它增加了更多的密钥表,移位和异或操作等。
代码实现
| 12
 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
 
 | #include <iostream>void encrypt(uint32_t * v , uint32_t * k) {
 u32 v0 = v[0], v1 = v[1];
 u32 k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
 u32 sum = 0;
 
 
 for (int i = 0; i < rounds; i ++) {
 v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
 sum += delta;
 v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum >> 11) & 3]);
 }
 
 v[0] = v0;
 v[1] = v1;
 }
 
 void decrypt(uint32_t * v , uint32_t * k) {
 u32 v0 = v[0], v1 = v[1];
 u32 k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
 u32 sum = rounds * delta;
 
 
 
 for (int i = 0; i < rounds; i ++) {
 v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum >> 11) & 3]);
 sum -= delta;
 v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
 }
 
 v[0] = v0;
 v[1] = v1;
 }
 
 | 
识别特征:
例题练习:[HNCTF 2022 WEEK2]TTTTTTTTTea
该题的逻辑很清晰,不难分析出flag=v5=v9,而v9又赋值给v4[8]v4[13],由下面的for循环可以得知,v4[0]v4[5]分别赋值给v4[8]~v4[13],所以经过加密后的数据已知,目标是将加密算法逆过来,找到密钥,得到加密前的v4数据。


有明显的特征,加密结构中存在右移11位并&3的运算,与标准的xtea进行比对,可以知道,delta=0x61c88647,a2是key,现在要找到key,双击key,点进去就行,可以看到key的值。key要求为8字节,有4位,按d可以将其变成8字节的。

exp:
| 12
 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
 
 | #include <stdio.h>#include <stdint.h>
 void decrypt (uint32_t* v, uint32_t* k) {
 long delta=0x61C88647;
 
 
 for (int j = 0; j < 6; j += 2)
 {
 unsigned int v0 = v[j];
 unsigned int v1 = v[j+1];
 unsigned int v6 = 0;
 long sum = -delta*32;
 
 for (int i=0; i < 32; i++)
 {
 v1 -= (((v0 >> 5) ^ (16 * v0)) + v0) ^ (k[((sum >> 11) & 3)] + sum);
 sum += delta;
 v0 -= (((v1 >> 5) ^ (16 * v1)) + v1) ^ (k[(sum & 3)] + sum);
 }
 v[j]=v0; v[j+1]=v1;
 }
 }
 
 int main()
 {
 uint32_t enflag[] = {0xC11EE75A, 0xA4AD0973, 0xF61C9018, 0x32E37BCD, 0x2DCC1F26, 0x344380CC};
 uint32_t key[] = {0x00010203,0x04050607,0x08090A0B,0x0C0D0E0F};
 
 
 decrypt(enflag, key);
 printf("%s",enflag);
 return 0;
 }
 
 
 | 
解出flag:NSSCTF{Tea_TEA_TeA_TEa+}
XXTEA
XXTEA,又称Corrected Block TEA,是XTEA的升级版 ,设计者是Roger Needham, David Wheeler。其实现过程要比前两种的算法略显复杂些,加密的明文不再是64bit(两个32位无符号整数),并且其加密轮数是由n,即待加密数据个数决定的。
| 12
 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
 
 | #define DELTA 0x9e3779b9#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))
 #include <stdio.h>
 #include <stdint.h>
 
 void xxtea(uint32_t* v, int n, uint32_t const*key)
 {
 uint32_t y, z, sum;
 unsigned p, rounds, e;
 if (n > 1)
 {
 rounds = 6 + 52 / n;
 sum = 0;
 z = v[n - 1];
 do
 {
 sum += DELTA;
 e = (sum >> 2) & 3;
 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);
 }
 else if (n < -1)
 {
 n = -n;
 rounds = 6 + 52 / n;
 sum = rounds * DELTA;
 y = v[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];
 y = v[0] -= MX;
 sum -= DELTA;
 }
 while (--rounds);
 }
 }
 
 
 int main()
 {
 
 uint32_t v[2] = {0x12345678,0x78563412};
 
 uint32_t k[4] = {0x1,0x2,0x3,0x4};
 
 int n = 2;
 
 
 printf("Data is :%x %x\n",v[0],v[1]);
 
 xxtea(v,n,k);
 printf("Encrypted data is :%x %x\n",v[0],v[1]);
 
 xxtea(v,-n,k);
 printf("Decrypted data is :%x %x\n",v[0],v[1]);
 return 0;
 }
 
 | 
XXTEA算法的解密同样只是对加密算法的数据处理顺序进行倒置,同时加法改减法(减法改加法)。
识别特征:
- 轮数一般为 rounds = 6 + 52 / n,比较明显,一般很少改动
总结
xxtea算法的例题很少见,感觉见的最多的是xtea及其变形。每一道题都有不同,不能死套着脚本,应该根据题的不同而进行修改,比如轮数,魔数,异或等的一些改变。
识别特征:
- 可能存在针对64bit以及128bit数字的操作(输入的msg和key) 
- 存在先进行位移,然后异或的类似操作(- (z>>5^y<<2)这类混合变换)
 
- 前面一个复杂的混合变换的结果可能会叠加到另一个值上,两者相互叠加(Feistel 结构) 
- 获取密钥的时候,会使用某一个常量值作为下标(- key[(sum>>11) & 3])
 
- 会在算法开始定义一个delta,并且这个值不断的参与算法,但是从来不会受到输入的影响(delta数值,根据见过的题目中很少会直接使用0x9e3779b9) - 借鉴于一位大佬写的博客https://www.kn0sky.com/?p=279