简单但不平凡的加密算法 - XXTEA

4 分钟阅读

微型加密算法(Tiny Encryption Algorithm,TEA)是剑桥大学计算机实验室的David Wheeler与Roger Needham于1994年发明。算法以加密解密速度快,实现简单著称。TEA算法每一次可以操作64bit(8byte),采用128bit(16byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。

XXTEA 是TEA系列算法中的最新版本,也是其第三个版本,发表于1998年,进一步提高了TEA算法的安全性,避免了密钥表攻击。

TXTEA是腾讯QQ和微信中常用的加密算法,算法原理不变,降低加密轮次到16轮。

其轻量,易实现、易跨平台特性使XXTEA而被广泛应用于各个领域。例如:游戏(Cocos2d-x)、通信(QQ和微信)、嵌入式、芯片卡等等。

TEA

TEA算法初版源码 - 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
#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;
}

Java中实现

将byte[]类型的加密内容转换为int[],方便处理运算。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Convert byte array to int array.
*/
private static int[] toIntArray(byte[] data, boolean includeLength) {
    int n = (((data.length & 3) == 0) ? (data.length >>> 2) : ((data.length >>> 2) + 1));
    int[] result;

    if (includeLength) {
        result = new int[n + 1];
        result[n] = data.length;
    } else {
        result = new int[n];
    }
    n = data.length;
    for (int i = 0; i < n; i++) {
        result[i >>> 2] |= (0x000000ff & data[i]) << ((i & 3) << 3);
    }
    return result;
}

加密:

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
/**
* Encrypt data with key.
*/
public static int[] encrypt(int[] v, int[] k) {
    int n = v.length - 1;
    if (n < 1) {
        return v;
    }
    if (k.length < 4) {
        int[] key = new int[4];
        System.arraycopy(k, 0, key, 0, k.length);
        k = key;
    }
    int z = v[n], y = v[0], delta = 0x9E3779B9, sum = 0, e;
    int p, q = 6 + 52 / (n + 1);

    while (q-- > 0) {
        sum = sum + delta;
        e = sum >>> 2 & 3;
        for (p = 0; p < n; p++) {
            y = v[p + 1];
            z = v[p] += (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
        }
        y = v[0];
        z = v[n] += (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
    }
    return v;
}

解密:

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
/**
* Decrypt data with key.
*/
public static int[] decrypt(int[] v, int[] k) {
    int n = v.length - 1;
    if (n < 1) {
        return v;
    }
    if (k.length < 4) {
        int[] key = new int[4];
        System.arraycopy(k, 0, key, 0, k.length);
        k = key;
    }
    int z = v[n], y = v[0], delta = 0x9E3779B9, sum, e;
    int p, q = 6 + 52 / (n + 1);
    sum = q * delta;
    while (sum != 0) {
        e = sum >>> 2 & 3;
        for (p = n; p > 0; p--) {
            z = v[p - 1];
            y = v[p] -= (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
        }
        z = v[n];
        y = v[0] -= (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
        sum = sum - delta;
    }
    return v;
}

解密完成将int[]转换为byte[].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Convert int array to byte array.
*/
private static byte[] toByteArray(int[] data, boolean includeLength) {
    int n = data.length << 2;
    if (includeLength) {
        int m = data[data.length - 1];
        if (m > n) {
            return null;
        } else {
            n = m;
        }
    }
    byte[] result = new byte[n];
    for (int i = 0; i < n; i++) {
        result[i] = (byte) ((data[i >>> 2] >>> ((i & 3) << 3)) & 0xff);
    }
    return result;
}

知识共享许可协议

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 TinyZ Zzh (包含链接: https://tinyzzh.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。 如有任何疑问,请 与我联系 (tinyzzh815@gmail.com)

TinyZ Zzh

TinyZ Zzh

专注于高并发服务器、网络游戏相关(Java、PHP、Unity3D、Unreal Engine等)技术,热爱游戏事业, 正在努力实现自我价值当中。

评论

  点击开始评论...