File Coverage

blib/lib/Crypt/PRNG.pm
Criterion Covered Total %
statement 46 47 97.8
branch 13 16 81.2
condition n/a
subroutine 14 15 93.3
pod 10 10 100.0
total 83 88 94.3


line stmt bran cond sub pod time code
1             package Crypt::PRNG;
2              
3 25     25   81277 use strict;
  25         35  
  25         659  
4 25     25   95 use warnings;
  25         32  
  25         3003  
5             our $VERSION = '0.088_004';
6              
7             require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
8             our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] );
9             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
10             our @EXPORT = qw();
11              
12 25     25   109 use Carp;
  25         27  
  25         1490  
13             $Carp::Internal{(__PACKAGE__)}++;
14 25     25   2546 use CryptX;
  25         36  
  25         12822  
15              
16             sub string {
17 12     12 1 1729 my ($self, $len) = @_;
18 12         59 return $self->string_from("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", $len);
19             }
20              
21             sub string_from {
22 27     27 1 4067 my ($self, $chars, $len) = @_;
23              
24 27 50       70 $len = 20 unless defined $len;
25 27 50       58 return unless $len > 0;
26 27 50       93 return unless length($chars) > 0;
27              
28 27         15746 my @ch = split(//, $chars);
29 27         64 my $max_index = $#ch;
30 27 100       2388 return if $max_index > 65535;
31              
32 26         33 my $mask;
33 26         81 for my $n (1..31) {
34 126         149 $mask = (1<<$n) - 1;
35 126 100       213 last if $mask >= $max_index;
36             }
37              
38 26 100       67 my $upck = ($max_index > 255) ? "n*" : "C*";
39 26         46 my $l = $len * 2;
40              
41 26         35 my $rv = '';
42 26         40 my @r;
43 26         58 my $ri = 0;
44 26         72 while (length $rv < $len) {
45 2296 100       2729 if ($ri >= @r) {
46 26         515 @r = unpack($upck, $self->bytes($l));
47 26         86 $ri = 0;
48             }
49 2296         2334 my $i = $r[$ri++] & $mask;
50 2296 100       2797 next if $i > $max_index;
51 2112         2793 $rv .= $ch[$i];
52             }
53 26         2576 return $rv;
54             }
55              
56 0     0   0 sub CLONE_SKIP { 1 } # prevent cloning
57              
58             ### FUNCTIONS
59              
60             {
61             ### stolen from Bytes::Random::Secure
62             #
63             # Instantiate our random number generator(s) inside of a lexical closure,
64             # limiting the scope of the RNG object so it can't be tampered with.
65             my $RNG_object = undef;
66             my $fetch_RNG = sub { # Lazily, instantiate the RNG object, but only once.
67             $RNG_object = Crypt::PRNG->new unless defined $RNG_object && ref($RNG_object) ne 'SCALAR';
68             return $RNG_object;
69             };
70 2000     2000 1 139862 sub rand(;$) { return $fetch_RNG->()->double(@_) }
71 1000     1000 1 1438 sub irand() { return $fetch_RNG->()->int32() }
72 17     17 1 13722 sub random_bytes($) { return $fetch_RNG->()->bytes(@_) }
73 4     4 1 832 sub random_bytes_hex($) { return $fetch_RNG->()->bytes_hex(@_) }
74 4     4 1 906 sub random_bytes_b64($) { return $fetch_RNG->()->bytes_b64(@_) }
75 4     4 1 932 sub random_bytes_b64u($) { return $fetch_RNG->()->bytes_b64u(@_) }
76 1     1 1 3 sub random_string_from($;$) { return $fetch_RNG->()->string_from(@_) }
77 1     1 1 3 sub random_string(;$) { return $fetch_RNG->()->string(@_) }
78             }
79              
80             1;
81              
82             =pod
83              
84             =head1 NAME
85              
86             Crypt::PRNG - Cryptographically secure random number generator
87              
88             =head1 SYNOPSIS
89              
90             ### Functional interface:
91             use Crypt::PRNG qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u
92             random_string random_string_from rand irand);
93              
94             my $octets = random_bytes(45);
95             my $hex_string = random_bytes_hex(45);
96             my $base64_string = random_bytes_b64(45);
97             my $base64url_string = random_bytes_b64u(45);
98             my $alphanumeric_string = random_string(30);
99             my $string = random_string_from('ACGT', 64);
100             my $floating_point_number_0_to_1 = rand;
101             my $floating_point_number_0_to_88 = rand(88);
102             my $unsigned_32bit_int = irand;
103              
104             ### OO interface:
105             use Crypt::PRNG;
106              
107             my $prng = Crypt::PRNG->new; # defaults to ChaCha20
108             my $rc4_prng = Crypt::PRNG->new("RC4");
109             my $seeded_prng = Crypt::PRNG->new("RC4", "some data used for seeding PRNG");
110              
111             my $octets = $prng->bytes(45);
112             my $hex_string = $prng->bytes_hex(45);
113             my $base64_string = $prng->bytes_b64(45);
114             my $base64url_string = $prng->bytes_b64u(45);
115             my $alphanumeric_string = $prng->string(30);
116             my $string = $prng->string_from('ACGT', 64);
117             my $floating_point_number_0_to_1 = $prng->double;
118             my $floating_point_number_0_to_88 = $prng->double(88);
119             my $unsigned_32bit_int = $prng->int32;
120              
121             =head1 DESCRIPTION
122              
123             Provides an interface to several pseudo random number generators (thread-safe
124             and fork-safe). The default algorithm is ChaCha20.
125              
126             =head1 FUNCTIONS
127              
128             For all C functions and the corresponding C methods,
129             C<$length> must not be greater than C<1000000000>.
130              
131             =head2 random_bytes
132              
133             my $octets = random_bytes($length);
134             # $length .. [integer] number of random bytes to generate
135              
136             Returns C<$length> random octets as a binary string.
137              
138             =head2 random_bytes_hex
139              
140             my $hex_string = random_bytes_hex($length);
141             # $length .. [integer] number of random bytes (output string will be 2x longer)
142              
143             Returns C<$length> random octets encoded as a lowercase hexadecimal string.
144              
145             =head2 random_bytes_b64
146              
147             my $base64_string = random_bytes_b64($length);
148             # $length .. [integer] number of random bytes to encode
149              
150             Returns C<$length> random octets encoded as a Base64 string.
151              
152             =head2 random_bytes_b64u
153              
154             my $base64url_string = random_bytes_b64u($length);
155             # $length .. [integer] number of random bytes to encode
156              
157             Returns C<$length> random octets encoded as a Base64 URL Safe string (RFC 4648 section 5).
158              
159             =head2 random_string_from
160              
161             my $string = random_string_from($range, $length);
162             # $range .. [string] alphabet of allowed characters
163             # $length .. [integer] optional, number of characters (DEFAULT: 20)
164             #e.g.
165             my $dna_string = random_string_from("ABCD", 10);
166              
167             Returns a random string made of C<$length> chars randomly chosen from C<$range> string.
168             The alphabet must contain between 1 and 65536 characters; longer alphabets
169             return C.
170              
171             =head2 random_string
172              
173             my $alphanumeric_string = random_string($length);
174             # $length .. [integer] optional, number of characters (DEFAULT: 20)
175             #or
176             my $default_alphanumeric_string = random_string; # default length = 20
177              
178             Similar to random_string_from, only C<$range> is fixed to C<'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'>.
179              
180             =head2 rand
181              
182             my $n = rand;
183             #or
184             my $limited_n = rand($limit);
185             # $limit .. [number] optional, upper bound (exclusive)
186              
187             Returns a random floating point number from range C<[0,1)> (if called without parameter) or C<[0,$limit)>.
188             If C<$limit> is C<0>, behaves like no limit (returns C<[0,1)>), matching Perl's built-in C.
189              
190             =head2 irand
191              
192             my $i = irand;
193              
194             Returns a random unsigned 32bit integer - range C<0 .. 0xFFFFFFFF>.
195              
196             =head1 METHODS
197              
198             Unless noted otherwise, assume C<$prng> is an existing PRNG object created via
199             C, for example:
200              
201             my $prng = Crypt::PRNG->new;
202              
203             =head2 new
204              
205             my $prng = Crypt::PRNG->new; # defaults to ChaCha20
206             #or
207             my $prng = Crypt::PRNG->new($alg);
208             #or
209             my $prng = Crypt::PRNG->new($alg, $seed);
210              
211             # $alg ... [string] algorithm name: 'ChaCha20' (DEFAULT), 'Fortuna', 'RC4' (legacy; compatibility only), 'Sober128' or 'Yarrow'
212             # $seed ... [binary string] optional, initial entropy for seeding the PRNG
213              
214             If C<$seed> is not specified the PRNG is automatically seeded with 40 bytes
215             obtained via libtomcrypt's C platform RNG logic.
216              
217             If C<$seed> is specified it must be non-empty for all algorithms. RC4 is
218             provided for legacy compatibility only, is not recommended for new designs, and
219             requires a seed of at least 5 bytes.
220              
221             =head2 add_entropy
222              
223             my $prng = Crypt::PRNG->new;
224             $prng->add_entropy($random_data);
225             #or
226             $prng->add_entropy();
227              
228             If called without parameter it uses 40 bytes obtained via libtomcrypt's
229             C platform RNG logic.
230              
231             B you probably do not need this function at all as the module does automatic seeding on initialization as well as reseeding after fork and thread creation.
232              
233             =head2 bytes
234              
235             my $octets = $prng->bytes($length);
236              
237             See L
238              
239             =head2 bytes_hex
240              
241             my $hex_string = $prng->bytes_hex($length);
242              
243             See L
244              
245             =head2 bytes_b64
246              
247             my $base64_string = $prng->bytes_b64($length);
248              
249             See L
250              
251             =head2 bytes_b64u
252              
253             my $base64url_string = $prng->bytes_b64u($length);
254              
255             See L
256              
257             =head2 string
258              
259             my $alphanumeric_string = $prng->string($length);
260             #or
261             my $default_alphanumeric_string = $prng->string; # default length = 20
262              
263             See L
264              
265             =head2 string_from
266              
267             my $string = $prng->string_from($range, $length); # default length = 20
268              
269             See L
270              
271             =head2 double
272              
273             my $n = $prng->double;
274             #or
275             my $limited_n = $prng->double($limit);
276              
277             See L
278              
279             =head2 int32
280              
281             my $i = $prng->int32;
282              
283             See L
284              
285             =head1 SEE ALSO
286              
287             L, L, L,
288             L, L
289              
290             For generating random UUIDs see L and L.
291              
292             =cut