line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Crypt::Random::TESHA2; |
2
|
6
|
|
|
6
|
|
23443
|
use strict; |
|
6
|
|
|
|
|
13
|
|
|
6
|
|
|
|
|
210
|
|
3
|
6
|
|
|
6
|
|
29
|
use warnings; |
|
6
|
|
|
|
|
12
|
|
|
6
|
|
|
|
|
190
|
|
4
|
6
|
|
|
6
|
|
39
|
use Carp qw/croak confess carp/; |
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
515
|
|
5
|
6
|
|
|
6
|
|
6463
|
use Time::HiRes qw/gettimeofday usleep/; |
|
6
|
|
|
|
|
11751
|
|
|
6
|
|
|
|
|
31
|
|
6
|
6
|
|
|
6
|
|
9963
|
use Digest::SHA qw/sha256 sha512/; |
|
6
|
|
|
|
|
29492
|
|
|
6
|
|
|
|
|
560
|
|
7
|
6
|
|
|
6
|
|
4146
|
use Crypt::Random::TESHA2::Config; |
|
6
|
|
|
|
|
15
|
|
|
6
|
|
|
|
|
511
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
BEGIN { |
10
|
6
|
|
|
6
|
|
13
|
$Crypt::Random::TESHA2::AUTHORITY = 'cpan:DANAJ'; |
11
|
6
|
|
|
|
|
109
|
$Crypt::Random::TESHA2::VERSION = '0.01'; |
12
|
|
|
|
|
|
|
} |
13
|
|
|
|
|
|
|
|
14
|
6
|
|
|
6
|
|
34
|
use base qw( Exporter ); |
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
7001
|
|
15
|
|
|
|
|
|
|
our @EXPORT_OK = qw( random_bytes random_values irand rand is_strong ); |
16
|
|
|
|
|
|
|
our %EXPORT_TAGS = (all => [ @EXPORT_OK ]); |
17
|
|
|
|
|
|
|
our @EXPORT = qw( ); # nothing by default |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
my $_opt_need_strong = 0; |
20
|
|
|
|
|
|
|
my $_opt_weak_ok = 0; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
my $_entropy_per_raw_byte = Crypt::Random::TESHA2::Config::entropy(); |
23
|
|
|
|
|
|
|
# Protect against possible abuse / misconfiguration |
24
|
|
|
|
|
|
|
$_entropy_per_raw_byte = 1 if $_entropy_per_raw_byte < 1; |
25
|
|
|
|
|
|
|
$_entropy_per_raw_byte = 7 if $_entropy_per_raw_byte > 7; |
26
|
|
|
|
|
|
|
my $_hashalg = \&sha512; |
27
|
|
|
|
|
|
|
my $_pool_size = 512; |
28
|
|
|
|
|
|
|
my $_nehi = 0; # A 64-bit counter |
29
|
|
|
|
|
|
|
my $_nelo = 0; |
30
|
|
|
|
|
|
|
my $_pool; |
31
|
|
|
|
|
|
|
my $_C; # bits of entropy that we think are in the pool |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# Make sure SHA512 is supported, back off to 256 if not. |
34
|
|
|
|
|
|
|
if (!defined sha512("test")) { |
35
|
|
|
|
|
|
|
$_pool_size = 256; |
36
|
|
|
|
|
|
|
$_hashalg = \&sha256; |
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
sub import { |
40
|
5
|
|
|
5
|
|
32
|
my @options; |
41
|
|
|
|
|
|
|
|
42
|
5
|
|
|
|
|
14
|
@options = grep { $_ !~ /^[-:]?weak$/i } @_; |
|
11
|
|
|
|
|
46
|
|
43
|
5
|
50
|
|
|
|
20
|
$_opt_weak_ok = 1 if @options != @_; |
44
|
5
|
|
|
|
|
15
|
@_ = @options; |
45
|
|
|
|
|
|
|
|
46
|
5
|
|
|
|
|
12
|
@options = grep { $_ !~ /^[-:]?strong$/i } @_; |
|
11
|
|
|
|
|
33
|
|
47
|
5
|
50
|
|
|
|
19
|
$_opt_need_strong = 1 if @options != @_; |
48
|
5
|
|
|
|
|
15
|
@_ = @options; |
49
|
|
|
|
|
|
|
|
50
|
5
|
50
|
33
|
|
|
21
|
croak "TESHA2 is not a strong randomness source on this platform" |
51
|
|
|
|
|
|
|
if $_opt_need_strong && !is_strong(); |
52
|
|
|
|
|
|
|
|
53
|
5
|
|
|
|
|
322
|
goto &Exporter::import; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# Returns 1 if our installtion-time entropy measurements indicated we could |
57
|
|
|
|
|
|
|
# get enough entropy to make this method work on this platform. |
58
|
|
|
|
|
|
|
sub is_strong { |
59
|
3
|
50
|
|
3
|
1
|
7166
|
return ($_entropy_per_raw_byte > 1.0) ? 1 : 0; |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# Return $n random 32-bit values |
63
|
|
|
|
|
|
|
sub random_values { |
64
|
1
|
|
|
1
|
1
|
756
|
return map { unpack("L", random_bytes(4)) } 1 .. shift; |
|
10
|
|
|
|
|
33
|
|
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
# Note, only 32 bits. |
67
|
|
|
|
|
|
|
# TODO: Figure out a portable non-64-bit way to make 52-bit doubles. |
68
|
|
|
|
|
|
|
sub rand { |
69
|
2
|
|
100
|
2
|
1
|
1766
|
return ($_[0]||1) * (unpack("L", random_bytes(4))/4294967296.0); |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
sub irand { |
72
|
1
|
|
|
1
|
1
|
953
|
return unpack("L", random_bytes(4)); |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# This uses an entropy pool (see Encyclopedia of Cryptography and Security, |
76
|
|
|
|
|
|
|
# volume 2, "Entropy Sources"). We use SHA-512 to handle a 512-bit pool. |
77
|
|
|
|
|
|
|
# One this this will do is ensure the input from any one byte is nicely |
78
|
|
|
|
|
|
|
# spread out among the 64 bytes of the pool. |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
sub random_bytes { |
81
|
2523
|
|
|
2523
|
1
|
45210
|
my $n = shift; |
82
|
2523
|
50
|
|
|
|
11668
|
return '' unless defined $n; |
83
|
2523
|
100
|
|
|
|
8256
|
if (!defined $_pool) { |
84
|
|
|
|
|
|
|
# Initialize pool with 64 bits of entropy. |
85
|
2
|
|
|
|
|
3
|
$_C = 64; |
86
|
|
|
|
|
|
|
# Get some extra bytes at the start. |
87
|
2
|
|
|
|
|
9
|
my $nbytes = 4 + int($_C/$_entropy_per_raw_byte) + 1; |
88
|
2
|
|
|
|
|
8
|
my $S = join("", map { _get_random_byte() } 1 .. $nbytes); |
|
28
|
|
|
|
|
61
|
|
89
|
2
|
|
|
|
|
31
|
$_pool = $_hashalg->($S); |
90
|
|
|
|
|
|
|
|
91
|
2
|
50
|
33
|
|
|
33
|
carp "TESHA2 is not a strong randomness source on this platform" |
92
|
|
|
|
|
|
|
if !$_opt_weak_ok && !is_strong(); |
93
|
|
|
|
|
|
|
} |
94
|
2523
|
|
|
|
|
6417
|
my $X = ''; |
95
|
2523
|
|
|
|
|
9744
|
while (length($X) < $n) { |
96
|
2522
|
|
|
|
|
11398
|
my $K = 8 * $n; |
97
|
2522
|
50
|
|
|
|
8527
|
$K = $_pool_size if $K > $_pool_size; |
98
|
|
|
|
|
|
|
# Add more entropy to pool if needed. |
99
|
2522
|
|
|
|
|
7588
|
while ($_C < $K) { |
100
|
2512
|
|
|
|
|
7415
|
my $nbytes = int( ($K - $_C) / $_entropy_per_raw_byte ) + 1; |
101
|
|
|
|
|
|
|
#warn "want $K bits, pool has $_C bits. Adding $nbytes bytes\n"; |
102
|
2512
|
|
|
|
|
11505
|
my $S = join("", map { _get_random_byte() } 1 .. $nbytes); |
|
2960
|
|
|
|
|
12334
|
|
103
|
2512
|
|
|
|
|
28752
|
$_pool = $_hashalg->($_pool . $S); |
104
|
2512
|
|
|
|
|
7311
|
$_C += $_entropy_per_raw_byte * $nbytes; |
105
|
2512
|
50
|
|
|
|
20272
|
$_C = $_pool_size if $_C > $_pool_size; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
# Extract K bits from the pool. |
108
|
2522
|
|
|
|
|
5471
|
$_C -= $K; |
109
|
2522
|
|
|
|
|
31283
|
my $V = $_hashalg->( 'te' . pack("LL", $_nehi, $_nelo) . $_pool ); |
110
|
2522
|
50
|
|
|
|
10167
|
if ($_nelo < 4294967295) { $_nelo++; } else { $_nehi++; $_nelo = 0; } |
|
2522
|
|
|
|
|
6966
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
111
|
2522
|
|
|
|
|
17220
|
$X .= substr($V, 0, int($K/8)); |
112
|
|
|
|
|
|
|
} |
113
|
2523
|
|
|
|
|
36400
|
return $X; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# The heart of the system, where we gather entropy from timer jitter |
117
|
|
|
|
|
|
|
# (technically this is scheduler jitter). This is a similar idea to |
118
|
|
|
|
|
|
|
# timer_entropyd, TrueRand, or the old Math::TrulyRandom module. |
119
|
|
|
|
|
|
|
# |
120
|
|
|
|
|
|
|
# *) Cryptographically, there are numerous issues here. This is, at best, |
121
|
|
|
|
|
|
|
# one source to feed to a well designed entropy pool system. |
122
|
|
|
|
|
|
|
# |
123
|
|
|
|
|
|
|
# *) The output of this function passes ENT and TestU01 Rabbit on all systems |
124
|
|
|
|
|
|
|
# I've run it on. timer_entropyd does not, even when von Neumann debiased. |
125
|
|
|
|
|
|
|
# However, even a counter run through SHA256 will pass these tests, which |
126
|
|
|
|
|
|
|
# just indicates the stream data is uncorrelated. |
127
|
|
|
|
|
|
|
# |
128
|
|
|
|
|
|
|
# *) The entropy tests mentioned above are only one part. If a system |
129
|
|
|
|
|
|
|
# returned the same sequence every time, it may pass all the tests but |
130
|
|
|
|
|
|
|
# still be a horrible generator. That's especially not what one wants |
131
|
|
|
|
|
|
|
# from this module. |
132
|
|
|
|
|
|
|
# |
133
|
|
|
|
|
|
|
# *) I discovered Matt Blaze's truerand after I wrote this -- no ideas or |
134
|
|
|
|
|
|
|
# code were used. However, I got the idea from timer_entropyd, which |
135
|
|
|
|
|
|
|
# probably in turn got the idea from truerand. Version 2.1 (1996) of |
136
|
|
|
|
|
|
|
# Matt Blaze's truerand is _far_ more conservative than the old design |
137
|
|
|
|
|
|
|
# in Math::TrulyRandom. First he replaces the old-school byte mixing |
138
|
|
|
|
|
|
|
# with a SHA (very similar to my solution here). Next, he does another |
139
|
|
|
|
|
|
|
# mixing to generate the actual bytes, while the old code would use the |
140
|
|
|
|
|
|
|
# raw results. I use a different method above, but the end result is |
141
|
|
|
|
|
|
|
# somewhat similar -- we take these raw results and stir them further. |
142
|
|
|
|
|
|
|
# |
143
|
|
|
|
|
|
|
# *) My tests using the raw timer data are showing 1.5 - 4 bits per xor. |
144
|
|
|
|
|
|
|
# The truerand 2.1 documentation indicates 0.67 to 1.33 bits per call, |
145
|
|
|
|
|
|
|
# then conservatively halves the number. |
146
|
|
|
|
|
|
|
# |
147
|
|
|
|
|
|
|
# *) Expanding on the above, assume the worst and absolutely no entropy is |
148
|
|
|
|
|
|
|
# gathered. Then each byte will be a sha256 related to the current hires |
149
|
|
|
|
|
|
|
# time, where each byte is mixed in the pool. We get a fine PRNG, just |
150
|
|
|
|
|
|
|
# not seeded well (from a crypto point of view, this is awful). |
151
|
|
|
|
|
|
|
# |
152
|
|
|
|
|
|
|
# *) For each bit, the two microsecond values are xor'd and packed into |
153
|
|
|
|
|
|
|
# 32-bit words. Eight of these are concatenated and a SHA-256 hash is |
154
|
|
|
|
|
|
|
# performed. As long as the sum of entropy gathered from all eight xors |
155
|
|
|
|
|
|
|
# is at least 8, we're good. The sha256 takes care of shuffling bits so |
156
|
|
|
|
|
|
|
# there aren't biases. This generates a much better result than using |
157
|
|
|
|
|
|
|
# boolean differences like timer_entropyd (even if the differences are |
158
|
|
|
|
|
|
|
# sent through von Neumann debiasing). |
159
|
|
|
|
|
|
|
# |
160
|
|
|
|
|
|
|
sub _get_random_byte { |
161
|
2988
|
|
|
2988
|
|
12853
|
my ($start, $t1, $t2) = gettimeofday(); |
162
|
|
|
|
|
|
|
# This basically gives us a counter, so every call is unique. We can |
163
|
|
|
|
|
|
|
# assume it adds no entropy. |
164
|
2988
|
|
|
|
|
11608
|
my $str = pack("LL", $start, $t1); |
165
|
|
|
|
|
|
|
# A hash we will use for a little bit of CPU processing inside the loop. |
166
|
2988
|
|
|
|
|
6892
|
my %dummy; |
167
|
2988
|
|
|
|
|
10415
|
foreach my $bit (1 .. 8) { |
168
|
|
|
|
|
|
|
# Sleep some period of time. Differ the times so we don't hit a |
169
|
|
|
|
|
|
|
# particular beat of the scheduler. |
170
|
23904
|
|
|
|
|
4571861
|
usleep(2+3*$bit); |
171
|
23904
|
|
|
|
|
145797
|
(undef, $t2) = gettimeofday(); |
172
|
|
|
|
|
|
|
# xor the two. The entropy is in the variation between what we got |
173
|
|
|
|
|
|
|
# (t2 - t1) and what we expected (2+3*bit + c). |
174
|
23904
|
|
|
|
|
115462
|
$str .= pack("L", $t1 ^ $t2); |
175
|
|
|
|
|
|
|
# A little hash processing to further perturb the times. |
176
|
23904
|
|
|
|
|
504730
|
$dummy{$str . $_}++ for 1..8; |
177
|
23904
|
|
|
|
|
76664
|
$t1 = $t2; |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
# To truly return a byte: return substr( sha256($str), 0, 1 ); |
180
|
|
|
|
|
|
|
# Return the entire string -- let the pool figure it out. |
181
|
2988
|
|
|
|
|
104921
|
return sha256($str); |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
1; |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
__END__ |