line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Webqq::Encryption::TEA::Perl; |
2
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
46
|
|
3
|
|
|
|
|
|
|
#源码参考cpan模块Crypt::OICQ,感谢作者Shufeng Tan |
4
|
|
|
|
|
|
|
my $TEA_ROUNDS = 0x10; |
5
|
|
|
|
|
|
|
my $TEA_DELTA = 0x9E3779B9; |
6
|
|
|
|
|
|
|
my $TEA_SUM = 0xE3779B90; |
7
|
|
|
|
|
|
|
sub tea_decrypt { |
8
|
1
|
|
|
1
|
|
485
|
use integer; |
|
1
|
|
|
|
|
11
|
|
|
1
|
|
|
|
|
4
|
|
9
|
0
|
|
|
0
|
0
|
|
my ($c_block, $key) = @_; |
10
|
0
|
|
|
|
|
|
my ($y, $z) = unpack("NN", $c_block); |
11
|
0
|
|
|
|
|
|
my ($a, $b, $c, $d) = unpack("NNNN", $key); |
12
|
0
|
|
|
|
|
|
my $sum = $TEA_SUM; |
13
|
0
|
|
|
|
|
|
my $n = $TEA_ROUNDS; |
14
|
0
|
|
|
|
|
|
while ($n-- > 0) { |
15
|
0
|
|
|
|
|
|
$z -= ($y<<4)+$c ^ $y+$sum ^ (0x07ffffff & ($y>>5))+$d; |
16
|
0
|
|
|
|
|
|
$y -= ($z<<4)+$a ^ $z+$sum ^ (0x07ffffff & ($z>>5))+$b; |
17
|
0
|
|
|
|
|
|
$sum -= $TEA_DELTA; |
18
|
|
|
|
|
|
|
} |
19
|
0
|
|
|
|
|
|
pack("NN", $y, $z); |
20
|
|
|
|
|
|
|
} |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub decrypt { |
23
|
0
|
|
|
0
|
0
|
|
my ($crypt, $key) = @_; |
24
|
0
|
|
|
|
|
|
my $crypt_len = length($crypt); |
25
|
0
|
0
|
0
|
|
|
|
if (($crypt_len % 8) || ($crypt_len < 16)) { |
26
|
0
|
|
|
|
|
|
warn "Webqq::Encryption::TEA::Perl::decrypt error: invalid input length $crypt_len\n"; |
27
|
0
|
|
|
|
|
|
return undef; |
28
|
|
|
|
|
|
|
} |
29
|
0
|
|
|
|
|
|
my $c_buf = substr($crypt, 0, 8); |
30
|
0
|
|
|
|
|
|
my $p_buf = tea_decrypt($c_buf, $key); |
31
|
0
|
|
|
|
|
|
my $pad_len = ord(substr($p_buf, 0, 1) & "\007"); |
32
|
0
|
|
|
|
|
|
my $plain_len = $crypt_len - $pad_len - 10; |
33
|
0
|
|
|
|
|
|
my $plain = $p_buf; |
34
|
0
|
|
|
|
|
|
my $pre_plain = $p_buf; |
35
|
0
|
|
|
|
|
|
my $pre_crypt = $c_buf; |
36
|
|
|
|
|
|
|
|
37
|
0
|
|
|
|
|
|
for (my $i = 8; $i < $crypt_len; $i += 8) { |
38
|
0
|
|
|
|
|
|
$c_buf = substr($crypt, $i, 8); |
39
|
0
|
|
|
|
|
|
$p_buf = tea_decrypt($c_buf ^ $pre_plain, $key); |
40
|
0
|
|
|
|
|
|
$pre_plain = $p_buf; |
41
|
0
|
|
|
|
|
|
$p_buf ^= $pre_crypt; |
42
|
0
|
|
|
|
|
|
$plain .= $p_buf; |
43
|
0
|
|
|
|
|
|
$pre_crypt = $c_buf; |
44
|
|
|
|
|
|
|
} |
45
|
0
|
0
|
|
|
|
|
if (substr($plain, -7, 7) ne "\0\0\0\0\0\0\0") { |
46
|
0
|
|
|
|
|
|
warn "Webqq::Encryption::TEA::Perl::decrypt error: bad decrypt data\n", |
47
|
|
|
|
|
|
|
"crypt: ", unpack("H*", $crypt), "\n", |
48
|
|
|
|
|
|
|
"key: ", unpack("H*", $key), "\n", |
49
|
|
|
|
|
|
|
"plain: ", unpack("H*", $plain), "\n"; |
50
|
0
|
|
|
|
|
|
return undef; |
51
|
|
|
|
|
|
|
} |
52
|
0
|
|
|
|
|
|
return substr($plain, -7-$plain_len, $plain_len); |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub tea_encrypt { |
56
|
1
|
|
|
1
|
|
318
|
use integer; |
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
3
|
|
57
|
0
|
|
|
0
|
0
|
|
my ($p_block, $key) = @_; |
58
|
0
|
|
|
|
|
|
my ($y, $z) = unpack("NN", $p_block); |
59
|
0
|
|
|
|
|
|
my ($a, $b, $c, $d) = unpack("NNNN", $key); |
60
|
0
|
|
|
|
|
|
my $sum = 0; |
61
|
0
|
|
|
|
|
|
my $n = $TEA_ROUNDS; |
62
|
0
|
|
|
|
|
|
while ($n-- > 0) { |
63
|
0
|
|
|
|
|
|
$sum += $TEA_DELTA; |
64
|
0
|
|
|
|
|
|
$y += ($z<<4)+$a ^ $z+$sum ^ (0x07ffffff & ($z>>5))+$b; |
65
|
0
|
|
|
|
|
|
$z += ($y<<4)+$c ^ $y+$sum ^ (0x07ffffff & ($y>>5))+$d; |
66
|
|
|
|
|
|
|
} |
67
|
0
|
|
|
|
|
|
pack("NN", $y, $z); |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
sub encrypt { |
70
|
0
|
|
|
0
|
0
|
|
my ($plain, $key) = @_; |
71
|
0
|
|
|
|
|
|
my $plain_len = length($plain); |
72
|
0
|
|
|
|
|
|
my $head_pad_len = ($plain_len + 10) % 8; |
73
|
0
|
0
|
|
|
|
|
$head_pad_len = 8 - $head_pad_len if $head_pad_len; |
74
|
0
|
|
|
|
|
|
my $padded_plain = chr(0xa8 + $head_pad_len) . |
75
|
|
|
|
|
|
|
rand_str(2+$head_pad_len) . |
76
|
|
|
|
|
|
|
#(chr(0xad) x (2 + $head_pad_len)) . |
77
|
|
|
|
|
|
|
$plain . ("\0" x 7); |
78
|
0
|
|
|
|
|
|
my $padded_plain_len = length($padded_plain); |
79
|
0
|
|
|
|
|
|
my $crypt = ""; |
80
|
0
|
|
|
|
|
|
my $pre_plain = "\0" x 8; |
81
|
0
|
|
|
|
|
|
my $pre_crypt = $pre_plain; |
82
|
0
|
|
|
|
|
|
for (my $i = 0; $i < $padded_plain_len; $i += 8) { |
83
|
0
|
|
|
|
|
|
my $p_buf = substr($padded_plain, $i, 8) ^ $pre_crypt; |
84
|
0
|
|
|
|
|
|
my $c_buf = tea_encrypt($p_buf, $key); |
85
|
0
|
|
|
|
|
|
$c_buf ^= $pre_plain; |
86
|
0
|
|
|
|
|
|
$crypt .= $c_buf; |
87
|
0
|
|
|
|
|
|
$pre_crypt = $c_buf; |
88
|
0
|
|
|
|
|
|
$pre_plain = $p_buf; |
89
|
|
|
|
|
|
|
} |
90
|
0
|
|
|
|
|
|
return $crypt; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
sub rand_str { |
93
|
0
|
|
|
0
|
0
|
|
my $len = pop; |
94
|
0
|
|
|
|
|
|
join('', map(pack("C", rand(0xff)), 1..$len)); |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
1; |