TEA(Tiny Encryption Algorithm)
是一種簡單高效的加密算法,以加密解密速度快,實(shí)現(xiàn)簡單著稱。算法真的很簡單,TEA算法每一次可以操作64-bit(8-byte),采用128-bit(16-byte)作為key,算法采用迭代的形式,推薦的迭代輪數(shù)是64輪,最少32輪。目前我只知道QQ一直用的是16輪TEA。沒什么好說的,先給出C語言的源代碼(默認(rèn)是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語言寫的用起來當(dāng)然不方便,沒關(guān)系,用C++封裝以下就OK了:
util.h
?1?#ifndef?UTIL_H
?2?#define?UTIL_H
?3?
?4?#include?<string>
?5?#include?<cstdlib>
?6?
?7?typedef?unsigned?char?byte;
?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(const?byte?*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?????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*/
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?*?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的構(gòu)造函數(shù):
TEA(const byte *key, int round = 32, bool isNetByte = false);1.
key - 加密或解密用的128-bit(16byte)密鑰。
2.
round - 加密或解密的輪數(shù),常用的有64,32,16。
3.
isNetByte - 用來標(biāo)記待處理的字節(jié)是不是來自網(wǎng)絡(luò),為true時在加密/解密前先要轉(zhuǎn)換成本地字節(jié),執(zhí)行加密/解密,然后再轉(zhuǎn)換回網(wǎng)絡(luò)字節(jié)。偷偷告訴你,QQ就是這樣做的!
最后當(dāng)然少不了測試代碼:
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?}
運(yùn)行結(jié)果:
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源代碼下載:
點(diǎn)擊下載