TEA加密算法与逆向方法简析

参考博客:

逆向算法之TEA算法

TEA算法解析

算法分析

TEA基本简介

TEA(Tiny Encryption Algorithm)是一种分组加密算法,它的实现非常简单,通常只需要很精短的几行代码。TEA 算法最初是由剑桥计算机实验室的 David Wheeler 和 Roger Needham 在 1994 年设计的。

TEA 算法使用 64 位的明文分组和 128 位的密钥,它使用 Feistel 分组加密框架,建议的迭代次数为 32 轮。该算法使用了一个常数 δ 作为倍数,它来源于黄金比率,以保证每一轮加密都不相同。但 δ 的精确值似乎并不重要,这里 TEA 把它定义为 δ=「(√5 - 1)231」(也就是程序中的 0×9E3779B9)。

之后 TEA 算法被发现存在缺陷,作为回应,设计者提出了一个 TEA 的升级版本——XTEA(有时也被称为“tean”)。XTEA 跟 TEA 使用了相同的简单运算,但它采用了截然不同的顺序,为了阻止密钥表攻击,四个子密钥(在加密过程中,原 128 位的密钥被拆分为 4 个 32 位的子密钥)采用了一种不太正规的方式进行混合,但速度更慢了。

代码表示

加密函数

void Encrypt(long* EntryData, long* Key) {
    //分别加密数组中的前四个字节与后4个字节,4个字节为一组每次加密两组
    unsigned long x = EntryData[0];
    unsigned long y = EntryData[1];

    unsigned long sum = 0;
    unsigned long delta = 0x9E3779B9;
    //总共加密32轮
    for (int i = 0; i < 32; i++) {
        sum += delta;
        x += ((y << 4) + Key[0]) ^ (y + sum) ^ ((y >> 5) + Key[1]);
        y += ((x << 4) + Key[2]) ^ (x + sum) ^ ((x >> 5) + Key[3]);
    }
    //最后加密的结果重新写入到数组中
    EntryData[0] = x;
    EntryData[1] = y;
}

解密函数

解密思路:

x +=xxx
y+=xxx 这两个公式总共是执行了 32 轮,可以记做为
(x+=xxx)32
(y+=xxx)32
那么解密的时候肯定也是执行 32 轮, 每次递减, 且顺序变换过来
(y-=xxx)
(x-=xxx)
其中这里的 xxx 就是异或的公式, 根据其特性我们不需要改公式中的内容
所以解密算法如下

void Decrypt(long* EntryData, long* Key) {
    //分别加密数组中的前四个字节与后4个字节,4个字节为一组每次加密两组
    unsigned long x = EntryData[0];
    unsigned long y = EntryData[1];

    unsigned long sum = 0;
    unsigned long delta = 0x9E3779B9;
    sum = delta << 5;   //注意这里,sum = 32轮之后的黄金分割值. 因为我们要反序解密.
    //总共加密32轮 那么反序也解密32轮
    for (int i = 0; i < 32; i++) {
        // 先将y解开 然后参与运算在解x
        y -= ((x << 4) + Key[2]) ^ (x + sum) ^ ((x >> 5) + Key[3]);
        x -= ((y << 4) + Key[0]) ^ (y + sum) ^ ((y >> 5) + Key[1]);
        sum -= delta;
    }
    //最后加密的结果重新写入到数组中
    EntryData[0] = x;
    EntryData[1] = y;

主函数

int main() {
    long Data[3] = { 0x44434241,0x48474645,0x0 };
    printf("待加密的数值 = %s\r\n", (char*)Data);

    long key[4] = { 0x11223344,0x55667788,0x99AABBCC,0xDDEEFF11 };

    //Encrypt每次只是加密4字节数组中的两组(也就是每次加密8个字节) 如果你数据多.可以来个for循环来循环加密,但是Entrypt内部还有32次循环,所以速度上还是会有点影响.
    Encrypt(Data, key);
    printf("加密后的数值 = %s\r\n", (char*)Data);
    Decrypt(Data, key);
    printf("解密后的数值 = %s\r\n", (char*)Data);
    system("pause");
}

完整代码

#include <bits/stdc++.h>
using namespace std;

void Encrypt(long* EntryData, long* Key) {
    //分别加密数组中的前四个字节与后4个字节,4个字节为一组每次加密两组
    unsigned long x = EntryData[0];
    unsigned long y = EntryData[1];

    unsigned long sum = 0;
    unsigned long delta = 0x9E3779B9;
    //总共加密32轮
    for (int i = 0; i < 32; i++) {
        sum += delta;
        x += ((y << 4) + Key[0]) ^ (y + sum) ^ ((y >> 5) + Key[1]);
        y += ((x << 4) + Key[2]) ^ (x + sum) ^ ((x >> 5) + Key[3]);
    }
    //最后加密的结果重新写入到数组中
    EntryData[0] = x;
    EntryData[1] = y;
}

void Decrypt(long* EntryData, long* Key) {
    //分别加密数组中的前四个字节与后4个字节,4个字节为一组每次加密两组
    unsigned long x = EntryData[0];
    unsigned long y = EntryData[1];

    unsigned long sum = 0;
    unsigned long delta = 0x9E3779B9;
    sum = delta << 5;   //注意这里,sum = 32轮之后的黄金分割值. 因为我们要反序解密.
    //总共加密32轮 那么反序也解密32轮
    for (int i = 0; i < 32; i++) {
        // 先将y解开 然后参与运算在解x
        y -= ((x << 4) + Key[2]) ^ (x + sum) ^ ((x >> 5) + Key[3]);
        x -= ((y << 4) + Key[0]) ^ (y + sum) ^ ((y >> 5) + Key[1]);
        sum -= delta;
    }
    //最后加密的结果重新写入到数组中
    EntryData[0] = x;
    EntryData[1] = y;
}

int main() {
    long Data[3] = {1, 2};  //明文,必须是8字节的倍数,不够需要程序补全,参考base64方法
    printf("待加密的数值:%d %d\n",Data[0],Data[1]);  

    long key[4] = {2,2,3,4 };   //密钥随便

    //Encrypt每次只是加密4字节数组中的两组(也就是每次加密8个字节) 如果你数据多.可以来个for循环来循环加密,但是Entrypt内部还有32次循环,所以速度上还是会有点影响.
    Encrypt(Data, key);
    printf("加密后的数值:%d %d\n",Data[0],Data[1]);
    Decrypt(Data, key);
    printf("解密后的数值:%d %d\",Data[0],Data[1]);
    system("pause");
}

逆向分析

题目待补充

posted @ 2021-07-20 23:53  Moominn  阅读(1975)  评论(0编辑  收藏  举报