File Coverage

blib/lib/Data/Entropy/RawSource/RandomnumbersInfo.pm
Criterion Covered Total %
statement 19 81 23.4
branch 0 30 0.0
condition n/a
subroutine 6 15 40.0
pod 9 9 100.0
total 34 135 25.1


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Data::Entropy::RawSource::RandomnumbersInfo - download entropy from
4             randomnumbers.info
5              
6             =head1 SYNOPSIS
7              
8             use Data::Entropy::RawSource::RandomnumbersInfo;
9              
10             my $rawsrc = Data::Entropy::RawSource::RandomnumbersInfo->new;
11              
12             $c = $rawsrc->getc;
13             # and the rest of the I/O handle interface
14              
15             =head1 DESCRIPTION
16              
17             This class provides an I/O handle connected to a stream of random octets
18             being generated by a quantum random number generator (from the company id
19             Quantique) connected to the randomnumbers.info server at the University
20             of Geneva. This is a strong source of random bits, but is not suitable
21             for security applications because the bits are passed over the Internet
22             unencrypted. The handle implements a substantial subset of the interface
23             described in L.
24              
25             For use as a general entropy source, it is recommended to wrap an object
26             of this class using C, which provides methods to
27             extract entropy in more convenient forms than mere octets.
28              
29             The bits generated at randomnumbers.info are, theoretically and as far as
30             anyone can tell, totally unbiased and uncorrelated. However, they are
31             sent over the Internet in the clear, and so are subject to interception
32             and alteration by an adversary. This is therefore generally unsuitable
33             for security applications. Applications requiring secret entropy
34             should generate it locally (see L).
35             Applications requiring a large amount of apparently-random data,
36             but not true entropy, might prefer to fake it cryptographically (see
37             L).
38              
39             =cut
40              
41             package Data::Entropy::RawSource::RandomnumbersInfo;
42              
43 1     1   26782 { use 5.006; }
  1         5  
  1         66  
44 1     1   8 use warnings;
  1         3  
  1         51  
45 1     1   7 use strict;
  1         3  
  1         58  
46              
47 1     1   1046 use Errno 1.00 qw(EIO);
  1         1539  
  1         124  
48 1     1   892 use HTTP::Lite 2.2 ();
  1         14395  
  1         972  
