Skip to content
This repository has been archived by the owner on Sep 15, 2020. It is now read-only.

腾讯TEA加密算法

苇子 edited this page Oct 6, 2017 · 3 revisions

腾讯常用的TEA加密算法,网上已经有很多人分析过了,自己再总结一下。

TEA加密/解密块

每次处理64位数据,使用128位密钥。数据和密钥都分割成32为无符号整型处理。TEA标准中使用的32轮加密,而腾讯只用了16轮。更多信息参考维基百科。 腾讯使用的TEA加/解密块用C代码实现如下:

#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 < 16; 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], i;  /* set up */
    uint32_t delta=0x9e3779b9;                     /* a key schedule constant */
    uint32_t sum = delta << 4;
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */
    for (i=0; i<16; 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;
}

填充

TEA每次处理8字节数据,但真实的数据可能是任意长度的,所以需要填充为8字节的整数倍。填充的字计数为filln = (- (len + 2)) % 8 + 2,这保证了填充字节数2 <= filln <= 9。一般来说,填充成8字节的整数倍,只需要加上filln= (-len) % 8字节就可以了,但是这样0 <= filln <= 7,有可能出现不填充的情况,不填充就没有随机性。填充了多少随机数是需要保存的,否则解密后没办法取出明文,所以最终的填充是:

fills = ''
for i in range(filln):
    fills += chr(rand()&0xff)

filledplaintext = chr(rand() & 0xf8 | (filln-2))) \
                    + fills \
                    + plaintext \
                    + '\0' * 7

加密模式

分组密码工作模式有EBC、CBC、PCBC、CFB、OFB、CTR。但是腾讯采用的是改进的CBC,CBC加密模式参见维基百科,腾讯使用的改进CBC示意图如下:

其中IV1和IV2都为全0。

Clone this wiki locally