tea系列算法
TEA
它是一种分组密码算法,其明文密文块为64比特,密钥长度为128比特。TEA算法利用不断增加的Delta(黄金分割率)值作为变化,使得每轮的加密是不同,该加密算法的迭代次数可以改变,建议的迭代次数为32轮。
Tea算法的特征是存在0x9e3779b9.
加密:
#include<stdio.h>
void encode(unsigned int* v,unsigned int *k)
{
unsigned int l=v[0],r=v[1];
unsigned int k0=k[0],k1=k[1],k2=k[2],k3=k[3];
unsigned int delta=0x9e3779b9;
int i;
unsigned int sum=0;
for(i=0;i<32;i++) //核心加密算法,建议32轮,最低16轮
{
sum+=delta;
l+=((r<<4)+k0)^(r+sum)^((r>>5)+k1); //r<<4/r*16
r+=((l<<4)+k2)^(l+sum)^((l>>5)+k3);
}
v[0]=l;
v[1]=r;
}
int main()
{
unsigned int a[2]={1,2}; //明文,必须是8字节的倍数,不够需要程序补全,参考base64方法
unsigned int k[4]={2,2,3,4};//密钥随便
encode(a,k);
printf("%d %d",a[0],a[1]);
}
解密:
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;
TEA算法逆向
- tea算法的特征就是DELTA值和十六个字节的密钥(也就是128位)。
- 在逆向程序的时候,可以利用ida的插件findcypto识别tea算法
- x-=0x61c88647和x+=0x9e3779b9,这两个值是等价的,可能会在反汇编中看到
TEA算法的变化技巧
前面有提到关于”但δ的精确值似乎并不重要”,所以δ的值不一定需要0x9E3779B9,所以这里的话在加密解密的时候可以改变这个δ的值,改了之后就会导致部分识别加密的工具失效来达到算法魔改的目的。
测试代码,改变其中的δ的值//加密函数 void encrypt(uint32_t* v, uint32_t* k) { uint32_t v0 = v[0], v1 = v[1], sum = 0, i; /* set up */ uint32_t delta = 0x12345678; /* 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 = 0x468acf00, i; /* set up */ uint32_t delta = 0x12345678; /* 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; }
XTEA
XTEA是TEA的升级版,增加了更多的密钥表,移位和异或操作等等,也被称为”tean”
加密:
解密:#include<stdio.h> #include<stdint.h> 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; //这里是加密轮数,自己设置 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; }
void decrypt(unsigned int* v, unsigned int* key) { unsigned int l = v[0], r = v[1], sum = 0, delta = 0x9e3779b9; sum = delta * 32; for (size_t i = 0; i < 32; i++) { r -= (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]); sum -= delta; l -= (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]); } v[0] = l; v[1] = r; }
下面是TEA和XTEA两种算法之间的主要区别:
- 密钥长度不同:TEA算法采用128位密钥,而XTEA算法采用更长的256位密钥。
- 加密轮数不同:TEA算法采用32轮迭代加密/解密,而XTEA算法采用64轮迭代加密/解密。这使得XTEA算法有更好的安全性,但也使得它相对于TEA算法来说更加耗时。
- 算法细节不同:XTEA算法在TEA算法的基础上进行了改进,主要针对TEA算法中的一些安全弱点。具体来说,XTEA算法中的迭代加密/解密中加入了一个变量delta的变化,以增强算法的安全性。此外,XTEA算法中的轮加密过程也做了一些微调,例如将密钥扩展的方式做了改进等。
XXTEA
又称Corrected Block TEA
特点:原字符串长度可以不是4的倍数了
在线解密网址:http://www.atoolbox.net/Tool.php?Id=861#include <stdbool.h> #include <stdio.h> #define MX \ ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z)) bool btea(unsigned int* v, int n, unsigned int* k) { unsigned int z = v[n - 1], y = v[0], sum = 0, e, DELTA = 0x9e3779b9; unsigned int p, q; if (n > 1) { /* Coding Part */ q = 6 + 52 / n; while (q-- > 0) { 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; } return 0; } else if (n < -1) { /* Decoding Part */ n = -n; q = 6 + 52 / n; sum = q * DELTA; while (sum != 0) { 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; } return 0; } return 1; } int main(int argc, char const* argv[]) { // test unsigned int v[2] = {1, 2}, key[4] = {1, 2, 3, 4}; printf("%u,%u\n", v[0], v[1]); btea(v, 2, key); printf("%u,%u\n", v[0], v[1]); btea(v, -2, key); printf("%u,%u\n", v[0], v[1]); return 0; }
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 simple blog!