TEA

TEA算法使用64位的明文分组和128位的密钥,它使用Feistel分组加密框架,需要进行64轮迭代,尽管作者认为32轮已经足够了。该算法使用了一个神秘常数δ作为倍数,它来源于黄金比率,以保证每一轮加密都不相同。但δ的精确值似乎并不重要,这里TEA把它定义为δ=「(√5-1)231」(也就是程序中的0x9E3779B9)。
之后TEA算法被发现存在缺陷,作为回应,设计者提出了一个TEA的升级版本——XTEA(有时也被称为“tean”)。XTEA跟TEA使用了相同的简单运算,但它采用了截然不同的顺序,为了阻止密钥表攻击,四个子密钥(在加密过程中,原128位的密钥被拆分为4个32位的子密钥)采用了一种不太正规的方式进行混合,但速度更慢了。
TEA加密和解密时都使用一个常量值,这个常量值为0x9E3779B9,这个值是近似黄金分割率,注意,有些编程人员为了避免在程序中直接出现”mov 变量,0x9E3779B9“,以免被破解者直接搜索0x9E3779B9这个常数得知使用TEA算法,所以有时会使用”sub 变量,0x61C88647“代替。
因为0x61C88647=-(0x9E3779B9)。
TEA算法每一次可以操作64bit(8byte),采用128bit(16byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。

代码

  1. #include<stdio.h>
  2. #define DELTA 0x9E3779B9
  3. //加密
  4. void tea_encrypt(unsigned int* v, unsigned int* key)
  5. {
  6. unsigned int l = v[0], r = v[1], sum = 0;
  7. for (size_t i = 0; i < 32; i++)
  8. {
  9. //进行32次迭代加密,Tea算法作者的建议迭代次数
  10. l += (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]);
  11. //累加Delta的值
  12. sum += DELTA;
  13. //利用多次双位移和异或将明文与密钥扩散混乱,并将两个明文互相加密
  14. r += (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]);
  15. }
  16. v[0] = l;
  17. v[1] = r;
  18. }
  19. //解密
  20. void tea_decrypt(unsigned int* v, unsigned int* key)
  21. {
  22. unsigned int l = v[0], r = v[1], sum = 0;
  23. //32次迭代累加后delta的值
  24. sum = DELTA * 32;
  25. for (size_t i = 0; i < 32; i++)
  26. {
  27. r -= (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]);
  28. sum -= DELTA;
  29. l -= (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]);
  30. }
  31. v[0] = l;
  32. v[1] = r;
  33. }
  34. int main(int argc, char const *argv[])
  35. {
  36. unsigned int key[4]={0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f};
  37. unsigned int v1[2] = {0xaabbccdd,0x01234567};
  38. tea_encrypt(v1,key);
  39. printf("tea_encrypt:%x %x\n",v1[0],v1[1]);
  40. tea_decrypt(v1,key);
  41. printf("tea_decrypt:%x %x\n",v1[0],v1[1]);
  42. return 0;
  43. }

更偏向于IDA的版本:

void encrypt (uint32_t* v, uint32_t* k)
{
    uint32_t v0=v[0], v1=v[1], sum=0, i;
    uint32_t delta=0x9E3779B9;
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];

    for (i=0; i < 32; i++)
    {
        sum += delta;
        v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
    }

    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;
    uint32_t delta=0x9E3779B9;
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];

    for (i=0; i<32; i++)
    {
        v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
        v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        sum -= delta;
    }

    v[0]=v0; v[1]=v1;
}