49              
50             our $VERSION = "0.007";
51              
52             =head1 CONSTRUCTOR
53              
54             =over
55              
56             =item Data::Entropy::RawSource::RandomnumbersInfo->new
57              
58             Creates and returns a handle object referring to a stream of random
59             octets generated by randomnumbers.info.
60              
61             =cut
62              
63             sub new {
64 1     1 1 15 my($class) = @_;
65 1         11 my $http = HTTP::Lite->new;
66 1         62 $http->http11_mode(1);
67 1         14 return bless({
68             http => $http,
69             buffer => "",
70             bufpos => 0,
71             error => 0,
72             }, $class);
73             }
74              
75             =back
76              
77             =head1 METHODS
78              
79             A subset of the interfaces described in L and L
80             are provided:
81              
82             =over
83              
84             =item $rawsrc->read(BUFFER, LENGTH[, OFFSET])
85              
86             =item $rawsrc->getc
87              
88             =item $rawsrc->ungetc(ORD)
89              
90             =item $rawsrc->eof
91              
92             Buffered reading from the source, as in L.
93              
94             =item $rawsrc->sysread(BUFFER, LENGTH[, OFFSET])
95              
96             Unbuffered reading from the source, as in L.
97              
98             =item $rawsrc->close
99              
100             Does nothing.
101              
102             =item $rawsrc->opened
103              
104             Retruns true to indicate that the source is available for I/O.
105              
106             =item $rawsrc->clearerr
107              
108             =item $rawsrc->error
109              
110             Error handling, as in L.
111              
112             =back
113              
114             The buffered (C et al) and unbuffered (C et al) sets
115             of methods are interchangeable, because no such distinction is made by
116             this class.
117              
118             Methods to write to the file are unimplemented because the stream is
119             fundamentally read-only. Methods to seek are unimplemented because the
120             stream is non-rewindable; C works, however.
121              
122             =cut
123              
124             sub _ensure_buffer {
125 0     0     my($self) = @_;
126 0 0         return 1 unless $self->{bufpos} == length($self->{buffer});
127 0           $self->{http}->reset;
128 0 0         unless($self->{http}->request(
129             "http://www.randomnumbers.info/cgibin/wqrng.cgi?".
130             "amount=256&limit=255"
131             ) == 200) {
132 0           $! = EIO;
133 0           return 0;
134             }
135 0           my($numbers) =
136             ($self->{http}->body =~ /((?:[0-9]+[\ \t\n]+){255}[0-9]+)/);
137 0 0         unless(defined $numbers) {
138 0           $! = EIO;
139 0           return 0;
140             }
141 0           $self->{buffer} = "";
142 0           $self->{bufpos} = 0;
143 0           while($numbers =~ /([0-9]+)/g) {
144 0 0         if($1 >= 256) {
145 0           $! = EIO;
146 0           return $self->{buffer} ne "";
147             }
148 0           $self->{buffer} .= chr($1);
149             }
150 0           return 1;
151             }
152              
153 0     0 1   sub close { 1 }
154              
155 0     0 1   sub opened { 1 }
156              
157 0     0 1   sub error { $_[0]->{error} }
158              
159             sub clearerr {
160 0     0 1   my($self) = @_;
161 0           $self->{error} = 0;
162 0           return 0;
163             }
164              
165             sub getc {
166 0     0 1   my($self) = @_;
167 0 0         unless($self->_ensure_buffer) {
168 0           $self->{error} = 1;
169 0           return undef;
170             }
171 0           return substr($self->{buffer}, $self->{bufpos}++, 1);
172             }
173              
174             sub ungetc {
175 0     0 1   my($self, $cval) = @_;
176 0 0         if($self->{bufpos} == 0) {
177 0           $self->{buffer} = chr($cval).$self->{buffer};
178             } else {
179 0           $self->{bufpos}--;
180             }
181             }
182              
183             sub read {
184 0     0 1   my($self, undef, $length, $offset) = @_;
185 0 0         return undef if $length < 0;
186 0 0         $_[1] = "" unless defined $_[1];
187 0 0         if(!defined($offset)) {
    0          
    0          
188 0           $offset = 0;
189 0           $_[1] = "";
190             } elsif($offset < 0) {
191 0 0         return undef if $offset < -length($_[1]);
192 0           substr $_[1], $offset, -$offset, "";
193 0           $offset = length($_[1]);
194             } elsif($offset > length($_[1])) {
195 0           $_[1] .= "\0" x ($offset - length($_[1]));
196             } else {
197 0           substr $_[1], $offset, length($_[1]) - $offset, "";
198             }
199 0           my $original_offset = $offset;
200 0           while($length != 0) {
201 0 0         unless($self->_ensure_buffer) {
202 0           $self->{error} = 1;
203 0           last;
204             }
205 0           my $avail = length($self->{buffer}) - $self->{bufpos};
206 0 0         if($length < $avail) {
207 0           $_[1] .= substr($self->{buffer}, $self->{bufpos},
208             $length);
209 0           $offset += $length;
210 0           $self->{bufpos} += $length;
211 0           last;
212             }
213 0           $_[1] .= substr($self->{buffer}, $self->{bufpos}, $avail);
214 0           $offset += $avail;
215 0           $length -= $avail;
216 0           $self->{bufpos} += $avail;
217             }
218 0           my $nread = $offset - $original_offset;
219 0 0         return $nread == 0 ? undef : $nread;
220             }
221              
222             *sysread = \&read;
223              
224 0     0 1   sub eof { 0 }
225              
226             =head1 SEE ALSO
227              
228             L,
229             L,
230             L,
231             L,
232             L
233              
234             =head1 AUTHOR
235              
236             Andrew Main (Zefram)
237              
238             =head1 COPYRIGHT
239              
240             Copyright (C) 2006, 2007, 2009, 2011
241             Andrew Main (Zefram)
242              
243             =head1 LICENSE
244              
245             This module is free software; you can redistribute it and/or modify it
246             under the same terms as Perl itself.
247              
248             =cut
249              
250             1;