TEA加密演算法的C/C++實現
阿新 • • 發佈:2018-12-27
TEA(Tiny Encryption Algorithm)
是一種簡單高效的加密演算法,以加密解密速度快,實現簡單著稱。演算法真的很簡單,TEA演算法每一次可以操作64-bit(8-byte),採用128-bit(16-byte)作為key,演算法採用迭代的形式,推薦的迭代輪數是64輪,最少32輪。目前我只知道QQ一直用的是16輪TEA。沒什麼好說的,先給出C語言的原始碼(預設是32輪):
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 }
C語言寫的用起來當然不方便,沒關係,用C++封裝以下就OK了:
util.h
1 #ifndef UTIL_H
2 #define UTIL_H
3 4 #include <string> 5 #include <cstdlib> 6 7 typedef unsigned charbyte;
8 typedef unsigned long ulong;
9 10 /*11 *convert int to hex char.
12 *example:10 -> 'A',15 -> 'F'
13 */14 char intToHexChar(int x);
15 16 /*17 *convert hex char to int.
18 *example:'A' -> 10,'F' -> 15
19 */20 int hexCharToInt(char hex);
21 22 using std::string;
23 /*24 *convert a byte array to hex string.
25 *hex string format example:"AF B0 80 7D"
26 */27 string bytesToHexString(constbyte*in, size_t size);
28 29 /*30 *convert a hex string to a byte array.
31 *hex string format example:"AF B0 80 7D"
32 */33 size_t hexStringToBytes(const string &str, byte*out);
34 35 #endif/*UTIL_H*/
util.cpp
1 #include "util.h" 2 #include <vector> 3 4 using namespace std;
5 6 char intToHexChar(int x) {
7 staticconstchar 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 return0;
23 }
24 25 string bytesToHexString(constbyte*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(constbyte*key, int round =32, bool isNetByte =false);
14 TEA(const TEA &rhs);
15 TEA& operator=(const TEA &rhs);
16 void encrypt(constbyte*in, byte*out);
17 void decrypt(constbyte*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 decrypt25 bool _isNetByte; //whether input bytes come from network26 byte _key[16]; //encrypt or decrypt key27 };
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(constbyte*key, int round /*= 32*/, bool isNetByte /*= false*/)
7 :_round(round)
8 ,_isNetByte(isNetByte) {
9 if (key !=0)
10 memcpy(_key, key, 16);
11 else12 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(constbyte*in, byte*out) {
31 encrypt((const ulong*)in, (ulong*)out);
32 }
33 34 void TEA::decrypt(constbyte*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 elseif (round ==16)
76 sum =0xE3779B90; /* delta << 4*/77 else78 sum = delta * 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
1 void encrypt(unsigned long*v, unsigned long*k) {
2 unsigned long y=v[0], z=v[1], sum=0, i;
7 y += ((z<<4) + a) ^ (z + sum)
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;
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 <cstdlib> 6 7 typedef unsigned charbyte;
8 typedef unsigned long ulong;
9 10 /*11 *convert int to hex char.
12 *example:10 -> 'A',15 -> 'F'
13 */14 char intToHexChar(int x);
15 16 /*17 *convert hex char to int.
18 *example:'A' -> 10,'F' -> 15
19 */20 int hexCharToInt(char hex);
21 22 using std::string;
23 /*24 *convert a byte array to hex string.
25 *hex string format example:"AF B0 80 7D"
26 */27 string bytesToHexString(constbyte*in, size_t size);
28 29 /*30 *convert a hex string to a byte array.
31 *hex string format example:"AF B0 80 7D"
32 */33 size_t hexStringToBytes(const string &str, byte*out);
34 35 #endif/*UTIL_H*/
util.cpp
1 #include "util.h" 2 #include <vector> 3 4 using namespace std;
5 6 char intToHexChar(int x) {
7 staticconstchar 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 return0;
23 }
24 25 string bytesToHexString(constbyte*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(constbyte*key, int round =32, bool isNetByte =false);
14 TEA(const TEA &rhs);
15 TEA& operator=(const TEA &rhs);
16 void encrypt(constbyte*in, byte*out);
17 void decrypt(constbyte*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 decrypt25 bool _isNetByte; //whether input bytes come from network26 byte _key[16]; //encrypt or decrypt key27 };
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(constbyte*key, int round /*= 32*/, bool isNetByte /*= false*/)
7 :_round(round)
8 ,_isNetByte(isNetByte) {
9 if (key !=0)
10 memcpy(_key, key, 16);
11 else12 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(constbyte*in, byte*out) {
31 encrypt((const ulong*)in, (ulong*)out);
32 }
33 34 void TEA::decrypt(constbyte*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 elseif (round ==16)
76 sum =0xE3779B90; /* delta << 4*/77 else78 sum = delta * 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