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");
}

逆向分析

題目待補充


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM