C++版本的XXTEA实现

算法实现


头文件:xxtea.h

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
29
#ifndef XXTEA_H
#define XXTEA_H

#include <stddef.h> /* for size_t & NULL declarations */

#if defined(_MSC_VER)

typedef unsigned __int32 xxtea_long;

#else

#if defined(__FreeBSD__) && __FreeBSD__ < 5
/* FreeBSD 4 doesn't have stdint.h file */
#include <inttypes.h>
#else
#include <stdint.h>
#endif

typedef uint32_t xxtea_long;

#endif /* end of if defined(_MSC_VER) */

#define XXTEA_MX (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z)
#define XXTEA_DELTA 0x9e3779b9

unsigned char *xxtea_encrypt(unsigned char *data, xxtea_long data_len, unsigned char *key, xxtea_long key_len, xxtea_long *ret_length);
unsigned char *xxtea_decrypt(unsigned char *data, xxtea_long data_len, unsigned char *key, xxtea_long key_len, xxtea_long *ret_length);

#endif

源文件:xxtea.cpp

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include "xxtea.h"
#include <memory.h>
#include <stdlib.h>

static void xxtea_long_encrypt(xxtea_long *v, xxtea_long len, xxtea_long *k)
{
xxtea_long n = len - 1;
xxtea_long z = v[n], y = v[0], p, q = 6 + 52 / (n + 1), sum = 0, e;
if (n < 1) {
return;
}
while (0 < q--) {
sum += XXTEA_DELTA;
e = sum >> 2 & 3;
for (p = 0; p < n; p++) {
y = v[p + 1];
z = v[p] += XXTEA_MX;
}
y = v[0];
z = v[n] += XXTEA_MX;
}
}

static void xxtea_long_decrypt(xxtea_long *v, xxtea_long len, xxtea_long *k)
{
xxtea_long n = len - 1;
xxtea_long z = v[n], y = v[0], p, q = 6 + 52 / (n + 1), sum = q * XXTEA_DELTA, e;
if (n < 1) {
return;
}
while (sum != 0) {
e = sum >> 2 & 3;
for (p = n; p > 0; p--) {
z = v[p - 1];
y = v[p] -= XXTEA_MX;
}
z = v[n];
y = v[0] -= XXTEA_MX;
sum -= XXTEA_DELTA;
}
}

static unsigned char *fix_key_length(unsigned char *key, xxtea_long key_len)
{
unsigned char *tmp = (unsigned char *)malloc(16);
memcpy(tmp, key, key_len);
memset(tmp + key_len, '\0', 16 - key_len);
return tmp;
}

static xxtea_long *xxtea_to_long_array(unsigned char *data, xxtea_long len, int include_length, xxtea_long *ret_len) {
xxtea_long i, n, *result;

n = len >> 2;
n = (((len & 3) == 0) ? n : n + 1);
if (include_length) {
result = (xxtea_long *)malloc((n + 1) << 2);
result[n] = len;
*ret_len = n + 1;
} else {
result = (xxtea_long *)malloc(n << 2);
*ret_len = n;
}
memset(result, 0, n << 2);
for (i = 0; i < len; i++) {
result[i >> 2] |= (xxtea_long)data[i] << ((i & 3) << 3);
}

return result;
}

static unsigned char *xxtea_to_byte_array(xxtea_long *data, xxtea_long len, int include_length, xxtea_long *ret_len) {
xxtea_long i, n, m;
unsigned char *result;

n = len << 2;
if (include_length) {
m = data[len - 1];
if ((m < n - 7) || (m > n - 4)) return NULL;
n = m;
}
result = (unsigned char *)malloc(n + 1);
for (i = 0; i < n; i++) {
result[i] = (unsigned char)((data[i >> 2] >> ((i & 3) << 3)) & 0xff);
}
result[n] = '\0';
*ret_len = n;

return result;
}

static unsigned char *do_xxtea_encrypt(unsigned char *data, xxtea_long len, unsigned char *key, xxtea_long *ret_len) {
unsigned char *result;
xxtea_long *v, *k, v_len, k_len;

v = xxtea_to_long_array(data, len, 1, &v_len);
k = xxtea_to_long_array(key, 16, 0, &k_len);
xxtea_long_encrypt(v, v_len, k);
result = xxtea_to_byte_array(v, v_len, 0, ret_len);
free(v);
free(k);

return result;
}

static unsigned char *do_xxtea_decrypt(unsigned char *data, xxtea_long len, unsigned char *key, xxtea_long *ret_len) {
unsigned char *result;
xxtea_long *v, *k, v_len, k_len;

v = xxtea_to_long_array(data, len, 0, &v_len);
k = xxtea_to_long_array(key, 16, 0, &k_len);
xxtea_long_decrypt(v, v_len, k);
result = xxtea_to_byte_array(v, v_len, 1, ret_len);
free(v);
free(k);

return result;
}

unsigned char *xxtea_encrypt(unsigned char *data, xxtea_long data_len, unsigned char *key, xxtea_long key_len, xxtea_long *ret_length)
{
unsigned char *result;

*ret_length = 0;

if (key_len < 16) {
unsigned char *key2 = fix_key_length(key, key_len);
result = do_xxtea_encrypt(data, data_len, key2, ret_length);
free(key2);
}
else
{
result = do_xxtea_encrypt(data, data_len, key, ret_length);
}

return result;
}

unsigned char *xxtea_decrypt(unsigned char *data, xxtea_long data_len, unsigned char *key, xxtea_long key_len, xxtea_long *ret_length)
{
unsigned char *result;

*ret_length = 0;

if (key_len < 16) {
unsigned char *key2 = fix_key_length(key, key_len);
result = do_xxtea_decrypt(data, data_len, key2, ret_length);
free(key2);
}
else
{
result = do_xxtea_decrypt(data, data_len, key, ret_length);
}

return result;
}

总结下


  • 对比python版本,应该能看出来C++的实现写的挺复杂的
  • python这门语言的抽象能力要比C++高出很多,C++需要关注很多低层次(low level)的细节问题,python作为一门脚本语言则屏蔽了这些需要考虑的细节,极大的减轻了使用者心智上的负担
  • 正是因为上面的原因,C++的使用示例写起来也挺麻烦的,也就没写了:)