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");
    }
    
  • 相关阅读:
    JSP基础
    线程控制
    多线程简述
    Servlet生命周期
    同步代码块和同步方法有什么区别?
    java.sql.Date和java.util.Date的区别
    Java自学指南五、编码工具
    基本类型和包装类的区别?
    什么是包装类?为什么要有包装类?基本类型与包装类如何转换?
    什么是Java的垃圾回收机制?
  • 原文地址:https://www.cnblogs.com/iBinary/p/13844861.html
Copyright © 2011-2022 走看看