TEA加密算法学习
最近几场比赛都看到了TEA算法的影子,但是以前从来没接触过,今天刚好来学一下
TEA
TEA算法全称微型加密算法(Tiny Encryption Algorithm),先贴一下参考代码
#define uint unsigned int
void encrypt(uint *v, uint *key)
{
uint l = v[0], r = v[1], sum = 0, delta = 0x9e3779b9;
for (int i = 1; i <= 32; ++i)
{
sum += delta;
l += ((r << 4) + key[0]) ^ (r + sum) ^ ((r >> 5) + key[1]);
r += ((l << 4) + key[2]) ^ (l + sum) ^ ((l >> 5) + key[3]);
}
v[0] = l, v[1] = r;
}
void decrypt(uint *v, uint *key)
{
uint l = v[0], r = v[1], sum = 0, delta = 0x9e3779b9;
sum = delta * 32;
for (int i = 1; i <= 32; ++i)
{
r -= ((l << 4) + key[2]) ^ (l + sum) ^ ((l >> 5) + key[3]);
l -= ((r << 4) + key[0]) ^ (r + sum) ^ ((r >> 5) + key[1]);
sum -= delta;
}
v[0] = l, v[1] = r;
}
其实看代码就已经很好理解了,加密算法中只涉及了几个量,v[0]和v[1]分别是第一、第二个明文,delta是TEA算法的一个重要特征值(magic number),固定为0x9e3779b9(当然可能有魔改版不是这个值?),有4个密钥key
显而易见的,TEA算法的强度在于其循环加密的次数
在一般情况下,TEA加密算法的密钥长度为128位,使用时首先判断密钥字节数组长度,如密钥字节数组长度小于16位,则将其长度扩展到16位,多余的位数用16进制的0x20代替(就是个空格)。然后将字节数组切分成4份,每4位为一新的字节数组,采用字节数组转无符号整数方法,完成密钥格式化成长度为4的无符号整数数组(就是上面代码里面的key[]数组的0~3位)。
相应的,明文字串的长度需要是偶数位,如果不是就用0x0增补一位。每两位明文用字节数组转无符号整数方法转换成2位无符号整数数组,并将这两个数进行加密(就是上面代码里的v[0],v[1]),并将加密后的数添加进新的字节数组,直到明文加密完毕。
解密过程恰好相反,在相应的解密后判断末位是否是0x0,是的话去掉就行
XTEA
XTEA是TEA算法的加强版,他增加了密钥的数量,位运算的操作也有所增加,还有一个差别是把r的变化结果和l的变化结果进行了交替赋值
#define uint unsigned int
void encrypt(uint *v, uint *key)
{
uint l = v[0], r = v[1], sum = 0, delta = 0x9e3779b9;
for (int i = 1; i <= 32; ++i)
{
l += (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]);
sum += delta;
r += (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]);
}
v[0] = l;
v[1] = r;
}
void decrypt(uint *v, uint *key)
{
uint l = v[0], r = v[1], sum = 0, delta = 0x9e3779b9;
sum = delta * 32;
for (int i = 1; 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;
}
XXTEA
先贴一个板子,后面找到好的博客再深入学习
#include <cstdio>
#define uint unsigned int
#define MX (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (k[(i & 3) ^ e] ^ z)))
void xxtea(uint *v, int n, uint *k)
{
uint y, z, sum, i, t, e, delta = 0x9e3779b9;;
if (n > 1) // encrypt
{
t = 6 + 52 / n, sum = 0, z = v[n - 1];
while (t--)
{
sum += delta, e = (sum >> 2) & 3;
for (i = 0; i < n - 1; ++i)
{
y = v[i + 1];
z = v[i] += MX;
}
y = v[0];
z = v[n - 1] += MX;
}
}
else if (n < -1) // decrypt
{
n = -n, t = 6 + 52 / n, sum = t * delta, y = v[0];
while (t--)
{
e = (sum >> 2) & 3;
for (i = n - 1; i > 0; --i)
{
z = v[i - 1];
y = v[i] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= delta;
}
}
}
int main()
{
uint v[2]= {1,2}, k[4]= {2,2,3,4};
int n = 2; // abs(n) = strlen(v)
printf("data: %u %u\n",v[0],v[1]);
xxtea(v, n, k);
printf("encrypt:%u %u\n",v[0],v[1]);
xxtea(v, -n, k);
printf("decrypt: %u %u\n",v[0],v[1]);
return 0;
}