zoukankan      html  css  js  c++  java
  • TEA算法解析

    算法之TEA

    一丶TEA简介

    "TEA" 的全称为"Tiny Encryption Algorithm" 是1994年由英国剑桥大学的David j.wheeler发明的.

    TEA算法也算是微型加密算法

    其加密流程如下

    在安全学领域,TEA(Tiny Encryption Algorithm)是一种分组加密算法,它的实现非常简单,通常只需要很精短的几行代码。TEA 算法最初是由剑桥计算机实验室的 David Wheeler 和 Roger Needham 在 1994 年设计的。
    TEA算法使用64位的明文分组和128位的密钥,它使用Feistel分组加密框架,需要进行 64 轮迭代,尽管作者认为 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;
    }
    

    其实这道题是在做CTF的时候遇到的,弄了半天百思不得其解最终搞出来了,发现其实是TEA算法.

    说一下解密的思路吧.

    x +=xxx
    
    y+=xxx 这两个公式总共是执行了32轮,可以记做为
    
    (x+=xxx)32
    
    (y+=xxx)32
    那么解密的时候肯定也是执行32轮,每次递减,且顺序变换过来
    (y-=xxx)
    (x-=xxx)
    其中这里的xxx就是异或的公式,根据其特性我们不需要改公式中的内容.我们可以看做是 a ^ b ^ c 反过来
    c ^ b ^ a 是一样的.
    既然倒过来了.我们的变量(黄金分割)32轮的和也要依次递减来进行解密
    所以解密算法如下
    
    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
    ", (char*)Data);
    
        long key[4] = { 0x11223344,0x55667788,0x99AABBCC,0xDDEEFF11 };
    
        //Encrypt每次只是加密4字节数组中的两组(也就是每次加密8个字节) 如果你数据多.可以来个for循环来循环加密,但是Entrypt内部还有32次循环,所以速度上还是会有点影响.
        Encrypt(Data, key);
        printf("加密后的数值 = %s
    ", (char*)Data);
        Decrypt(Data, key);
        printf("解密后的数值 = %s
    ", (char*)Data);
        system("pause");
    }
    

    实现结果

    完整代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    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] = { 0x44434241,0x48474645,0x0 };
        printf("待加密的数值 = %s
    ", (char*)Data);
    
        long key[4] = { 0x11223344,0x55667788,0x99AABBCC,0xDDEEFF11 };
    
        //Encrypt每次只是加密4字节数组中的两组(也就是每次加密8个字节) 如果你数据多.可以来个for循环来循环加密,但是Entrypt内部还有32次循环,所以速度上还是会有点影响.
        Encrypt(Data, key);
        printf("加密后的数值 = %s
    ", (char*)Data);
        Decrypt(Data, key);
        printf("解密后的数值 = %s
    ", (char*)Data);
        system("pause");
    }
    
  • 相关阅读:
    openwrt 相关文章
    负载均衡相关文章
    Today's Progress
    Rodrigues formula is beautiful, but uneven to sine and cosine. (zz Berkeley's Page)
    Camera Calibration in detail
    Fundamental Matrix in Epipolar
    Camera Calibration's fx and fy do Cares in SLAM
    FilterEngine::apply
    FilterEngine 类解析——OpenCV图像滤波核心引擎(zz)
    gaussBlur
  • 原文地址:https://www.cnblogs.com/iBinary/p/13844861.html
Copyright © 2011-2022 走看看