TEA
感谢各位师傅,转载连接:https://www.cnblogs.com/sk2rw/p/14797633.html
我做做删减和补充。
简介
TEA算法使用64位的明文分组和128位的密钥,使用feistel分组加框架,需要进行32轮循环得到最后的64位密文,其中magic number DELTA是由黄金分割点。
tea算法最关键的是要找到DELTA值和128位的key。
在逆向程序的时候,可以利用ida的插件findcypto识别tea算法。
如上图的程序,可以看出a2就是key,v4-=0x61c88647和v4+=0x9e3779b9是等价的,显然DELTA就是0x9e3779b9
Tea算法还可以进行魔改,魔改的地方主要是DELTA值,将这个值修改会让很多加密算法识别软件失效,像下面的程序就将DELTA魔改为0x1234567,绕过来peid的插件KANAL的识别。
补充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
| #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; /* set up */ uint32_t delta=0x9e3779b9; /* a key schedule constant */ uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */ for (i=0; i < 32; i++) { /* basic cycle start */ sum += delta; v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); } /* end cycle */ 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; /* set up */ uint32_t delta=0x9e3779b9; /* a key schedule constant */ uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */ for (i=0; i<32; i++) { /* basic cycle start */ v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); sum -= delta; } /* end cycle */ 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; }
|
TEA升级版XTEA
增加了更多的密钥表,移位和异或等操作。
XTEA是TEA的扩展,也称做TEAN,它使用与TEA相同的简单运算,同样是一个64位块的Feistel密码,使用128位密钥,建议64轮, 但四个子密钥采取不正规的方式进行混合以阻止密钥表攻击。
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
| 加密前原始数据:1 2 加密后的数据:1347371722 925494771 解密后的数据:1 2 Process returned 0 (0x0) execution time : 0.020 s Press any key to continue.
XTEA是TEA的升级版,增加了更多的密钥表,移位和异或操作等等,设计者是Roger Needham, David Wheeler 加密过程:
算法实现:
示例代码:
[cpp] view plain copy #include <stdio.h> #include <stdint.h> /* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */ void encipher(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 decipher(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() { uint32_t v[2]={1,2}; uint32_t const k[4]={2,2,3,4}; unsigned int r=32;//num_rounds建议取值为32 // v为要加密的数据是两个32位无符号整数 // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位 printf("加密前原始数据:%u %u\n",v[0],v[1]); encipher(r, v, k); printf("加密后的数据:%u %u\n",v[0],v[1]); decipher(r, v, k); printf("解密后的数据:%u %u\n",v[0],v[1]); return 0; }
|
XXTEA
又称Corrected Block TEA,是XTEA的升级版 XXTEA是一个非平衡Feistel网络分组密码,在可变长度块上运行,这些块是32位大小的任意倍数(最小64位),使用128位密钥, 是目前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 53 54 55 56 57 58 59 60 61 62 63 64 65
| #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 btea(uint32_t *v, int n, uint32_t const key[4]) { uint32_t y, z, sum; unsigned p, rounds, e; if (n > 1) /* Coding Part */ { 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) /* Decoding Part */ { 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]= {1,2}; uint32_t const k[4]= {2,2,3,4}; int n= 2; //n的绝对值表示v的长度,取正表示加密,取负表示解密 // v为要加密的数据是两个32位无符号整数 // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位 printf("加密前原始数据:%u %u\n",v[0],v[1]); btea(v, n, k); printf("加密后的数据:%u %u\n",v[0],v[1]); btea(v, -n, k); printf("解密后的数据:%u %u\n",v[0],v[1]); return 0; }
|
注意!
python是大端序, 我们的C语言是小端序。所以需要转化一下。例如:
1 2 3 4 5
| python: b'\xbc\xa5\xce@\xf4\xb2\xb2\xe7\xa9\x12\x9d\x12\xae\x10\xc8[=\xd7\x06\x1d\xdcp\xf8\xdc' c++: uint32_t v[6]= {0x40cea5bc,0xe7b2b2f4,0x129d12a9,0x5bc810ae,0x1d06d73d,0xdcf870dc}; "flag" 0x67616c66
|