【学习笔记】TEA/XTEA/XXTEA算法

1.TEA算法

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

  TEA算法使用64位的明文分组和128位的密钥,它使用Feistel分组加密框架,将明文分为两个32位无符号数,密钥分为4个32位无符号数子密钥,进行迭代(一般建议32轮)最后得到64位密文。该算法使用了一个神秘常数δ作为倍数,它来源于黄金比率,以保证每一轮加密都不相同。但δ的精确值并不重要,这里 TEA 把它定义为 δ=「(√5 - 1)231」(也就是程序中的 0×9E3779B9),该值也可能会魔改防止被作为特征识别。
加密流程大致为:
1.TEA以原文每8字节加解密(如果明文本身的长度不是8的倍数,那么还要进行填充以使其成为8的倍数),分成左右两边各四字节传入L(0)、R(0)。
2.右边传入的四个字节R(0),与密钥K和常数δ进行一系列左右移、相加、异或操作,得到结果F(R(0),K,δ),L(1)=L(0)+F(R(0),K,δ)。
3.L(1)再与密钥K和常数δ进行一系列左右移、相加、异或操作,得到结果F(L(1),K,δ),R(1)=R(0)+F(L(1),K,δ)。
4.以此重复32轮得到加密后的L和R。
具体实现代码如下:
复制代码
#include <stdio.h>
#include <stdint.h>
 
//加密函数
void encrypt (uint32_t* v, uint32_t* k) {
    uint32_t v0=v[0], v1=v[1], sum=0, i;           /* set up */
    uint32_t delta=0x9e3779b9;                     /* a key schedule constant */
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */
    for (i=0; i < 32; i++) {                       /* basic cycle start */
        sum += delta;
        v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
    }                                              /* end cycle */
    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;  /* set up */
    uint32_t delta=0x9e3779b9;                     /* a key schedule constant */
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */
    for (i=0; i<32; i++) {                         /* basic cycle start */
        v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
        v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        sum -= delta;
    }                                              /* end cycle */
    v[0]=v0; v[1]=v1;
}
 
int main()
{
    uint32_t v[2]={1,2},k[4]={2,2,3,4};
    // v为要加密的数据是两个32位无符号整数
    // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
    printf("加密前原始数据:%u %u\n",v[0],v[1]);
    encrypt(v, k);
    printf("加密后的数据:%u %u\n",v[0],v[1]);
    decrypt(v, k);
    printf("解密后的数据:%u %u\n",v[0],v[1]);
    return 0;
}
复制代码

 

2.XTEA算法
  之后 TEA 算法被发现存在缺陷,作为回应,设计者提出了一个 TEA 的升级版本——XTEA。XTEA 跟 TEA 使用了相同的简单运算,但它采用了截然不同的顺序,为了阻止密钥表攻击,四个子密钥采用了其他方式进行混合,但速度更慢了。
具体代码如下:
复制代码
#include <stdio.h>  
#include <stdint.h>  
  
/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */  
  
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;//num_rounds建议取值为32  
    // v为要加密的数据是两个32位无符号整数  
    // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位  
    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;  
} 
复制代码

 

3.XXTEA算法
  XXTEA算法加解密函数均接受三个参数,待加解密的32位数据块数组、数据块数组长度、128位密钥。
  每一轮迭代都会对32位数据块数组中每个元素进行加解密操作。在实际使用中还需要对数据进行填充等处理,以保证数据块长度为32位的倍数。
  加密轮数rounds=6+52/n
  n表示待加密的数据块组的长度,单位为字节。公式中的除数52是一个常数,与数据块长度无关,它是根据算法的设计和实验结果确定的。
  这个公式的含义是,对于给定的数据长度,根据公式计算出加密轮数rounds,以便在加密过程中执行足够的轮数,达到较高的安全性。
加解密过程大致为,
  1.传入数据块数组v[0,1,2,3...n-1],并计算轮数等相关参数。
  2.加密的每一轮迭代中,都从v[0]开始,与其相邻的两个数据块、密钥K、δ进行相应操作计算,v[0]=v[0]+F(v[n-1],v[1]),v[1]=v[1]+F(v[0],v[2]).......v[n-1]=v[n-1]+F(v[n-2],v[0]。
  3.解密的每一轮迭代中,都从v[n-1]开始,与其相邻的两个数据块、密钥K、δ进行相应操作计算,v[n-1]=v[n-1]-F(v[n-2],v[0]),v[n-2]=v[n-2]-F(v[n-3],v[n-1])......v[0]=v[0]-F(v[n-1],v[1])
具体代码如下:
复制代码
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#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)            /* Coding Part */
    {
        rounds = 6 + 52/n;
        sum = 0;
        z = v[n-1];
        do
        {
            sum += DELTA;
            e = (sum >> 2) & 3;
            for (p=0; p<n-1; p++)
            {
                y = v[p+1];
                z = v[p] += MX;
            }
            y = v[0];
            z = v[n-1] += MX;
        }
        while (--rounds);
    }
    else if (n < -1)      /* Decoding Part */
    {
        n = -n;
        rounds = 6 + 52/n;
        sum = rounds*DELTA;
        y = v[0];
        do
        {
            e = (sum >> 2) & 3;
            for (p=n-1; p>0; p--)
            {
                z = v[p-1];
                y = v[p] -= MX;
            }
            z = v[n-1];
            y = v[0] -= MX;
            sum -= DELTA;
        }
        while (--rounds);
    }
}
 
 
int main()
{
    uint32_t v[2]= {1,2};
    uint32_t const k[4]= {2,2,3,4};
    int n= 2; //n的绝对值表示v的长度,取正表示加密,取负表示解密
    // v为要加密的数据是两个32位无符号整数
    // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
    printf("加密前原始数据:%u %u\n",v[0],v[1]);
    btea(v, n, k);
    printf("加密后的数据:%u %u\n",v[0],v[1]);
    btea(v, -n, k);
    printf("解密后的数据:%u %u\n",v[0],v[1]);
    return 0;
}
复制代码

 

 
posted @   写忧  阅读(68)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示