您的位置:首页 > 编程语言 > C语言/C++

TEA加密算法的C/C++实现

2016-06-20 00:00 411 查看
TEA(Tiny Encryption Algorithm) 是一种简单高效的加密算法,以加密解密速度快,实现简单著称。算法真的很简单,TEA算法每一次可以操作64-bit(8-byte),采用128-bit(16-byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。目前我只知道QQ一直用的是16轮TEA。没什么好说的,先给出C语言的源代码(默认是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语言写的用起来当然不方便,没关系,用C++封装以下就OK了:

util.h

1
#ifndef UTIL_H

2
#define UTIL_H

3

4
#include
<
string
>

5
#include
<
cmath
>

6
#include
<
cstdlib
>

7

8
typedef unsigned
char

byte
;

9
typedef unsigned
long
ulong;

10

11
inline
double
logbase(
double
base,
double
x) {

12

return
log(x)
/
log(base);

13
}

14

15

/*

16
*convert int to hex char.

17
*example:10 -> 'A',15 -> 'F'

18

*/

19

char
intToHexChar(
int
x);

20

21

/*

22
*convert hex char to int.

23
*example:'A' -> 10,'F' -> 15

24

*/

25

int
hexCharToInt(
char
hex);

26

27
using std::string;

28

/*

29
*convert a byte array to hex string.

30
*hex string format example:"AF B0 80 7D"

31

*/

32
string bytesToHexString(
const

byte

*
in, size_t size);

33

34

/*

35
*convert a hex string to a byte array.

36
*hex string format example:"AF B0 80 7D"

37

*/

38
size_t hexStringToBytes(
const
string
&
str,
byte

*
out);

39

40
#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
<<
static_cast
<
int
>
(logbase(
2
, 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的构造函数:

TEA(const byte *key, int round = 32, bool isNetByte = false);

1.
key - 加密或解密用的128-bit(16byte)密钥。

2.
round - 加密或解密的轮数,常用的有64,32,16。

3.
isNetByte - 用来标记待处理的字节是不是来自网络,为true时在加密/解密前先要转换成本地字节,执行加密/解密,然后再转换回网络字节。偷偷告诉你,QQ就是这样做的!

最后当然少不了测试代码:

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
}

运行结果:

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

源代码下载:
点击下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: