TEA家族算法

TEA系列算法总结

前言:之前都是面向CTF-reverse学的TEA算法,属于是只知道找算法特征然后无脑一把梭,现在来好好学习总结一下


TEA

引用百度百科的介绍:

TEA算法由剑桥大学计算机实验室的David Wheeler和Roger Needham于1994年发明。它是一种分组密码算法,其明文密文块为64位(8字节)密钥长度为128位(16字节)。TEA算法利用不断增加的Delta(黄金分割率)值作为变化,使得每轮的加密是不同,该加密算法的迭代次数可以改变,建议的迭代次数为32轮。

TEA 采用与 DES 算法类似的 Feistel 结构,迭代的每次循环使用加法和移位操作,对明文和密钥进行扩散和混乱,实现明文的非线性变换。TEA 密钥长度和迭代次数都是 DES 的两倍,抗“试错法”攻击的强度不低于 DES 算法。算法以32bits 的字为运算单位,而不是耗费计算能力的逐位运算。算法没有采用 DES 那样的转换矩阵,它安全、高效、占用存储空间少,非常适合在嵌入式系统中应用, 据说 QQ 就是使用 16 轮迭代的 TEA 算法。

简单来说,就是又轻量又快

加密原理

原理图如下(k[]就是密钥key数组)

img

加密时,先把明文块(64位)分成两个32位的无符号整数

1.将其中一个无符号整数(设为v0)作为输入端生成对另一个无符号整数(设为v1)进行加密的内容,该过程包括:

  • (v0<<4)+k[0]
  • sum+=Delta; v0+sum(sum初始值为0)
  • (v0>>5)+k[1]

以上计算得到的3个值相互异或。将异或后的值与v1相加,相加后的值给v1

用代码表示如下

v1+=((v0<<4)+k[0])^(v0+sum)^((v0>>5)+k[1]);

2.将得到的v1作为下一次加密的输入端,生成对v0进行加密的内容,该过程包括:

  • (v1<<4)+k[2]
  • sum+=Delta;v1+sum
  • (v1>>5)+k[3]

同样地,以上计算得到的3个值相互异或。将异或后的值与v0相加,相加后的值给v0

v0+=((v1<<4)+k[2])^(v1+sum)^((v1>>5)+k[3]);

依次类推,回到步骤1,直到进行32轮加密

完整加密代码如下:

void encrypt (uint32_t *v,uint32_t *k ){
	uint32_t v0=v[0],v1=v[1],sum=0,i;
	uint32_t delta=0x9e3779b9;//(通常默认delta的值为0x9e3779b9,但它是多少其实不重要)
	uint32_t k0=k[0],k1=k[1],k2=k[2],k3=k[3];
	for(i=0;i<32;i++){
		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;
}

解密原理

由于异或的可逆性,解密过程就是把加密的顺序颠倒一下,+变成-就行

重点是将加密的

sum+=delta;
v0+=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
v1+=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);

颠倒成

v1-=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
v0-=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
sum-=delta;

完整解密代码如下


void decrypt (uint32_t *v,uint32_t *k){
	uint32_t v0=v[0],v1=v[1],sum=0xC6EF3720,i;//这里的sum是0x9e3779b9*32后截取32位的结果,截取很重要。
	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;

main举例


int main()
{
	uint32_t v[2]={1,2},k[4]={2,2,3,4};
	printf("加密前的数据:%u %u\n",v[0],v[1]);	//%u 以十进制形式输出无符号整数 
	encrypt(v,k);
	printf("加密后数据:%u %u\n",v[0],v[1]);
	decrypt(v,k);
	printf("解密后数据:%u %u\n",v[0],v[1]);
	return 0;
}

实战

以极客大挑战的DH爱喝茶为例(只关注加密部分)

unsigned int __cdecl enc(unsigned int *a1, int *a2)
{
  unsigned int result; // eax
  unsigned int v3; // [esp+8h] [ebp-28h]
  unsigned int v4; // [esp+Ch] [ebp-24h]
  int v5; // [esp+10h] [ebp-20h]
  unsigned int i; // [esp+14h] [ebp-1Ch]
  int v7; // [esp+1Ch] [ebp-14h]
  int v8; // [esp+20h] [ebp-10h]

  v3 = *a1;
  v4 = a1[1];
  v5 = 0;
  v7 = *a2;
  v8 = a2[1];
  for ( i = 0; i <= 0x1F; ++i )
  {
    v5 += (unsigned __int8)(v8 ^ v7) - 0x6789ABCE;
    v3 += (v4 + v5) ^ (16 * v4 + v7) ^ ((v4 >> 5) + v8);
    v4 += (v3 + v5) ^ (16 * v3 + a2[2]) ^ ((v3 >> 5) + a2[3]);
  }
  *a1 = v3;
  result = v4;
  a1[1] = v4;
  return result;
}

//调用部分
v6[0] = 0x56789ABC;
v6[1] = 0x6789ABCD;
v6[2] = 0x789ABCDE;
v6[3] = 0x89ABCDEF;
puts("plz treat DH with a cup of tea:");
fgets(s, 33, stdin);
s[strcspn(s, "\n")] = 0;
for ( i = 0; i <= 3; ++i )
{
  	v6[i] = __ROL4__(v6[i], 6);//对v6[i]左循环位移6位,相当于右移2位
    enc((unsigned int *)&s[8 * i], v6);//魔改TEA加密内容
}

关注enc函数,可以发现它在原TEA的基础上做了一些魔改,但不影响解密,仍然是+变成-,-变成+,异或还是异或,Delta它是多少就是多少,这个不重要

核心代码如下

int v5[] = {0xecaa140, 0xeca8fc0, 0xeca8fc0, 0xeca8fc0};//外层有4次调用enc,每次调用后最后得到的v5不一样

for (i = 0; i <= 0x1F; ++i)
{
	v4 -= (v3 + v5) ^ (16 * v3 + a2[2]) ^ ((v3 >> 5) + a2[3]);
	v3 -= (v4 + v5) ^ (16 * v4 + v7) ^ ((v4 >> 5) + v8);
	v5 -= (unsigned __int8)(v8 ^ v7) - 0x6789ABCE;
}

XTEA

之后 TEA 算法被发现存在缺陷,作为回应,设计者提出了一个 TEA 的升级版本——XTEA(有时也被称为"tean")

XTEA是TEA的升级版,也被称作为Corrected Block TEA,它增加了更多的密钥表,移位和异或操作等等,设计者是Roger Needham, David Wheeler

XTEA 跟 TEA 使用了相同的简单运算,但它采用了截然不同的顺序,为了阻止密钥表攻击,四个子密钥(在加密过程中,原 128 位的密钥被拆分为 4 个 32 位的子密钥)采用了一种不太正规的方式进行混合,但速度更慢了

img

加密算法如下:

#include<stdio.h>
#include<stdint.h>
 
void XTEA_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 XTEA_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;
}
from ctypes import * 
def encrypt(v,k):
	v0=c_uint32(v[0])
	v1=c_uint32(v[1])
	sum1=c_uint32(0)
	delta=0x9e3779b9
	for i in range(32):
		v0.value+=(((v1.value<<4)^(v1.value>>5))+v1.value)^(sum1.value+k[sum1.value&3])
		sum1.value+=delta
		v1.value+=(((v0.value<<4)^(v0.value>>5))+v0.value)^(sum1.value+k[(sum1.value>>11)&3])
	return v0.value,v1.value
 
