|
|
发表于 2010-1-19 19:59:57
|
显示全部楼层
tea.cpp
1 #include "tea.h" : `0 P/ c+ Z! M& K7 U" c2 A8 H
2 #include <cstring> //for memcpy,memset
' a: \) a8 B" q1 s5 {* ? 3 2 I- i6 x9 r( m7 S7 K. S$ _
4 using namespace std;
/ t' B( M. B: {8 o 5 * x9 `7 ]9 D* P: |
6 TEA::TEA(const byte *key, int round /*= 32*/, bool isNetByte /*= false*/)
0 n) ]1 K% Q- Z/ z9 b! L 7 :_round(round)
5 q" R8 E# a( {# i8 t6 ] 8 ,_isNetByte(isNetByte) {
+ W# ^ c4 E! S; p 9 if (key != 0)
. C7 a- L3 }2 x0 l" U# ~+ P; G$ M10 memcpy(_key, key, 16); 6 j7 k) ~. o( b. Q" ^8 A- B
11 else
8 y; {7 t0 V. L12 memset(_key, 0, 16);
2 j' ~) ~7 U Y" Q& x13 } 2 R3 ?; s: S* o
14
" v* l. Q6 h; ~$ N15 TEA::TEA(const TEA &rhs)
% u+ ^4 |1 v# n+ f16 :_round(rhs._round)
: [, m/ {) D# B1 E17 ,_isNetByte(rhs._isNetByte) { 1 B; e8 J! Q2 y5 {9 Y% i
18 memcpy(_key, rhs._key, 16);
; b1 f1 k; ]. c+ t19 } 1 O+ X& ?' c" g+ L @. @$ `' b
20
% s2 F! l# u8 Q" r$ s$ \! J% v( p21 TEA& TEA::operator=(const TEA &rhs) {
- y8 S7 a1 L. x+ d22 if (&rhs != this) {
7 @( [9 G% W4 o23 _round = rhs._round; , U: X: K N# b; }
24 _isNetByte = rhs._isNetByte;
* z @- _# h" _, s) `9 X( o; ?: ^25 memcpy(_key, rhs._key, 16);
# T5 @8 K9 W6 u- W' K* p26 } ; V) V5 L: r' x# ~$ G8 ]# N
27 return *this; 4 T3 @" p! Z- ~
28 }
2 Q. L& D& C2 E; Z: z29
9 Z6 u* a2 d! W) P9 W# _& k5 b& _30 void TEA::encrypt(const byte *in, byte *out) {
% s$ q7 z' b G: K9 k) F3 F/ H8 s31 encrypt((const ulong*)in, (ulong*)out); ( q/ a' A9 z) R' I7 T4 V
32 } o% d( r) y0 w u8 b/ n
33
0 S8 k3 Q4 Z, A: B3 R, d34 void TEA::decrypt(const byte *in, byte *out) { 6 N1 s: x( W( u/ T
35 decrypt((const ulong*)in, (ulong*)out); ( u" u, S1 s3 m5 v* Q' s2 ~
36 }
7 H; J! K4 Y x1 C. L37 ! `) O7 X4 s/ M( Y( e( U& z, B
38 void TEA::encrypt(const ulong *in, ulong *out) {
( L# {1 w; w' n6 `* S. p+ f" S9 t39 " w; ~* p# K! ^
40 ulong *k = (ulong*)_key; ( p/ w. f, p7 @$ T3 w' _1 l
41 register ulong y = ntoh(in[0]); n; v. `* E @
42 register ulong z = ntoh(in[1]); # g9 d7 i2 T# L/ J
43 register ulong a = ntoh(k[0]); 5 K% b" Q; x$ L( R9 c( F
44 register ulong b = ntoh(k[1]); 3 k& I. g, a* ^( m! e# y
45 register ulong c = ntoh(k[2]);
' M. x+ X! d1 b" U/ S% _ {46 register ulong d = ntoh(k[3]);
3 P( }- \( m {: K5 u# u2 i4 s8 C47 register ulong delta = 0x9E3779B9; /* (sqrt(5)-1)/2*2^32 */
# o1 N; H: B. }: ~+ c48 register int round = _round;
2 H. v! i$ _& H49 register ulong sum = 0;
; a2 F5 X* i( J7 f; n/ Q4 T: ^ u- z- q& K50 7 m/ o; r" }+ Y) M2 C: D' I
51 while (round--) { /* basic cycle start */
. e; j# ?2 b0 V52 sum += delta; ( C7 }9 n. w& C" i7 e e1 S( y. j
53 y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); , `; ^ x! F0 \, z
54 z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
' R9 s1 W' D& |; F6 R55 } /* end cycle */
8 W9 H; \/ f6 ]0 z. X9 M3 T56 out[0] = ntoh(y); 5 q$ C# `5 q6 q! F& e2 j8 i- |
57 out[1] = ntoh(z); : V/ b( Z, ~7 t! r! _
58 } 8 w9 E# D& ^+ Q2 a5 H( Q9 W
59 0 \ M g J$ x3 p7 E0 P* N
60 void TEA::decrypt(const ulong *in, ulong *out) {
9 I' Y: K Q9 @- l4 D& u61 6 @5 v& G- Q+ |9 G
62 ulong *k = (ulong*)_key; & {( c4 F' ~0 G" b7 i: m
63 register ulong y = ntoh(in[0]);
# N' o0 d; E" J" m64 register ulong z = ntoh(in[1]); , I8 H! l% d4 i8 d
65 register ulong a = ntoh(k[0]);
' i; m' l+ D5 R66 register ulong b = ntoh(k[1]);
& H5 C9 }( t- Z$ q# `4 H- J67 register ulong c = ntoh(k[2]);
6 q- {9 o5 W8 Z8 g68 register ulong d = ntoh(k[3]); / g7 C% L0 L3 k
69 register ulong delta = 0x9E3779B9; /* (sqrt(5)-1)/2*2^32 */ 0 F9 G0 t# {! V3 k) z% ^
70 register int round = _round;
; G; p; C* y' V) k0 a2 J7 ~/ y& V6 Y71 register ulong sum = 0;
8 R$ e- D- \2 S5 K2 u4 }72
2 `1 o8 {& o o0 M1 L' ?3 m73 if (round == 32) 1 @5 N# @( T# I, x' l! O
74 sum = 0xC6EF3720; /* delta << 5*/
' D% q/ _0 c4 \& P75 else if (round == 16) 7 \+ e) m# V; `5 c: B6 s+ `; Q% D
76 sum = 0xE3779B90; /* delta << 4*/
/ q2 C5 i: b7 m. G# L77 else $ U) U6 ]. R5 r! H( V8 f+ m
78 sum = delta << static_cast<int>(logbase(2, round)); - q3 g9 @, U" y
79
% D, }: c- Q: P8 o5 U) t7 [80 while (round--) { /* basic cycle start */
4 i1 x9 G' ?; r' ?) p$ z81 z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
+ O2 Z; y7 n% K. [4 G82 y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); # Z; d0 |7 A) O; ?6 m. d7 ^" _
83 sum -= delta;
# Y5 K4 `* t7 j' b, ]% ^84 } /* end cycle */ ^$ ~: @( e$ I) t" q. ?& U
85 out[0] = ntoh(y);
5 y7 X" ?/ ]! o3 z' q0 Q# K' N86 out[1] = ntoh(z);
* D) g* }% q1 s% W' Z87 }$ F, v5 e5 g9 Y0 J( r
! n4 G, C% t! C8 S: K2 U) X
需要说明的是TEA的构造函数:
0 n1 ]9 W$ t% X' _TEA(const byte *key, int round = 32, bool isNetByte = false); ' A$ _0 n% R4 T
1.key - 加密或解密用的128-bit(16byte)密钥。 # T7 Y9 d q' {# C1 E3 s+ v
2.round - 加密或解密的轮数,常用的有64,32,16。 ! ?/ M, x$ c; W4 l. S
3.isNetByte - 用来标记待处理的字节是不是来自网络,为true时在加密/解密前先要转换成本地字节,执行加密/解密,然后再转换回网络字节。偷偷告诉你,QQ就是这样做的!
% E0 f+ h1 J" v! d/ d$ v( K, b( O+ t0 O4 s6 `( h1 g3 }" {
最后当然少不了测试代码: |
|