TEA

- cryptos

TEA 加密族


  1. Tea 加密

    Tea 是一种_Feistel网络_的分组加密算法,所以它的解密就是加密的逆。

    TEA 的流程图如下:

img

不像其他的加密算法有固定的轮数,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)

  1. XTEA 加密

    XTEA 是对 TEA 的一种改进,修改了加密轮。

    XTEA_InfoBox_Diagram

    可以看到加密变得更复杂了, 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]);
    
    }
    

    image-20220924155251786


  1. XXTEA 加密

    1280px-Algorithm_diagram_for_XXTEA_cipher.svg

    #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 分析

    image-20220924160206858