经典 Tea 加密
https://www.cnblogs.com/zpchcbd/p/15974293.html
特征值识别
模式匹配
TEA 算法的实现
#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;
}
XTea
#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;
}
//加密过程发现不同之处在于,加密算法变了,key 的利用不同,同时多了轮转数的选择,其他的还是变化不大,还是一样可以逆推。
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;
}
这里在知道 tea 算法的基础上,再记住特征,key[sum&3]
,还有轮转数的选择,就可以认出 Xtea 算法了
这里有 shr 11
可以识别到
XXtea
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
void btea (uint32_t *v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned i, rounds, e;
if (n > 1) //n 作为加解密的选择,正数为加密,负数为解密
{
rounds = 6 + 52/n; //轮转数的选择,是个特征值:6+52/n
sum = 0;
z = v[n-1]; //先取出最后一个值
do
{
sum += DELTA; //开始加密
e = (sum >> 2) & 3; //通过 sum 得到 e,也是个特征值
for (i=0; i<n-1; i++) //轮转次数
{
y = v[i+1]; //得到
v[i] += (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(i&3)^e] ^ z)));
z = v[i];
//细细分析就会知道,首先通过 v[n-1]和 v[1]进行加密得到 v[0],然后通过 v[0]和 v[2]加密得到 v[1]就会发现规律了:其实就是 3 个数为一组,通过左右两个数加密得到中间的数这里只会运算到 v[n-2]
}
y = v[0];
v[n-1] += (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(i&3)^e] ^ z)));
z = v[n-1];//最后一个数 v[n-1]的加密,拿到 v[0]和 v[n-2]进行加密得到, 算法一样
} //第一轮结束,每个数都加密了一遍
while (--rounds); //执行 rounds 轮,加密完全
}
else if (n < -1) //当负数时就是解密
{
n = -n; //首先把负数转成正数
rounds = 6 + 52/n; //确定轮转数
sum = rounds*DELTA; //根据轮转数计算 sum
y = v[0];
do
{
e = (sum >> 2) & 3;
for (i=n-1; i>0; i--) //逆序倒推
{
z = v[i-1]; //先解密 v[n-1],需要知道 v[0]和 v[n-2],
v[i] -= (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(i&3)^e] ^ z)));
y = v[i];//只会解密到 v[1]
}
z = v[n-1]; //对于第一个 v[0]的解密,要知道 v[n-1]和 v[1]
v[0] -= (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(i&3)^e] ^ z)));
y = v[0];
sum -= DELTA;//sum 的减减
}
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;
}
特征值 rounds = 6 + 52/n
e = (sum >> 2) & 3
中间加密是 ((z>>5^y<<2) + (y>>3^z<<4))