|
|
发表于 2010-1-19 19:59:57
|
显示全部楼层
tea.cpp
1 #include "tea.h" 6 _9 Q$ ]3 L4 a1 R9 V* ~) c$ i
2 #include <cstring> //for memcpy,memset
; Y) p' O7 L* C& I& m. E q+ ^ 3 + N) [7 j9 L+ N
4 using namespace std;
( L* f+ S9 Z n0 |7 ? 5 3 S% Z: T3 @7 F9 P
6 TEA::TEA(const byte *key, int round /*= 32*/, bool isNetByte /*= false*/) 7 Y- A) e N* d! h s4 _
7 :_round(round)
# Q' \% M) B/ e2 Z: K2 @' B! M 8 ,_isNetByte(isNetByte) {
2 V4 ?( t% E% o5 q3 M 9 if (key != 0)
8 S: K2 [0 Y( U& t- h5 u/ ^8 ^10 memcpy(_key, key, 16); - n$ s$ X5 `3 z" Y2 F X: b* u. p
11 else
/ t4 q2 \9 O% p12 memset(_key, 0, 16);
: b A/ [) r0 { |, b13 }
( i+ R! q3 A- s14 2 ^6 U$ D4 H7 E% U) e
15 TEA::TEA(const TEA &rhs)
$ |8 F9 U4 T/ |) q; i" D; H, M16 :_round(rhs._round) 2 e! N) V# P7 e+ _3 j- a
17 ,_isNetByte(rhs._isNetByte) {
3 h, k \5 s6 f18 memcpy(_key, rhs._key, 16);
: Y5 C0 z0 l5 G# y19 } 2 [* h, w) n9 U
20
1 I# S$ H% z8 J$ u21 TEA& TEA::operator=(const TEA &rhs) { V3 d& t% [% }5 G4 K; F( K$ [8 i
22 if (&rhs != this) {
# _' W0 \4 f0 {: ]. {23 _round = rhs._round; % c! T; N3 w, ^' P& @
24 _isNetByte = rhs._isNetByte; ) p$ J4 _+ i! y1 @1 t
25 memcpy(_key, rhs._key, 16); ) K+ c9 ? E1 W) f; }
26 } 4 R0 H8 A$ G3 h; } N
27 return *this;
! T' p+ H* |$ [# d, [28 }
( J9 f9 c3 R+ t29
7 c2 {& w. F* o O30 void TEA::encrypt(const byte *in, byte *out) {
1 c0 @! U/ [+ U o6 q31 encrypt((const ulong*)in, (ulong*)out);
6 c, f/ K# m( |; c32 } - Z* f7 M: ~0 n/ j( p( W$ j* Z
33
" J* `# ` c) R% I' P6 }3 H, ?# g( k0 e34 void TEA::decrypt(const byte *in, byte *out) {
7 n+ Z% m: F7 x35 decrypt((const ulong*)in, (ulong*)out);
2 v& G6 Q) T7 \9 B$ I6 B36 } 0 N" n6 G$ _; V
37
. P0 e8 N0 C; I! n38 void TEA::encrypt(const ulong *in, ulong *out) {
5 U- C0 X0 D* \/ G. B39
* I/ g( Q- M1 ]) g+ n/ g2 k" r7 ]40 ulong *k = (ulong*)_key; % {. [5 X& G6 _; z, w" n
41 register ulong y = ntoh(in[0]); # q/ E$ A$ l! r3 d. R
42 register ulong z = ntoh(in[1]); U- p/ |, p* `
43 register ulong a = ntoh(k[0]); ! K8 C Z2 K% |/ H: ^4 x5 I
44 register ulong b = ntoh(k[1]); & ?8 N8 e$ R2 w+ u2 C% e9 k
45 register ulong c = ntoh(k[2]); , V# D/ g8 q& V: i" E9 G0 n. _+ z& K
46 register ulong d = ntoh(k[3]);
: L8 U. R+ d3 L& A" p; ?47 register ulong delta = 0x9E3779B9; /* (sqrt(5)-1)/2*2^32 */
+ G7 Z. U7 R3 P! s& o48 register int round = _round;
+ \+ Z* E- ~2 s0 X/ e7 q' k1 g7 k49 register ulong sum = 0; - U+ |' F; \& {! W
50
5 L. V4 \! n& y/ T# Y, D51 while (round--) { /* basic cycle start */ 8 f0 }* I' z' {( n! U: z
52 sum += delta;
6 h% n" Q9 N% T% n5 i j* h/ j: \53 y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); 9 I' n# ?1 M d$ T. F+ S1 b
54 z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
2 {/ Q( U! ?5 B2 k; f: c55 } /* end cycle */ ) W) ~( @, a& L3 x
56 out[0] = ntoh(y); ) Z4 ]8 `$ C; a4 g# u; _
57 out[1] = ntoh(z); 4 Y) }/ j8 D6 j
58 }
, i* Y7 ?7 d( s% H3 G0 ]59
1 w% P; Q5 k# s$ v: i60 void TEA::decrypt(const ulong *in, ulong *out) { ; H! C# O( |+ y% O: b
61
# y# U1 i( o, ]. S4 d- e62 ulong *k = (ulong*)_key;
" b% {% `0 Z, c- g4 r! g63 register ulong y = ntoh(in[0]);
% n y- o( _/ j, j5 |8 f; T6 z64 register ulong z = ntoh(in[1]); ) u; B$ j2 D( D( P S3 `3 s
65 register ulong a = ntoh(k[0]);
. S8 C L. d% T: R9 ~66 register ulong b = ntoh(k[1]); 2 R9 K6 A, E$ y5 U6 P
67 register ulong c = ntoh(k[2]);
) h! u9 {) H7 @% h3 G: C# N68 register ulong d = ntoh(k[3]);
) p' C$ V! T1 r; @& ]! c69 register ulong delta = 0x9E3779B9; /* (sqrt(5)-1)/2*2^32 */
$ }9 `' K3 a9 l1 _9 J3 |70 register int round = _round;
! B5 T9 s( @- V% }$ h9 J- r& }71 register ulong sum = 0; 1 E& o; w& f+ l8 X# z% ^. B9 {# x
72
8 Y0 [, s, k M+ ?73 if (round == 32) & C; r* \' T# P, }- M8 g6 i9 P) W
74 sum = 0xC6EF3720; /* delta << 5*/
3 a2 P( S5 |# g0 ^7 ]& f- k5 t75 else if (round == 16) ( U7 d2 u) ?* A3 B+ Q" _, b/ s* M6 I6 a
76 sum = 0xE3779B90; /* delta << 4*/ # A0 d% F% Y' d3 L* V# k4 L2 N7 P
77 else
4 [! q7 c& n: a: x u: F78 sum = delta << static_cast<int>(logbase(2, round)); 1 p% p, H' m9 s0 ~9 P# J; b9 N
79 5 i! j- k& @. v- d
80 while (round--) { /* basic cycle start */
& W, y v5 H! b81 z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
7 z# V7 y% N) `& Q; D! v7 l82 y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
9 R( F4 d1 [% l( t# t83 sum -= delta;
2 a' y" u& }6 ]' \84 } /* end cycle */ 1 \' z% l7 m ]5 y
85 out[0] = ntoh(y); + n3 A: f5 ^4 b5 {
86 out[1] = ntoh(z);
6 Y% A6 D$ h6 c* m" g87 }, z9 j+ S, ` M0 m- o) m7 S& E
4 I u3 e# d( U需要说明的是TEA的构造函数: , {9 ?+ g2 Y1 w! A
TEA(const byte *key, int round = 32, bool isNetByte = false);
4 y: ^0 `4 ?& A& Z g, M4 [8 h! b! ]1.key - 加密或解密用的128-bit(16byte)密钥。 5 o2 r! d& U. O' p5 i
2.round - 加密或解密的轮数,常用的有64,32,16。 1 W+ Z D) b2 _& @7 ]- f
3.isNetByte - 用来标记待处理的字节是不是来自网络,为true时在加密/解密前先要转换成本地字节,执行加密/解密,然后再转换回网络字节。偷偷告诉你,QQ就是这样做的!
: u! U! n, V5 \! k! g8 D) V6 \( C, l& b! n; l' B4 t# w( o2 g
最后当然少不了测试代码: |
|