linux社区爱心援助Linux认证系列教程业界动态站务新闻公司招聘建议留言网址大全LPI专题CISCO专题
设为首页
加入收藏
管理团队
JSP  
JAVA  
PERL  
 您的位置:首页 > article > Linux开发区 > 软件开发 >
栏目导栏
资料搜索
热门文章
·Linux 下 C 语言编程
·Linux下的通用线程池创建
·C++字符串转换篇
·linux C 进程操作篇
·linux上的C/C++编译器gcc/egcs
·linux C 文件权限控制篇
·GCC使用手册
·linux C 接口处理篇
·在Redhat Linux上安装 GCC 编译
·GCC使用指南
·C语言运算符
·Linux下C开发环境的构成和安装
·fopen()函数的参数说明
·GCC使用手册与常用命令
·Scheme 语言介绍
最新文章
·在Ubuntu Linux 8.04上构建GCC
·Linux操作系统下Socket编程地址
·将VC程序移植到Linux系统的几点
·Linux下malloc/free与new/dele
·Linux下用GTK和socket实现简单
·Linux操作系统下让Tomcat启动在
·Linux操作系统中如何编译C程序
·几种常被人们忽略的Linux系统下
·Eclipse编程工具 在Ubuntu下的
·Linux操作系统下的网络地址转换
·老手经验谈:Linux驱动程序开发
·Linux操作系统多线程同步Mutex
·Linux操作系统下C程序语言简易
·Linux系统平台下关于GCC编译及
·解决Linux系统下管道被接受方关
Google
 
