XXTEA加密流程分析

First Post:

Last Update:

插图ID:87326553   

代码与图解来自:https://www.jianshu.com/p/4272e0805da3

    对于我这种相关知识欠缺的人来说,光是如此有些难以理解,因此基于该作者的图片与代码试着分析了一下实际的加密过程(也因为网上没能找到具体的文字描述过程,甚至图解的字符解释也没有,所以只能自己对着代码分析了)。

图解:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#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);
}
}

如果您要对照本文章实际调试,试着小窗吧。如下文字解释不会再引用图片。

代码符号:

    DELTA:算是该加密算法的一个特征值,为黄金分割数(5√-2)/2与232的乘积。实际上,该值不影响算法,但能很好的避免一些错误。该数值在其他算法中也常有运用。

    MX:对照图例。暂时不知道其为什么的缩写。在本例中请对照加密图解,算是算法的一部分。

    n:对应明文或密文的数组长度。(+n用于加密,-n用于解密。单纯是在代码实现时为了方便而如此设计罢了)

    v:明文或密文数组。对应图解中的X

    key:密钥数组。对应图解中的K

    rounds:加密循环的轮数。

    sum:对应图解中的D。

    e:对应图解中的(D>>2)

    p:本例中用作明文或密文数组的索引。

    r:参照代码,类比p&3**(该符号在图中而不在代码中)。3的二进制编码为11,任何数与其与运算后,可能产生(00,01,10,11),对应(0,1,2,3)(但这种理解仍有问题,怀疑图解中的r所在位置不同时具有不同的意义)**

图解符号:

    方框:相加盒。将指向该盒的变量进行相加。

    圆圈:异或盒。将指向该盒的变量进行异或。

个人建议:

    观看图解的时候,推荐自下而上,那样比较符合代码编写的流程。

    其中涉及的数学原理是异或,因此具有可逆性。但对于一些变量的来历仍然不解(例如:Xω的含义尚且不明。r猜测对应了加密轮数)

注释:

    可以将图示当作一轮的加密过程。Xr所在的循环中的相加盒实际作用为将MZ与Xr相加后的结果赋予Xr

    代码中的y、z分别表示图例中的Xr-1与Xr+1,但需要注意的是,实际代码实现中,存在如下代码:

1
2
y = v[p+1];  
z = v[p] += MX;

    也就是说,z既对应了图中的Xr,也对应了Xr+1;而y表示Xr-1,实际上是z的后一个元素

    (换一种说法就是,将y指向明文的下一位,z指向本次需要加密的明文元素。将z经过各种复杂的变化后,再将结果与原本的数据相加得到密文,将指针后移,重复同样的操作。)

    仅对比图例有着相对别扭的说法,但这已经是笔者能在网上找到的可读性相对较好的一版代码了。

-————————————————–

    顺便也将TEA与XTEA的图解与代码留在这里,以方便查阅和帮助XXTEA加密的流程理解。

TEA:

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
28
29
30
#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;
}

// v为要加密的数据
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位

XTEA:

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
#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;
}