|
发表于 2010-1-19 19:59:57
|
显示全部楼层
tea.cpp
1 #include "tea.h"
! e' y+ q4 ]8 } X 2 #include <cstring> //for memcpy,memset
T+ w6 w- o4 U, U5 F$ D 3 ) G) F# @: I" ?$ j$ l4 Z
4 using namespace std;
8 O0 `" E% I4 z1 t2 h 5
; y6 n2 l' g' W( `: [. T 6 TEA::TEA(const byte *key, int round /*= 32*/, bool isNetByte /*= false*/)
. c0 L- c1 c" A' _: S+ N 7 :_round(round)
1 ]4 I# T) N% B0 M 8 ,_isNetByte(isNetByte) {
6 U) o4 {; o2 s 9 if (key != 0)
& C) c2 r1 |9 \% [2 i, ]10 memcpy(_key, key, 16); 8 t2 ]9 c* A' t) `
11 else
% P! N/ }- f" I5 e12 memset(_key, 0, 16); 2 U4 T7 J8 Z# V) `
13 } 1 r3 D2 F& W+ Q
14 4 @8 ~: H+ D5 I$ k8 `# ~+ i% \! f
15 TEA::TEA(const TEA &rhs)
; J! Y0 g8 n i16 :_round(rhs._round)
: X! K6 C" P. h) w, k$ H( R& }17 ,_isNetByte(rhs._isNetByte) { . k3 {; z! k5 Q5 R( L' B; Z
18 memcpy(_key, rhs._key, 16);
V. v) ~( U" o: w/ @19 } # U2 G: d h/ O
20
" Z( T5 ?- j. W' F1 \6 M21 TEA& TEA::operator=(const TEA &rhs) {
9 H+ r# W& C: g22 if (&rhs != this) {
: j' w$ ]! n- [, H23 _round = rhs._round;
9 A/ m; t3 W* q' e9 W24 _isNetByte = rhs._isNetByte; 8 {$ h! m7 [0 j- D C
25 memcpy(_key, rhs._key, 16); 9 L- a( }0 o9 T O# H3 H5 i
26 }
! d, m E& z) ]+ h7 ^% E2 u$ d27 return *this;
4 ]% ?+ Q+ W0 o# Y28 }
& b% ^% ?- r2 C8 h; p3 s29 9 a1 d" _% G) t) L
30 void TEA::encrypt(const byte *in, byte *out) { % t* Z3 f& s6 s
31 encrypt((const ulong*)in, (ulong*)out); 1 x+ E( ~5 `& u& i: C) [" X
32 } + e9 a1 I, H6 x& F* [1 H
33
& x+ m `, {" o6 e8 j34 void TEA::decrypt(const byte *in, byte *out) {
- X/ s/ A6 t) t) |" [0 @35 decrypt((const ulong*)in, (ulong*)out);
; |" c' f/ I+ T4 [8 X2 a6 ?4 ^36 }
4 F* k" k2 P1 N/ {2 h37 - ]1 s& r) f) ]
38 void TEA::encrypt(const ulong *in, ulong *out) {
5 q! Z- c' J$ @2 Z/ P8 s% U& h, |39 . h# k, n1 B" _) y6 ?
40 ulong *k = (ulong*)_key; ( N* u) f' `: N
41 register ulong y = ntoh(in[0]);
1 e4 ~: v7 `1 z8 H3 p42 register ulong z = ntoh(in[1]);
( B& b; Z4 A* P, q1 _3 C3 \; @43 register ulong a = ntoh(k[0]);
' U5 K n2 \' @5 E8 Z. q- }3 t44 register ulong b = ntoh(k[1]); 7 V: o5 p0 Q0 ~- p
45 register ulong c = ntoh(k[2]);
% S+ k$ O" l6 v, l! b/ b# _46 register ulong d = ntoh(k[3]); * T7 K: j+ x/ R1 l8 I
47 register ulong delta = 0x9E3779B9; /* (sqrt(5)-1)/2*2^32 */
1 @% g( l. ~) n48 register int round = _round; $ v1 m# z4 ?" U! |! Y5 u7 J: h
49 register ulong sum = 0; " r/ k, J; A* ^6 P% F2 i! m
50
+ _; d3 f0 u$ Y+ h8 n51 while (round--) { /* basic cycle start */
v& @& V5 P6 V: @: q52 sum += delta;
c5 ^% R8 e- N+ Y! F5 W6 \1 M53 y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
; Q/ t J* Q6 u% z' r- x54 z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
7 _. V# @+ p% W+ h" a0 ~' f. d55 } /* end cycle */ , r- {, B+ m9 R" X# P4 l3 Q* g2 O
56 out[0] = ntoh(y);
2 p# P/ R3 ^6 Q57 out[1] = ntoh(z);
# f e% j* a) i) g& Q4 `# a- m58 }
4 [& `$ `2 k& ^9 h59
4 n0 A7 j' E" P0 Y8 [60 void TEA::decrypt(const ulong *in, ulong *out) { $ w2 W" M+ U+ A/ q* g& w3 V6 V
61 8 ~: r3 ]- j; U' b, G5 J t' f
62 ulong *k = (ulong*)_key; ! ^3 l! A8 w9 ~ k# j" S( i. x" g
63 register ulong y = ntoh(in[0]);
5 y+ G% U2 E% R# l/ w64 register ulong z = ntoh(in[1]);
1 s2 [) M2 F1 B. e n: [" f65 register ulong a = ntoh(k[0]); ; r3 \% {4 V4 {, f! c% p' ~0 ~
66 register ulong b = ntoh(k[1]); / M) u3 e, T& b- n
67 register ulong c = ntoh(k[2]);
; L" {; D2 T: E2 M6 |, U68 register ulong d = ntoh(k[3]); 6 t1 Z2 |% @" V, Q
69 register ulong delta = 0x9E3779B9; /* (sqrt(5)-1)/2*2^32 */ 8 f2 `- _6 X* j& o" f+ b x6 ^
70 register int round = _round;
I4 D; b' b3 d( g9 k2 ]! d71 register ulong sum = 0; 4 T7 v+ u" w$ m3 G( N/ c# M1 n; X
72
$ k! {+ o, e W5 A73 if (round == 32)
: T/ B" s% n: t. A. ^6 f2 a" C6 }% Z74 sum = 0xC6EF3720; /* delta << 5*/ 7 t7 ]4 `1 o! H4 ^- P' f! y
75 else if (round == 16)
. W D1 D) f4 D5 E* C76 sum = 0xE3779B90; /* delta << 4*/
( d# }2 c" E/ @3 a5 B' t* Q3 i77 else 9 |% m( d6 O- U# W1 m
78 sum = delta << static_cast<int>(logbase(2, round));
& ?% T6 X' e5 }* `- Z2 A3 \! l79
; G: x( v; d }' a$ M4 z3 ]80 while (round--) { /* basic cycle start */
7 H- a& \, a) H81 z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
) c' t6 z% j8 q9 n% d82 y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); ; j! `' c: E; N, d9 f
83 sum -= delta; & @- T" [) Z- N; r# O$ u# p# `
84 } /* end cycle */ - Q' Z3 } m! e, Q* u P7 g6 }
85 out[0] = ntoh(y); , C" n# ]- [6 z5 ?
86 out[1] = ntoh(z);
3 [1 q" U8 u0 m& H1 x8 l8 i87 }1 c- q& }6 P/ v. B: u- @$ T
: l5 [( i+ Y8 t) Y$ ?$ a
需要说明的是TEA的构造函数: X5 S9 {, @4 R2 W$ `
TEA(const byte *key, int round = 32, bool isNetByte = false);
7 f* Y3 Q3 S- R- ` Z1.key - 加密或解密用的128-bit(16byte)密钥。 0 U" J) d2 E! l
2.round - 加密或解密的轮数,常用的有64,32,16。
. t1 R; @# g8 w6 w/ D+ m; `3.isNetByte - 用来标记待处理的字节是不是来自网络,为true时在加密/解密前先要转换成本地字节,执行加密/解密,然后再转换回网络字节。偷偷告诉你,QQ就是这样做的!
( q1 }" }7 P- {* I2 }* a! g/ z) P {0 J
: Y' ~$ ^2 E: L' P8 C' |5 \最后当然少不了测试代码: |
|