TEA
- cryptos
TEA 加密族
Tea 加密
Tea 是一种_Feistel网络_的分组加密算法,所以它的解密就是加密的逆。
TEA 的流程图如下:
不像其他的加密算法有固定的轮数,TEA 的轮数是*可变*的。一般来说会选择大于`32`轮。
那么加密的实现就非常简单了。
```c
#define LOOP_COUNT 32
void encrypt(uint32_t *v,uint32_t *k){
// 黄金分割率
uint32_t delta = 0x9e3779b9;
// 初始化数据流
uint32_t l = v[0];
uint32_t r = v[1];
// key
uint32_t k0 = k[0]; uint32_t k1 = k[1]; uint32_t k2 = k[2]; uint32_t k3 = k[3];
// delta 轮加
uint32_t sum = 0;
for (size_t i = 0; i < LOOP_COUNT; i++)
{
sum += delta;
l += ((r << 4) + k0) ^ ((r >> 5) + k1) ^ (r + sum); // L1 = L0+ E(R0)
r += ((l << 4) + k2) ^ ((l >> 5) + k3) ^ (l + sum); // R1 = R0+ E(L1)
}
// 替换数据
v[0] = l;
v[1] = r;
}
```
用 `C/C++` 实现还是还是比较方便。
那么解密就是这个函数的逆,我们知道 R1 ,L1 , R0 ,L0 的关系。当我们知道轮数的时候,同时可以确定最后一轮sum
的叠加值。
```c
#define LOOP_COUNT 32
void decrypt(uint32_t *v,uint32_t *k){
uint32_t delta = 0x9e3779b9;
uint32_t l = v[0];
uint32_t r = v[1];
// key
uint32_t k0 = k[0]; uint32_t k1 = k[1]; uint32_t k2 = k[2]; uint32_t k3 = k[3];
// sum 发生了改变,这是 u32 的 sum 叠加 32 轮的结果。
uint32_t sum=0xC6EF3720;
for (size_t i = 0; i < LOOP_COUNT; i++)
{
// R1 = R0 + E(L1)
r -= ((l << 4) + k2) ^ ((l >> 5) + k3) ^ (l + sum); // R0 = R1 - E(L1)
l -= ((r << 4) + k0) ^ ((r >> 5) + k1) ^ (r + sum); // L0 = L1 - E(R0)
sum -= delta;
}
// 替换数据
v[0] = l;
v[1] = r;
}
```
用 IDA 分析一下。
Vs2019 的 encrypt 明显特征。
![image-20220924151158530](https://cdn.jsdelivr.net/gh/TsingShui/mdimages@main/img/2022/24/20220924151233.png)
XTEA 加密
XTEA 是对 TEA 的一种改进,修改了加密轮。
可以看到加密变得更复杂了, L + ((R«4 ^ R»5)+R)^( Delta_i + key[num & 3])。
#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; }
同样用 IDA 分析一下。
这里测试代码需要修改一下,轮数如果是个常值,就会被 vs 常量传播,直接展开循环,对分析会产生干扰。
#include"cipher.cpp" using namespace std; int main(int argc) { uint32_t v[2]{ 1,2 }; uint32_t k[4]{ 1,2,3,4 }; uint32_t rounds = 32*argc; encipher(rounds,v, k); printf("%X_%X \n", v[0], v[1]); decipher(rounds, v, k); printf("%X_%X", v[0], v[1]); }
XXTEA 加密
#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); } }
这个流程图分析起来的确是很困难,看了一晚上也没搞明白怎么读懂这东西,遂放弃。毕竟我们不是密码研究员,能够快速识别这个即可。
同样使用 IDA 分析