def decrypt(v,k):
	v0=c_uint32(v[0])
	v1=c_uint32(v[1])
	delta=0x9e3779b9
	sum1=c_uint32(delta*32)
	for i in range(32):
		v1.value-=(((v0.value<<4)^(v0.value>>5))+v0.value)^(sum1.value+k[(sum1.value>>11)&3])
		sum1.value-=delta
		v0.value-=(((v1.value<<4)^(v1.value>>5))+v1.value)^(sum1.value+k[sum1.value&3])
	return v0.value,v1.value
 
if __name__=='__main__':
	a=[1,2]
	k=[2,2,3,4]
	print("加密前数据:",a)
	res=encrypt(a,k)
	print("加密后的数据:",res)
	res=decrypt(res,k)
	print("解密后数据:",res)

XXTEA

XXTEA,又称Corrected Block TEA,是XTEA的升级版 ,设计者是Roger Needham, David Wheeler。

特点:原字符串长度(明文)可以不是4的倍数了,是目前TEA系列中最安全的算法,但性能较上两种有所降低。

加密流程:

img

示例代码:

#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;
}

单独的加密代码:


void XXTEA_encrypto(unsigned int v[8], unsigned int key[4]) {
    unsigned int sum = 0;
    unsigned int y, z, p, rounds, e;
    int n = 8; // 数组v的长度
    rounds = 6 + 52 / n;
    y = v[0];
    sum = 0; // 加密时从0开始加delta

    while (rounds--) {
        sum += delta;
        e = sum >> 2 & 3;
        for (p = n - 1; p > 0; p--) {
            z = v[p - 1];
            y = v[p] = v[p] + ((((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^
                              ((key[(p & 3) ^ e] ^ z) + (y ^ sum)));
        }
        z = v[n - 1];
        y = v[0] = v[0] + (((key[(p ^ e) & 3] ^ z) + (y ^ sum)) ^
                          (((y << 2) ^ (z >> 5)) + ((z << 4) ^ (y >> 3))));
    }
}

另外的解密代码:

#include <stdio.h>
#include <stdlib.h>
#define delta 0x9e3779b9
 
void XXTEA_decrypto(unsigned int v[8], unsigned int key[4]) {
    unsigned int sum = 0;
    unsigned int y, z, p, rounds, e;
    int n = 8; // 数组v的长度
    rounds = 6 + 52 / n;
    y = v[0];
    sum = rounds * delta;
    do {
        e = sum >> 2 & 3;
        for (p = n - 1; p > 0; p--) {
            z = v[p - 1];
            v[p] -= ((((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^
                     ((key[(p & 3) ^ e] ^ z) + (y ^ sum)));
            y = v[p];
        }
        z = v[n - 1];
        v[0] -= (((key[(p ^ e) & 3] ^ z) + (y ^ sum)) ^
                 (((y << 2) ^ (z >> 5)) + ((z << 4) ^ (y >> 3))));
        y = v[0];
        sum -= delta;
    } while (--rounds);
    // 打印结果(如果需要)
    for (int i = 0; i < n; i++) {
        printf("%c%c%c%c", *((char *)&v[i] + 0), *((char *)&v[i] + 1),
               *((char *)&v[i] + 2), *((char *)&v[i] + 3));
        // 或者使用下面这行来以不同的字节顺序打印
        // printf("%c%c%c%c", *((char *)&v[i] + 3), *((char *)&v[i] + 2), *((char *)&v[i] + 1), *((char *)&v[i] + 0));
    }
}

参考资料:

TEA/XTEA/XXTEA系列算法 - zpchcbd - 博客园

解析 TEA 加密算法(C语言、python):_tea加密-CSDN博客

posted @ 2024-11-28 18:01  Q7h2q9  阅读(15)  评论(0编辑  收藏  举报