1
void
encrypt(unsigned
long
*
v, unsigned
long
*
k) {
2 unsigned long y = v[ 0 ], z = v[ 1 ], sum = 0 , i; /* set up */
3 unsigned long delta = 0x9e3779b9 ; /* a key schedule constant */
4 unsigned long a = k[ 0 ], b = k[ 1 ], c = k[ 2 ], d = k[ 3 ]; /* cache key */
5 for (i = 0 ; i < 32 ; i ++ ) { /* basic cycle start */
6 sum += delta;
7 y += ((z << 4 ) + a) ^ (z + sum) ^ ((z >> 5 ) + b);
8 z += ((y << 4 ) + c) ^ (y + sum) ^ ((y >> 5 ) + d); /* end cycle */
9 }
10 v[ 0 ] = y;
11 v[ 1 ] = z;
12 }
13
14 void decrypt(unsigned long * v, unsigned long * k) {
15 unsigned long y = v[ 0 ], z = v[ 1 ], sum = 0xC6EF3720 , i; /* set up */
16 unsigned long delta = 0x9e3779b9 ; /* a key schedule constant */
17 unsigned long a = k[ 0 ], b = k[ 1 ], c = k[ 2 ], d = k[ 3 ]; /* cache key */
18 for (i = 0 ; i < 32 ; i ++ ) { /* basic cycle start */
19 z -= ((y << 4 ) + c) ^ (y + sum) ^ ((y >> 5 ) + d);
20 y -= ((z << 4 ) + a) ^ (z + sum) ^ ((z >> 5 ) + b);
21 sum -= delta; /* end cycle */
22 }
23 v[ 0 ] = y;
24 v[ 1 ] = z;
25 }
2 unsigned long y = v[ 0 ], z = v[ 1 ], sum = 0 , i; /* set up */
3 unsigned long delta = 0x9e3779b9 ; /* a key schedule constant */
4 unsigned long a = k[ 0 ], b = k[ 1 ], c = k[ 2 ], d = k[ 3 ]; /* cache key */
5 for (i = 0 ; i < 32 ; i ++ ) { /* basic cycle start */
6 sum += delta;
7 y += ((z << 4 ) + a) ^ (z + sum) ^ ((z >> 5 ) + b);
8 z += ((y << 4 ) + c) ^ (y + sum) ^ ((y >> 5 ) + d); /* end cycle */
9 }
10 v[ 0 ] = y;
11 v[ 1 ] = z;
12 }
13
14 void decrypt(unsigned long * v, unsigned long * k) {
15 unsigned long y = v[ 0 ], z = v[ 1 ], sum = 0xC6EF3720 , i; /* set up */
16 unsigned long delta = 0x9e3779b9 ; /* a key schedule constant */
17 unsigned long a = k[ 0 ], b = k[ 1 ], c = k[ 2 ], d = k[ 3 ]; /* cache key */
18 for (i = 0 ; i < 32 ; i ++ ) { /* basic cycle start */
19 z -= ((y << 4 ) + c) ^ (y + sum) ^ ((y >> 5 ) + d);
20 y -= ((z << 4 ) + a) ^ (z + sum) ^ ((z >> 5 ) + b);
21 sum -= delta; /* end cycle */
22 }
23 v[ 0 ] = y;
24 v[ 1 ] = z;
25 }
C语言写的用起来当然不方便,没关系,用C++封装以下就OK了:
util.h
1
#ifndef UTIL_H
2 #define UTIL_H
3
4 #include < string >
5 #include < cmath >
6 #include < cstdlib >
7
8 typedef unsigned char byte ;
9 typedef unsigned long ulong;
10
11 inline double logbase( double base, double x) {
12 return log(x) / log(base);
13 }
14
15 /*
16 *convert int to hex char.
17 *example:10 -> 'A',15 -> 'F'
18 */
19 char intToHexChar( int x);
20
21 /*
22 *convert hex char to int.
23 *example:'A' -> 10,'F' -> 15
24 */
25 int hexCharToInt( char hex);
26
27 using std::string;
28 /*
29 *convert a byte array to hex string.
30 *hex string format example:"AF B0 80 7D"
31 */
32 string bytesToHexString( const byte * in, size_t size);
33
34 /*
35 *convert a hex string to a byte array.
36 *hex string format example:"AF B0 80 7D"
37 */
38 size_t hexStringToBytes( const string & str, byte * out);
39
40 #endif /* UTIL_H */
2 #define UTIL_H
3
4 #include < string >
5 #include < cmath >
6 #include < cstdlib >
7
8 typedef unsigned char byte ;
9 typedef unsigned long ulong;
10
11 inline double logbase( double base, double x) {
12 return log(x) / log(base);
13 }
14
15 /*
16 *convert int to hex char.
17 *example:10 -> 'A',15 -> 'F'
18 */
19 char intToHexChar( int x);
20
21 /*
22 *convert hex char to int.
23 *example:'A' -> 10,'F' -> 15
24 */
25 int hexCharToInt( char hex);
26
27 using std::string;
28 /*
29 *convert a byte array to hex string.
30 *hex string format example:"AF B0 80 7D"
31 */
32 string bytesToHexString( const byte * in, size_t size);
33
34 /*
35 *convert a hex string to a byte array.
36 *hex string format example:"AF B0 80 7D"
37 */
38 size_t hexStringToBytes( const string & str, byte * out);
39
40 #endif /* UTIL_H */
util.cpp
1
#include
"
util.h
"
2 #include < vector >
3
4 using namespace std;
5
6 char intToHexChar( int x) {
7 static const char HEX[ 16 ] = {
8 ' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' ,
9 ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' ,
10 ' 8 ' , ' 9 ' , ' A ' , ' B ' ,
11 ' C ' , ' D ' , ' E ' , ' F '
12 };
13 return HEX[x];
14 }
15
16 int hexCharToInt( char hex) {
17 hex = toupper(hex);
18 if (isdigit(hex))
19 return (hex - ' 0 ' );
20 if (isalpha(hex))
21 return (hex - ' A ' + 10 );
22 return 0 ;
23 }
24
25 string bytesToHexString( const byte * in, size_t size) {
26 string str;
27 for (size_t i = 0 ; i < size; ++ i) {
28 int t = in[i];
29 int a = t / 16 ;
30 int b = t % 16 ;
31 str.append( 1 , intToHexChar(a));
32 str.append( 1 , intToHexChar(b));
33 if (i != size - 1 )
34 str.append( 1 , ' ' );
35 }
36 return str;
37 }
38
39 size_t hexStringToBytes( const string & str, byte * out) {
40
41 vector < string > vec;
42 string::size_type currPos = 0 , prevPos = 0 ;
43 while ((currPos = str.find( ' ' , prevPos)) != string::npos) {
44 string b(str.substr(prevPos, currPos - prevPos));
45 vec.push_back(b);
46 prevPos = currPos + 1 ;
47 }
48 if (prevPos < str.size()) {
49 string b(str.substr(prevPos));
50 vec.push_back(b);
51 }
52 typedef vector < string > ::size_type sz_type;
53 sz_type size = vec.size();
54 for (sz_type i = 0 ; i < size; ++ i) {
55 int a = hexCharToInt(vec[i][ 0 ]);
56 int b = hexCharToInt(vec[i][ 1 ]);
57 out[i] = a * 16 + b;
58 }
59 return size;
60 }
2 #include < vector >
3
4 using namespace std;
5
6 char intToHexChar( int x) {
7 static const char HEX[ 16 ] = {
8 ' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' ,
9 ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' ,
10 ' 8 ' , ' 9 ' , ' A ' , ' B ' ,
11 ' C ' , ' D ' , ' E ' , ' F '
12 };
13 return HEX[x];
14 }
15
16 int hexCharToInt( char hex) {
17 hex = toupper(hex);
18 if (isdigit(hex))
19 return (hex - ' 0 ' );
20 if (isalpha(hex))
21 return (hex - ' A ' + 10 );
22 return 0 ;
23 }
24
25 string bytesToHexString( const byte * in, size_t size) {
26 string str;
27 for (size_t i = 0 ; i < size; ++ i) {
28 int t = in[i];
29 int a = t / 16 ;
30 int b = t % 16 ;
31 str.append( 1 , intToHexChar(a));
32 str.append( 1 , intToHexChar(b));
33 if (i != size - 1 )
34 str.append( 1 , ' ' );
35 }
36 return str;
37 }
38
39 size_t hexStringToBytes( const string & str, byte * out) {
40
41 vector < string > vec;
42 string::size_type currPos = 0 , prevPos = 0 ;
43 while ((currPos = str.find( ' ' , prevPos)) != string::npos) {
44 string b(str.substr(prevPos, currPos - prevPos));
45 vec.push_back(b);
46 prevPos = currPos + 1 ;
47 }
48 if (prevPos < str.size()) {
49 string b(str.substr(prevPos));
50 vec.push_back(b);
51 }
52 typedef vector < string > ::size_type sz_type;
53 sz_type size = vec.size();
54 for (sz_type i = 0 ; i < size; ++ i) {
55 int a = hexCharToInt(vec[i][ 0 ]);
56 int b = hexCharToInt(vec[i][ 1 ]);
57 out[i] = a * 16 + b;
58 }
59 return size;
60 }
tea.h
1
#ifndef TEA_H
2 #define TEA_H
3
4 /*
5 *for htonl,htonl
6 *do remember link "ws2_32.lib"
7 */
8 #include < winsock2.h >
9 #include " util.h "
10
11 class TEA {
12 public :
13 TEA( const byte * key, int round = 32 , bool isNetByte = false );
14 TEA( const TEA & rhs);
15 TEA & operator = ( const TEA & rhs);
16 void encrypt( const byte * in, byte * out);
17 void decrypt( const byte * in, byte * out);
18 private :
19 void encrypt( const ulong * in, ulong * out);
20 void decrypt( const ulong * in, ulong * out);
21 ulong ntoh(ulong netlong) { return _isNetByte ? ntohl(netlong) : netlong; }
22 ulong hton(ulong hostlong) { return _isNetByte ? htonl(hostlong) : hostlong; }
23 private :
24 int _round; // iteration round to encrypt or decrypt
25 bool _isNetByte; // whether input bytes come from network
26 byte _key[ 16 ]; // encrypt or decrypt key
27 };
28
29 #endif /* TEA_H */
2 #define TEA_H
3
4 /*
5 *for htonl,htonl
6 *do remember link "ws2_32.lib"
7 */
8 #include < winsock2.h >
9 #include " util.h "
10
11 class TEA {
12 public :
13 TEA( const byte * key, int round = 32 , bool isNetByte = false );
14 TEA( const TEA & rhs);
15 TEA & operator = ( const TEA & rhs);
16 void encrypt( const byte * in, byte * out);
17 void decrypt( const byte * in, byte * out);
18 private :
19 void encrypt( const ulong * in, ulong * out);
20 void decrypt( const ulong * in, ulong * out);
21 ulong ntoh(ulong netlong) { return _isNetByte ? ntohl(netlong) : netlong; }
22 ulong hton(ulong hostlong) { return _isNetByte ? htonl(hostlong) : hostlong; }
23 private :
24 int _round; // iteration round to encrypt or decrypt
25 bool _isNetByte; // whether input bytes come from network
26 byte _key[ 16 ]; // encrypt or decrypt key
27 };
28
29 #endif /* TEA_H */
tea.cpp
1
#include
"
tea.h
"
2 #include < cstring > // for memcpy,memset
3
4 using namespace std;
5
6 TEA::TEA( const byte * key, int round /* = 32 */ , bool isNetByte /* = false */ )
7 :_round(round)
8 ,_isNetByte(isNetByte) {
9 if (key != 0 )
10 memcpy(_key, key, 16 );
11 else
12 memset(_key, 0 , 16 );
13 }
14
15 TEA::TEA( const TEA & rhs)
16 :_round(rhs._round)
17 ,_isNetByte(rhs._isNetByte) {
18 memcpy(_key, rhs._key, 16 );
19 }
20
21 TEA & TEA::operator = ( const TEA & rhs) {
22 if ( & rhs != this ) {
23 _round = rhs._round;
24 _isNetByte = rhs._isNetByte;
25 memcpy(_key, rhs._key, 16 );
26 }
27 return * this ;
28 }
29
30 void TEA::encrypt( const byte * in, byte * out) {
31 encrypt(( const ulong * )in, (ulong * )out);
32 }
33
34 void TEA::decrypt( const byte * in, byte * out) {
35 decrypt(( const ulong * )in, (ulong * )out);
36 }
37
38 void TEA::encrypt( const ulong * in, ulong * out) {
39
40 ulong * k = (ulong * )_key;
41 register ulong y = ntoh(in[ 0 ]);
42 register ulong z = ntoh(in[ 1 ]);
43 register ulong a = ntoh(k[ 0 ]);
44 register ulong b = ntoh(k[ 1 ]);
45 register ulong c = ntoh(k[ 2 ]);
46 register ulong d = ntoh(k[ 3 ]);
47 register ulong delta = 0x9E3779B9 ; /* (sqrt(5)-1)/2*2^32 */
48 register int round = _round;
49 register ulong sum = 0 ;
50
51 while (round -- ) { /* basic cycle start */
52 sum += delta;
53 y += ((z << 4 ) + a) ^ (z + sum) ^ ((z >> 5 ) + b);
54 z += ((y << 4 ) + c) ^ (y + sum) ^ ((y >> 5 ) + d);
55 } /* end cycle */
56 out[ 0 ] = ntoh(y);
57 out[ 1 ] = ntoh(z);
58 }
59
60 void TEA::decrypt( const ulong * in, ulong * out) {
61
62 ulong * k = (ulong * )_key;
63 register ulong y = ntoh(in[ 0 ]);
64 register ulong z = ntoh(in[ 1 ]);
65 register ulong a = ntoh(k[ 0 ]);
66 register ulong b = ntoh(k[ 1 ]);
67 register ulong c = ntoh(k[ 2 ]);
68 register ulong d = ntoh(k[ 3 ]);
69 register ulong delta = 0x9E3779B9 ; /* (sqrt(5)-1)/2*2^32 */
70 register int round = _round;
71 register ulong sum = 0 ;
72
73 if (round == 32 )
74 sum = 0xC6EF3720 ; /* delta << 5 */
75 else if (round == 16 )
76 sum = 0xE3779B90 ; /* delta << 4 */
77 else
78 sum = delta << static_cast < int > (logbase( 2 , round));
79
80 while (round -- ) { /* basic cycle start */
81 z -= ((y << 4 ) + c) ^ (y + sum) ^ ((y >> 5 ) + d);
82 y -= ((z << 4 ) + a) ^ (z + sum) ^ ((z >> 5 ) + b);
83 sum -= delta;
84 } /* end cycle */
85 out[ 0 ] = ntoh(y);
86 out[ 1 ] = ntoh(z);
87 }
2 #include < cstring > // for memcpy,memset
3
4 using namespace std;
5
6 TEA::TEA( const byte * key, int round /* = 32 */ , bool isNetByte /* = false */ )
7 :_round(round)
8 ,_isNetByte(isNetByte) {
9 if (key != 0 )
10 memcpy(_key, key, 16 );
11 else
12 memset(_key, 0 , 16 );
13 }
14
15 TEA::TEA( const TEA & rhs)
16 :_round(rhs._round)
17 ,_isNetByte(rhs._isNetByte) {
18 memcpy(_key, rhs._key, 16 );
19 }
20
21 TEA & TEA::operator = ( const TEA & rhs) {
22 if ( & rhs != this ) {
23 _round = rhs._round;
24 _isNetByte = rhs._isNetByte;
25 memcpy(_key, rhs._key, 16 );
26 }
27 return * this ;
28 }
29
30 void TEA::encrypt( const byte * in, byte * out) {
31 encrypt(( const ulong * )in, (ulong * )out);
32 }
33
34 void TEA::decrypt( const byte * in, byte * out) {
35 decrypt(( const ulong * )in, (ulong * )out);
36 }
37
38 void TEA::encrypt( const ulong * in, ulong * out) {
39
40 ulong * k = (ulong * )_key;
41 register ulong y = ntoh(in[ 0 ]);
42 register ulong z = ntoh(in[ 1 ]);
43 register ulong a = ntoh(k[ 0 ]);
44 register ulong b = ntoh(k[ 1 ]);
45 register ulong c = ntoh(k[ 2 ]);
46 register ulong d = ntoh(k[ 3 ]);
47 register ulong delta = 0x9E3779B9 ; /* (sqrt(5)-1)/2*2^32 */
48 register int round = _round;
49 register ulong sum = 0 ;
50
51 while (round -- ) { /* basic cycle start */
52 sum += delta;
53 y += ((z << 4 ) + a) ^ (z + sum) ^ ((z >> 5 ) + b);
54 z += ((y << 4 ) + c) ^ (y + sum) ^ ((y >> 5 ) + d);
55 } /* end cycle */
56 out[ 0 ] = ntoh(y);
57 out[ 1 ] = ntoh(z);
58 }
59
60 void TEA::decrypt( const ulong * in, ulong * out) {
61
62 ulong * k = (ulong * )_key;
63 register ulong y = ntoh(in[ 0 ]);
64 register ulong z = ntoh(in[ 1 ]);
65 register ulong a = ntoh(k[ 0 ]);
66 register ulong b = ntoh(k[ 1 ]);
67 register ulong c = ntoh(k[ 2 ]);
68 register ulong d = ntoh(k[ 3 ]);
69 register ulong delta = 0x9E3779B9 ; /* (sqrt(5)-1)/2*2^32 */
70 register int round = _round;
71 register ulong sum = 0 ;
72
73 if (round == 32 )
74 sum = 0xC6EF3720 ; /* delta << 5 */
75 else if (round == 16 )
76 sum = 0xE3779B90 ; /* delta << 4 */
77 else
78 sum = delta << static_cast < int > (logbase( 2 , round));
79
80 while (round -- ) { /* basic cycle start */
81 z -= ((y << 4 ) + c) ^ (y + sum) ^ ((y >> 5 ) + d);
82 y -= ((z << 4 ) + a) ^ (z + sum) ^ ((z >> 5 ) + b);
83 sum -= delta;
84 } /* end cycle */
85 out[ 0 ] = ntoh(y);
86 out[ 1 ] = ntoh(z);
87 }
需要说明的是TEA的构造函数:
TEA(const byte *key, int round = 32, bool isNetByte = false);
1. key - 加密或解密用的128-bit(16byte)密钥。
2. round - 加密或解密的轮数,常用的有64,32,16。
3. isNetByte - 用来标记待处理的字节是不是来自网络,为true时在加密/解密前先要转换成本地字节,执行加密/解密,然后再转换回网络字节。偷偷告诉你,QQ就是这样做的!
最后当然少不了测试代码:
test.cpp
1
#include
"
tea.h
"
2 #include " util.h "
3 #include < iostream >
4
5 using namespace std;
6
7 int main() {
8
9 const string plainStr( " AD DE E2 DB B3 E2 DB B3 " );
10 const string keyStr( " 3A DA 75 21 DB E2 DB B3 11 B4 49 01 A5 C6 EA D4 " );
11 const int SIZE_IN = 8 , SIZE_OUT = 8 , SIZE_KEY = 16 ;
12 byte plain[SIZE_IN], crypt[SIZE_OUT], key[SIZE_KEY];
13
14 size_t size_in = hexStringToBytes(plainStr, plain);
15 size_t size_key = hexStringToBytes(keyStr, key);
16
17 if (size_in != SIZE_IN || size_key != SIZE_KEY)
18 return - 1 ;
19
20 cout << " Plain: " << bytesToHexString(plain, size_in) << endl;
21 cout << " Key : " << bytesToHexString(key, size_key) << endl;
22
23 TEA tea(key, 16 , true );
24 tea.encrypt(plain, crypt);
25 cout << " Crypt: " << bytesToHexString(crypt, SIZE_OUT) << endl;
26
27 tea.decrypt(crypt, plain);
28 cout << " Plain: " << bytesToHexString(plain, SIZE_IN) << endl;
29 return 0 ;
30 }
2 #include " util.h "
3 #include < iostream >
4
5 using namespace std;
6
7 int main() {
8
9 const string plainStr( " AD DE E2 DB B3 E2 DB B3 " );
10 const string keyStr( " 3A DA 75 21 DB E2 DB B3 11 B4 49 01 A5 C6 EA D4 " );
11 const int SIZE_IN = 8 , SIZE_OUT = 8 , SIZE_KEY = 16 ;
12 byte plain[SIZE_IN], crypt[SIZE_OUT], key[SIZE_KEY];
13
14 size_t size_in = hexStringToBytes(plainStr, plain);
15 size_t size_key = hexStringToBytes(keyStr, key);
16
17 if (size_in != SIZE_IN || size_key != SIZE_KEY)
18 return - 1 ;
19
20 cout << " Plain: " << bytesToHexString(plain, size_in) << endl;
21 cout << " Key : " << bytesToHexString(key, size_key) << endl;
22
23 TEA tea(key, 16 , true );
24 tea.encrypt(plain, crypt);
25 cout << " Crypt: " << bytesToHexString(crypt, SIZE_OUT) << endl;
26
27 tea.decrypt(crypt, plain);
28 cout << " Plain: " << bytesToHexString(plain, SIZE_IN) << endl;
29 return 0 ;
30 }
运行结果:
Plain: AD DE E2 DB B3 E2 DB B3
Key : 3A DA 75 21 DB E2 DB B3 11 B4 49 01 A5 C6 EA D4
Crypt: 3B 3B 4D 8C 24 3A FD F2
Plain: AD DE E2 DB B3 E2 DB B3
源代码下载: 点击下载