TEA加密算法的C/C++实现
[ 作者:  加入时间:2007-09-11 11:02:34  来自:Linux联盟收集整理 ]
TEA(Tiny Encryption Algorithm) 是一种简单高效的加密算法,以加密解密速度快,实现简单著称。算法真的很简单,TEA算法每一次可以操作64-bit(8-byte),采用128-bit(16-byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。目前我只知道QQ一直用的是16轮TEA。没什么好说的,先给出C语言的源代码(默认是32轮):
微型加密算法(TEA)及其相关变种(XTEA,Block TEA,XXTEA) 都是分组加密算法,它们很容易被描述,实现也很简单(典型的几行代码)。azhLinux联盟
azhLinux联盟
TEA 算法最初是由剑桥计算机实验室的 David Wheeler 和 Roger Needham 在 1994 年设计的。该算法使用 128 位的密钥为 64 位的信息块进行加密,它需要进行 64 轮迭代,尽管作者认为 32 轮已经足够了。该算法使用了一个神秘常数δ作为倍数,它来源于黄金比率,以保证每一轮加密都不相同。但δ的精确值似乎并不重要,这里 TEA 把它定义为 δ=「(√5 - 1)231」(也就是程序中的 0×9E3779B9)。azhLinux联盟
azhLinux联盟
之后 TEA 算法被发现存在缺陷,作为回应,设计者提出了一个 TEA 的升级版本——XTEA(有时也被称为“tean”)。XTEA 跟 TEA 使用了相同的简单运算,但它采用了截然不同的顺序,为了阻止密钥表攻击,四个子密钥(在加密过程中,原 128 位的密钥被拆分为 4 个 32 位的子密钥)采用了一种不太正规的方式进行混合,但速度更慢了。azhLinux联盟
azhLinux联盟
在跟描述 XTEA 算法的同一份报告中,还介绍了另外一种被称为 Block TEA 算法的变种,它可以对 32 位大小任意倍数的变量块进行操作。该算法将 XTEA 轮循函数依次应用于块中的每个字,并且将它附加于它的邻字。该操作重复多少轮依赖于块的大小,但至少需要 6 轮。该方法的优势在于它无需操作模式(CBC,OFB,CFB 等),密钥可直接用于信息。对于长的信息它可能比 XTEA 更有效率。azhLinux联盟
azhLinux联盟
在 1998 年,Markku-Juhani Saarinen 给出了一个可有效攻击 Block TEA 算法的代码,但之后很快 David J. Wheeler 和 Roger M. Needham 就给出了 Block TEA 算法的修订版,这个算法被称为 XXTEA。XXTEA 使用跟 Block TEA 相似的结构,但在处理块中每个字时利用了相邻字。它利用一个更复杂的 MX 函数代替了 XTEA 轮循函数,MX 使用 2 个输入量。azhLinux联盟
 1 void encrypt(unsigned long *v, unsigned long *k) {azhLinux联盟
 2     unsigned long y=v[0], z=v[1], sum=0, i;         /* set up */
azhLinux联盟
 3     unsigned long delta=0x9e3779b9;                 /* a key schedule constant */azhLinux联盟
 4     unsigned long a=k[0], b=k[1], c=k[2], d=k[3];   /* cache key */azhLinux联盟
 5     for (i=0; i < 32; i++) {                        /* basic cycle start */azhLinux联盟
 6         sum += delta;azhLinux联盟
 7         y += ((z<<4+ a) ^ (z + sum) ^ ((z>>5+
 b);azhLinux联盟
 8         z += ((y<<4+ c) ^ (y + sum) ^ ((y>>5+ d);/* end cycle */
azhLinux联盟
 9     }azhLinux联盟
10     v[0]=
y;azhLinux联盟
11     v[1]=
z;azhLinux联盟
12 
}azhLinux联盟
13 
azhLinux联盟
14 void decrypt(unsigned long *v, unsigned long *k) {azhLinux联盟
15     unsigned long y=v[0], z=v[1], sum=0xC6EF3720, i; /* set up */
azhLinux联盟
16     unsigned long delta=0x9e3779b9;                  /* a key schedule constant */azhLinux联盟
17     unsigned long a=k[0], b=k[1], c=k[2], d=k[3];    /* cache key */azhLinux联盟
18     for(i=0; i<32; i++) {                            /* basic cycle start */azhLinux联盟
19         z -= ((y<<4+ c) ^ (y + sum) ^ ((y>>5+ d);azhLinux联盟
20         y -= ((z<<4+ a) ^ (z + sum) ^ ((z>>5+
 b);azhLinux联盟
21         sum -= delta;                                /* end cycle */
azhLinux联盟
22     }azhLinux联盟
23     v[0]=
y;azhLinux联盟
24     v[1]=
z;azhLinux联盟
25 }
azhLinux联盟
C语言写的用起来当然不方便,没关系,用C++封装以下就OK了:azhLinux联盟
util.hazhLinux联盟
 1 #ifndef UTIL_HazhLinux联盟
 2 
#define UTIL_HazhLinux联盟
 3 
azhLinux联盟
 4 #include <string>azhLinux联盟
 5 #include <cmath>azhLinux联盟
 6 #include <cstdlib>azhLinux联盟
 7 azhLinux联盟
 8 typedef unsigned char byte;azhLinux联盟
 9 typedef unsigned long
 ulong;azhLinux联盟
10 
azhLinux联盟
11 inline double logbase(double base, double x) {azhLinux联盟
12     return log(x)/
log(base);azhLinux联盟
13 
}azhLinux联盟
14 
azhLinux联盟
15 /*azhLinux联盟
16 *convert int to hex char.azhLinux联盟
17 
*example:10 -> 'A',15 -> 'F'azhLinux联盟
18 */
azhLinux联盟
19 char intToHexChar(int x);azhLinux联盟
20 
azhLinux联盟
21 /*azhLinux联盟
22 *convert hex char to int.azhLinux联盟
23 
*example:'A' -> 10,'F' -> 15azhLinux联盟
24 */
azhLinux联盟
25 int hexCharToInt(char hex);azhLinux联盟
26 
azhLinux联盟
27 using std::string;azhLinux联盟
28 /*
azhLinux联盟
29 *convert a byte array to hex string.azhLinux联盟
30 
*hex string format example:"AF B0 80 7D"azhLinux联盟
31 */
azhLinux联盟
32 string bytesToHexString(const byte *in, size_t size);azhLinux联盟
33 
azhLinux联盟
34 /*azhLinux联盟
35 *convert a hex string to a byte array.azhLinux联盟
36 
*hex string format example:"AF B0 80 7D"azhLinux联盟
37 */
azhLinux联盟
38 size_t hexStringToBytes(const string &str, byte *out);azhLinux联盟
39 
azhLinux联盟
40 #endif/*UTIL_H*/
azhLinux联盟
util.cppazhLinux联盟
 1 #include "util.h"azhLinux联盟
 2 #include <vector>azhLinux联盟
 3 azhLinux联盟
 4 using namespace std;azhLinux联盟
 5 
azhLinux联盟
 6 char intToHexChar(int x) {azhLinux联盟
 7     static const char HEX[16=
 {azhLinux联盟
 8         '0''1''2''3'
,azhLinux联盟
 9         '4''5''6''7'
,azhLinux联盟
10         '8''9''A''B'
,azhLinux联盟
11         'C''D''E''F'
azhLinux联盟
12     };azhLinux联盟
13     return
 HEX[x];azhLinux联盟
14 
}azhLinux联盟
15 
azhLinux联盟
16 int hexCharToInt(char hex) {azhLinux联盟
17     hex =
 toupper(hex);azhLinux联盟
18     if
 (isdigit(hex))azhLinux联盟
19         return (hex - '0'
);azhLinux联盟
20     if
 (isalpha(hex))azhLinux联盟
21         return (hex - 'A' + 10
);azhLinux联盟
22     return 0
;azhLinux联盟
23 
}azhLinux联盟
24 
azhLinux联盟
25 string bytesToHexString(const byte *in, size_t size) {azhLinux联盟
26 
    string str;azhLinux联盟
27     for (size_t i = 0; i < size; ++
i) {azhLinux联盟
28         int t =
 in[i];azhLinux联盟
29         int a = t / 16
;azhLinux联盟
30         int b = t % 16
;azhLinux联盟
31         str.append(1
, intToHexChar(a));azhLinux联盟
32         str.append(1
, intToHexChar(b));azhLinux联盟
33         if (i != size - 1
)azhLinux联盟
34             str.append(1' '
);azhLinux联盟
35 
    }azhLinux联盟
36     return
 str;azhLinux联盟
37 
}azhLinux联盟
38 
azhLinux联盟
39 size_t hexStringToBytes(const string &str, byte *out) {azhLinux联盟
40 
azhLinux联盟
41     vector<string> vec;azhLinux联盟
42     string::size_type currPos = 0, prevPos = 0
;azhLinux联盟
43     while ((currPos = str.find(' ', prevPos)) !=
 string::npos) {azhLinux联盟
44         string b(str.substr(prevPos, currPos -
 prevPos));azhLinux联盟
45 
        vec.push_back(b);azhLinux联盟
46         prevPos = currPos + 1
;azhLinux联盟
47 
    }azhLinux联盟
48     if (prevPos <
 str.size()) {azhLinux联盟
49 
        string b(str.substr(prevPos));azhLinux联盟
50 
        vec.push_back(b);azhLinux联盟
51 
    }azhLinux联盟
52     typedef vector<string>
::size_type sz_type;azhLinux联盟
53     sz_type size =
 vec.size();azhLinux联盟
54     for (sz_type i = 0; i < size; ++
i) {azhLinux联盟
55         int a = hexCharToInt(vec[i][0
]);azhLinux联盟
56         int b = hexCharToInt(vec[i][1
]);azhLinux联盟
57         out[i] = a * 16 +
 b;azhLinux联盟
58 
    }azhLinux联盟
59     return
 size;azhLinux联盟
60 }
azhLinux联盟
tea.hazhLinux联盟
 1 #ifndef TEA_HazhLinux联盟
 2 
#define TEA_HazhLinux联盟
 3 
azhLinux联盟
 4 /*azhLinux联盟
 5 *for htonl,htonlazhLinux联盟
 6 
*do remember link "ws2_32.lib"azhLinux联盟
 7 */
azhLinux联盟
 8 #include <winsock2.h>azhLinux联盟
 9 #include "util.h"azhLinux联盟
10 azhLinux联盟
11 class TEA {azhLinux联盟
12 public
:azhLinux联盟
13     TEA(const byte *key, int round = 32, bool isNetByte = false
);azhLinux联盟
14     TEA(const TEA &
rhs);azhLinux联盟
15     TEA& operator=(const TEA &
rhs);azhLinux联盟
16     void encrypt(const byte *in, byte *
out);azhLinux联盟
17     void decrypt(const byte *in, byte *
out);azhLinux联盟
18 private
:azhLinux联盟
19     void encrypt(const ulong *in, ulong *
out);azhLinux联盟
20     void decrypt(const ulong *in, ulong *
out);azhLinux联盟
21     ulong ntoh(ulong netlong) { return _isNetByte ?
 ntohl(netlong) : netlong; }azhLinux联盟
22     ulong hton(ulong hostlong) { return _isNetByte ?
 htonl(hostlong) : hostlong; }azhLinux联盟
23 private
:azhLinux联盟
24     int _round; //iteration round to encrypt or decrypt
azhLinux联盟
25     bool _isNetByte; //whether input bytes come from networkazhLinux联盟
26     byte _key[16]; //encrypt or decrypt keyazhLinux联盟
27 };azhLinux联盟
28 
azhLinux联盟
29 #endif/*TEA_H*/
azhLinux联盟
tea.cppazhLinux联盟
 1 #include "tea.h"azhLinux联盟
 2 #include <cstring> //for memcpy,memsetazhLinux联盟
 3 azhLinux联盟
 4 using namespace std;azhLinux联盟
 5 
azhLinux联盟
 6 TEA::TEA(const byte *key, int round /*= 32*/, bool isNetByte /*= false*/)azhLinux联盟
 7 
:_round(round)azhLinux联盟
 8 
,_isNetByte(isNetByte) {azhLinux联盟
 9     if (key != 0
)azhLinux联盟
10         memcpy(_key, key, 16
);azhLinux联盟
11     else
azhLinux联盟
12         memset(_key, 016);azhLinux联盟
13 
}azhLinux联盟
14 
azhLinux联盟
15 TEA::TEA(const TEA &rhs)azhLinux联盟
16 
:_round(rhs._round)azhLinux联盟
17 
,_isNetByte(rhs._isNetByte) {azhLinux联盟
18     memcpy(_key, rhs._key, 16
);azhLinux联盟
19 
}azhLinux联盟
20 
azhLinux联盟
21 TEA& TEA::operator=(const TEA &rhs) {azhLinux联盟
22     if (&rhs != this
) {azhLinux联盟
23         _round =
 rhs._round;azhLinux联盟
24         _isNetByte =
 rhs._isNetByte;azhLinux联盟
25         memcpy(_key, rhs._key, 16
);azhLinux联盟
26 
    }azhLinux联盟
27     return *this
;azhLinux联盟
28 
}azhLinux联盟
29 
azhLinux联盟
30 void TEA::encrypt(const byte *in, byte *out) {azhLinux联盟
31     encrypt((const ulong*)in, (ulong*
)out);azhLinux联盟
32 
}azhLinux联盟
33 
azhLinux联盟
34 void TEA::decrypt(const byte *in, byte *out) {azhLinux联盟
35     decrypt((const ulong*)in, (ulong*
)out);azhLinux联盟
36 
}azhLinux联盟
37 
azhLinux联盟
38 void TEA::encrypt(const ulong *in, ulong *out) {azhLinux联盟
39 
azhLinux联盟
40     ulong *= (ulong*)_key;azhLinux联盟
41     register ulong y = ntoh(in[0
]);azhLinux联盟
42     register ulong z = ntoh(in[1
]);azhLinux联盟
43     register ulong a = ntoh(k[0
]);azhLinux联盟
44     register ulong b = ntoh(k[1
]);azhLinux联盟
45     register ulong c = ntoh(k[2
]);azhLinux联盟
46     register ulong d = ntoh(k[3
]);azhLinux联盟
47     register ulong delta = 0x9E3779B9/* (sqrt(5)-1)/2*2^32 */
azhLinux联盟
48     register int round = _round;azhLinux联盟
49     register ulong sum = 0
;azhLinux联盟
50 
azhLinux联盟
51     while (round--) {    /* basic cycle start */azhLinux联盟
52         sum += delta;azhLinux联盟
53         y += ((z << 4+ a) ^ (z + sum) ^ ((z >> 5+
 b);azhLinux联盟
54         z += ((y << 4+ c) ^ (y + sum) ^ ((y >> 5+
 d);azhLinux联盟
55     }    /* end cycle */
azhLinux联盟
56     out[0= ntoh(y);azhLinux联盟
57     out[1=
 ntoh(z);azhLinux联盟
58 
}azhLinux联盟
59 
azhLinux联盟
60 void TEA::decrypt(const ulong *in, ulong *out) {azhLinux联盟
61 
azhLinux联盟
62     ulong *= (ulong*)_key;azhLinux联盟
63     register ulong y = ntoh(in[0
]);azhLinux联盟
64     register ulong z = ntoh(in[1
]);azhLinux联盟
65     register ulong a = ntoh(k[0
]);azhLinux联盟
66     register ulong b = ntoh(k[1
]);azhLinux联盟
67     register ulong c = ntoh(k[2
]);azhLinux联盟
68     register ulong d = ntoh(k[3
]);azhLinux联盟
69     register ulong delta = 0x9E3779B9/* (sqrt(5)-1)/2*2^32 */
azhLinux联盟
70     register int round = _round;azhLinux联盟
71     register ulong sum = 0
;azhLinux联盟
72 
azhLinux联盟
73     if (round == 32)azhLinux联盟
74         sum = 0xC6EF3720/* delta << 5*/
azhLinux联盟
75     else if (round == 16)azhLinux联盟
76         sum = 0xE3779B90/* delta << 4*/
azhLinux联盟
77     elseazhLinux联盟
78         sum = delta << static_cast<int>(logbase(2, round));azhLinux联盟
79 
azhLinux联盟
80     while (round--) {    /* basic cycle start */azhLinux联盟
81         z -= ((y << 4+ c) ^ (y + sum) ^ ((y >> 5+ d);azhLinux联盟
82         y -= ((z << 4+ a) ^ (z + sum) ^ ((z >> 5+
 b);azhLinux联盟
83         sum -=
 delta;azhLinux联盟
84     }    /* end cycle */
azhLinux联盟
85     out[0= ntoh(y);azhLinux联盟
86     out[1=
 ntoh(z);azhLinux联盟
87 }
azhLinux联盟
需要说明的是TEA的构造函数:azhLinux联盟
TEA(const byte *key, int round = 32, bool isNetByte = false);azhLinux联盟
1.key - 加密或解密用的128-bit(16byte)密钥。azhLinux联盟
2.round - 加密或解密的轮数,常用的有64,32,16。azhLinux联盟
3.isNetByte - 用来标记待处理的字节是不是来自网络,为true时在加密/解密前先要转换成本地字节,执行加密/解密,然后再转换回网络字节。偷偷告诉你,QQ就是这样做的!azhLinux联盟
azhLinux联盟
最后当然少不了测试代码:azhLinux联盟
test.cppazhLinux联盟
 1 #include "tea.h"azhLinux联盟
 2 #include "util.h"azhLinux联盟
 3 #include <iostream>azhLinux联盟
 4 azhLinux联盟
 5 using namespace std;azhLinux联盟
 6 
azhLinux联盟
 7