目录
初级tea算法:
XTEA算法:
XXTEA算法:
题目中TEA算法特征:
[HNCTF 2022 WEEK2]TTTTTTTTTea:
算法流程图解析:
TEA算法是一种对称加密算法,全称为Tiny Encryption Algorithm。它使用一个128位的密钥和64位的明文块,通过多轮迭代加密来实现加密过程。TEA算法的加密和解密过程是相同的,只是密钥的使用顺序不同。其拥有一个叫做Feistel 结构的密码学结构。这种密码学结构通俗的来讲就是会将加密的plaintext分成L、R两部分,并且满足 L_{i+1} = R_i, R_{i+1} = F(K_i,R_i) \oplus L_i
这种交换式的加密方式的一种结构。tea算法最关键的是要找到DELTA值和128位的key。其中DELTA常常是存在0x9e3779b9,但是也存在DELTA的值被改变的代码。除了初等tea算法,tea算法还有很多魔改版本。
#include
#include
//加密函数
void encrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0, i; //v0,v1分别为字符串的低字节高字节
uint32_t delta=0x9e3779b9;
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];
for (i=0; i < 32; i++) { //加密32轮
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 (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;//解密后再重新赋值
}
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;
}
加密过程中:
由于是一个类似delta状态变化+异或加密的过程,所以整个流程反过来写即可得到解密
XTEA算法是一种对称加密算法,它使用一个128位的密钥对数据进行加密和解密。它的加密和解密过程都是基于一个32位的块进行的。
XTEA算法的加密和解密过程都是由多轮迭代完成的。每轮迭代都包括四个步骤:轮密钥加、代换、置换和轮密钥加。其中,代换和置换步骤是XTEA算法的核心部分。XTEA算法是TEA算法的魔改算法。XTEA算法四个子密钥采取不正规的方式进行混合以阻止密钥表攻击。
#include
#include
/* 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;
}
————————————————
可以看到:
((v1<<4) + k0) ^ ((v1>>5) + k1)
变化成了 ((v1 << 4) ^ (v1 >> 5)) + v1)
,此时v1内部数据的加密变化不再受到密钥的影响。v1 + sum
变成了(sum + key[sum & 3])
以及sum + key[(sum>>11) & 3]
,密钥变成了轮转使用,而不是固定只针对某种数据进行加密(解密)。并且此时密钥的选取受到sum的影响sum += delta
的时机由每次加密开头就发生变化到v0,v1两个block加密的中间。XXtea算法的基本原理是将明文分成若干个固定长度的块,然后对每个块进行加密。加密过程中,使用一个密钥对每个块进行加密,然后将加密后的块拼接在一起形成密文。
解密过程与加密过程相反。使用相同的密钥对密文进行解密,然后将解密后的块拼接在一起形成明文。
#include
#include
#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> 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;
}
(z>>5^y<<2)
这类混合变换)key[(sum>>11) & 3]
)下面用一个xtea例子,进一步了解xtea算法
在ida中打开文件
函数传进去的是v4[8]~v4[12]的值,两位两位的传,加密后看看是否与v4[1]~v4[5]相等,进入加密函数查看
典型的xtea算法,注意:v4 -= 1640531527实际上就等于+0x9E3779B9,写出解密脚本
#define _DWORD unsigned int
#define HIDWORD(x) (*((_DWORD *)&(x) + 1))
#define LODWORD(x) (*((_DWORD *)&(x)))
//key="\x67\x45\x23\x01\xEF\xCD\xAB\x89\x98\xBA\xDC\xFE\x10\x32\x54\x76"
//TEA解密算法
long long xxxx_decrypt(int a1, int a2)
{
int v2;
int v3;
int v4;
unsigned int v5;
unsigned int v6;
int v7;
long long v9;
v2 = *(int *)(a2 + 8); //v2=0xFEDCBA98
v3 = *(int *)a2; //v3=0x1234567
v4 = *(int *)(a2 + 4); //v4=0x89ABCDEF
v5 = *(int *)a1;
v6 = *(int *)(a1 + 4);
HIDWORD(v9) = *(int *)(a2 + 12);
v7 = 0xC6EF3720;
LODWORD(v9) = v2; //v9=0x76543210FEDCBA98
do
{
v6 -= ((v5 >> 5) + HIDWORD(v9)) ^ (16 * v5 + v2) ^ (v5 + v7);
v5 -= ((v6 >> 5) + v4) ^ (16 * v6 + v3) ^ (v6 + v7);
v7 += 0x61C88647;
} while (v7 != 0);
*(int *)a1 = v5;
*(int *)(a1 + 4) = v6;
return v9;
}
最后用放大佬的几张图深入了解一下TEA算法(源出处找不到了,所以没附上链接,见谅见谅)
tea算法;
XTEA算法:
XXTEA
XXTEA算法:
参考文章: https://www.anquanke.com/post/id/224198
https://www.cnblogs.com/sk2rw/p/15220705.html