Tea加密解密算法分析

Tea简介及特点:

TEA算法是一种对称加密算法,它使用一个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:

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
//加密函数
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()
{
   //关于输出,printf("%x")将整个数组输出,然后进行16进制转换字符串
}

加密过程中:

存在一个delta值,这个值会不停的增加到sum之中,形成一种循环的效果

传入的v0,v1会和传入的key0,key1运算。v1优先参与,并且会有一个位移->与密钥相加->异或的过程。

v0 = 原先的v1值套用公式,v1 = 变化后的v0 套用公式

之前用于计算delta的sum状态值也会参与

魔改Tea:

关于Tea的魔改部分会有如下情形:

1.对delta进行修改

可能将delta的值进行其他操作

2.修改加密轮数

加密轮数可能大于32轮

3.对密钥进行修改

每次加密时可能对密钥进行一定的修改

XTea算法:

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

XXTea算法:

XXTea则改动较大,需要获取明文长度,通过明文长度来控制轮数,同时有新的变量控制数组下标

#include<stdio.h>
#include<stdint.h>
#define DELTA 0x933779b9
#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)
        {
                rounds=6+52/n;        //这里可以说是预定义值,n=2是rounds=32
                sum=0;
                z=v[n-1];
                do
                {
                        sum+=DELTA;
                        e=(sum>>2)&3;
                        for(p=0;p<n-1;p++)        //注意这里的p是从0~n-1
                        {
                                y=v[p+1];
                                z=v[p]+=MX;
                        }
                        y=v[0];
                        z=v[n-1]+=MX;        //这里的MX中传入的p=n-1
                }        
                while(--rounds);
        }
        else if(n<-1)
        {
                n=-n;
                rounds=6+52/n;
                sum=rounds*DELTA;
                y=v[0];
                do
                {
                        e=(sum>>2)&3;
                        for(p=n-1;p>0;p--)    //注意这里的p是从n-1~0,和上面是反过来的
                        {
                                z=v[p-1];
                                y=v[p]-=MX;
                        }
                        z=v[n-1];
                        y=v[0]-=MX;    //这里的MX中传入的 p=0
                        sum-=DELTA;
                }
                while(--rounds);
        }
}
 
int main()
{
       //关于输出,printf("%x")将整个数组输出,然后进行16进制转换字符串
        
}

例题:[GDOUCTF]tea

拿到题目照样放入ida反编译

检索字符串查看

找到关于flag的关键信息点之后交叉引用再F5反编译

可以清楚看到对v7密钥进行了处理,从而判断出加密函数的切入点

我们可以很容易看到更改的内容

 此处就是对加密的整体实现所以我们可以写tea的解密脚本来将其解密出来

这里是加密的密文

但是要注意的是,与常规的tea相比这里ea加密外面还有一层for循环来处理sum

所以我们也要对其进行处理 

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int v5,v6,v3;
    int key[4]={2233,4455,6677,8899};
   unsigned int v8[20];//必须采用无符号整型 因为我们转化为十六进制可能会存在溢出而变为负数
  v8[0] = 0x1A800BDA;
  v8[1] = 0xF7A6219B;
  v8[2] = 0x491811D8;
  v8[3] = 0xF2013328;
  v8[4] = 0x156C365B;
  v8[5] = 0x3C6EAAD8;
  v8[6] = 0x84D4BF28;
  v8[7] = 0xF11A7EE7;
  v8[8] = 0x3313B252;
  v8[9] = 0xDD9FE279;
    for(int i=8;i>=0;i--)
    {
        v5 = 33; //由原来的最后可以到33 要从33开始逆
        v6 = 0xF462900 * (i+v5);//从最后向前开始逆向 也就是最后的总和
        v3 = i + 1;
        while ( v5-- )
        {
            v6 -= 0xF462900;
            v8[i+1] -= (v6 + key[(v6 >> 11) & 3]) ^ (v8[i] + ((v8[i] >> 5) ^ (16 * v8[i])));
            v8[i] -= v6 ^ (v8[i+1] + ((v8[i+1] >> 5) ^ (16 * v8[i+1]))) ^ (v6 + key[v6 & 3]);
         }
    } 
    for(int i=0;i<=9;i++)
    {
        printf("%x",v8[i]);//以十六进制进行输出
    }
    
}
 

然后我们再将输出的十六进制以字符串的形式进行输出

放到加密解密网站最后就可以一把梭出flag

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