# 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 位的子密钥)采用了一种不太正规的方式进行混合,但速度更慢了

# 加密解密过程

这里有一个大佬写的 c 语言脚本可以实现 TEA 加密,我们以这个脚本来分析一下它的加解密过程

# 加密过程

# 32 位无符号整数

整型的每一种都有无符号(unsigned)和有符号(signed)两种类型(float 和 double 总是带符号),在默认情况下声明的整型变量都是有符号类型,如果要声明其不是无符号,则需要在类型前加上 unsigned。这两者的区别就是,无符号类型可以保存两倍于有符号类型的正整数数据,比如 16 位系统中 int 能储存的数据范围为 - 32768~32767,而无符号的范围则是 0 ~ 65535.

而在我们的脚本中,uint32_t 就是定义其为 32 位无符号整数,关于其还要注意,当某个数据不可能为负数的时候我们就可以这样定义:uint32_t,unsigned char, unsigned int, size_t, uint64_t, unsigned long int,也可以这么理解,当有些数据我们不知道是正是负时,就不能用以上定义.

此外,在运算两个 32 位无符号整数时要注意它会不会超过它的最大值,比如:

1
2
3
uint32_t a,b,c;
uint64_t s;
s = a * b + c;

在这个运算中 a*b 可能会超过 uint32_t 的最大值,所以我们要这样写:

1
s = ((uint64_t)a )* b + c;

我们现在再来看脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#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;
}

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]);
return 0;
}

我们可以看到,v 就是要加密的数据,是两个 32 位无符号整数,而 k 是加密解密的密钥,为 4 个 32 位无符号整数,即密钥长度为 128 位,这个 delta 是为了保证每一轮加密都不同,一般都是 0x9e3779b9,但有的也不一定是这个,这个要根据情况而定

加密过程其实很好理解,就不多解释了,这个是 TEA 算法家族中最简单的,因为还有很多魔改 TEA 也就是 XTEA、XXTEA,我哭

# 解密过程

1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}

(未完持续)