插图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; }