1#----------------------------------------------------------------------------+
2#
3#  String::Urandom - An alternative to using /dev/random
4#
5#  DESCRIPTION
6#  Using output of /dev/urandom.  Simply convert bytes into 8-bit characters.
7#
8#  AUTHOR
9#  Marc S. Brooks <mbrooks@cpan.org>
10#
11#  This module is free software; you can redistribute it and/or
12#  modify it under the same terms as Perl itself.
13#
14#----------------------------------------------------------------------------+
15
16package String::Urandom;
17
18use strict;
19use warnings;
20use Params::Validate qw( :all );
21
22our $VERSION = 0.16;
23
24#~~~~~~~~~~~~~~~~~~~~~~~~~~[  OBJECT METHODS  ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
25
26#----------------------------------------------------------------------------+
27# new(\%params)
28#
29# General object constructor.
30
31sub new {
32    my $class  = shift;
33    my $params = (ref $_[0] eq 'HASH') ? shift : { @_ };
34    return bless( {
35        LENGTH => $params->{LENGTH} || 32,
36        CHARS  => $params->{CHARS}  ||
37                  [ qw/ a b c d e f g h i j k l m n o p q r s t u v w x y z
38                        A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
39                        1 2 3 4 5 6 7 8 9                                 / ]
40    }, $class );
41}
42
43#----------------------------------------------------------------------------+
44# str_length($value)
45#
46# Set/Get the string length.
47
48sub str_length {
49    my ( $self, $value )
50      = validate_pos( @_,
51          { type => OBJECT },
52          { type => SCALAR, optional => 1 }
53          );
54
55    return $self->{LENGTH} unless ($value);
56    return $self->{LENGTH} unless ($value =~ /^[\d]*$/);
57    $self->{LENGTH} = $value;
58    return $self->{LENGTH};
59}
60
61#----------------------------------------------------------------------------+
62# str_chars($value)
63#
64# Set/Get the string characters.
65
66sub str_chars {
67    my ( $self, $value )
68      = validate_pos( @_,
69          { type => OBJECT },
70          { type => SCALAR, optional => 1 }
71          );
72
73    return $self->{CHARS} unless ($value);
74    return $self->{CHARS} unless ($value =~ /^[\w\s]*$/);
75    my @chars = split(/\s+/, $value);
76    $self->{CHARS} = \@chars;
77    return $self->{CHARS};
78}
79
80#----------------------------------------------------------------------------+
81# rand_string()
82#
83# Generate a new random string.
84
85sub rand_string {
86    my ($self)
87      = validate_pos( @_,
88          { type => OBJECT }
89          );
90
91    my @chars = @{ $self->{CHARS} };
92
93    shuffle_array(\@chars);
94
95    open (DEV, "/dev/urandom") or die "Cannot open file: $!";
96    read (DEV, my $bytes, $self->{LENGTH});
97
98    my $string;
99    my @randoms = split(//, $bytes);
100    foreach (@randoms) {
101        $string .= $chars[ ord($_) % @chars ];
102    }
103    return $string;
104}
105
106#----------------------------------------------------------------------------+
107# shuffle_array()
108#
109# Fisher-Yates shuffle algorithm - Perl Cookbook, Recipe 4.17
110
111sub shuffle_array {
112    my $array = shift;
113
114    for (my $i = @$array; --$i;) {
115        my $j = int rand ($i + 1);
116        next if ($i == $j);
117        @$array[$i, $j] = @$array[$j, $i];
118    }
119}
120
1211;
122
123__END__
124
125=head1 NAME
126
127String::Urandom - An alternative to using /dev/random
128
129=head1 SYNOPSIS
130
131  use String::Urandom;
132
133  my $obj = String::Urandom->new(
134      LENGTH => 55,
135      CHARS  => [ qw/ a b c 1 2 3 / ]
136    );
137
138  print $obj->rand_string, "\n";
139
140=head1 DESCRIPTION
141
142Using output from /dev/urandom.  Simply convert bytes into 8-bit characters.
143
144=head1 PREREQUISITES
145
146  Params::Validate
147
148=head1 INSTALLATION
149
150From source:
151
152  $ tar xfz String-Urandom-0.X.X.tar.gz
153  $ perl MakeFile.PL PREFIX=~/path/to/custom/dir LIB=~/path/to/custom/lib
154  $ make
155  $ make test
156  $ make install
157
158Perl one liner using CPAN.pm:
159
160  $ perl -MCPAN -e 'install String::Urandom'
161
162Use of CPAN.pm in interactive mode:
163
164  $ perl -MCPAN -e shell
165  cpan> install String::Urandom
166  cpan> quit
167
168Just like the manual installation of Perl modules, the user may need root access during
169this process to insure write permission is allowed within the installation directory.
170
171=head1 OBJECT METHODS
172
173=head2 new
174
175Create a new session object.  Configuration items may be passed as a parameter.
176
177  my $obj = new String::Urandom;
178
179    or
180
181  my %params = (
182      LENGTH => 55,
183      CHARS  => [ qw/ a b c 1 2 3 / ]
184    );
185
186  my $obj = String::Urandom->new(\%params);
187
188=head2 str_length
189
190This method will Set/Get the string character length.
191
192The default value is: 32
193
194  $obj->str_length(55);
195
196=head2 str_chars
197
198This method will Set/Get characters used for generating a string.
199
200The default value is: a-z A-Z 0-9
201
202  $obj->str_chars('a b c 1 2 3');
203
204=head2 rand_string
205
206This method generates a new random string.
207
208  $obj->rand_string;
209
210=head1 PARAMETERS
211
212=head2 LENGTH
213
214Defines the length of the string in characters.
215
216The default value is: 32
217
218=head2 CHARS
219
220Defines the characters used for generating the string.
221
222The default value is: a-z A-Z 0-9
223
224=head1 REQUIREMENTS
225
226Any flavour of UNIX that supports /dev/urandom
227
228=head1 SECURITY
229
230In general, the longer the string length and total characters defined, the more
231secure the output result will be.
232
233=head1 NOTES
234
235The /dev/urandom is an ("unlocked" random source) which reuses the internal pool to
236produce more pseudo-random bits.  Since this is the case, the read may contain less
237entropy than its counterpart /dev/random.  Knowing this, this module was intended
238to be used as a pseudorandom string generator for less secure applications where
239response timing may be an issue.
240
241=head1 SEE ALSO
242
243urandom(4)
244
245=head1 AUTHOR
246
247Marc S. Brooks E<lt>mbrooks@cpan.orgE<gt> L<http://mbrooks.info>
248
249=head1 COPYRIGHT
250
251This program is free software; you can redistribute it and/or modify it
252under the same terms as Perl itself.
253
254See L<http://www.perl.com/perl/misc/Artistic.html>
255
256=head1 DISCLAIMER OF WARRANTY
257
258BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
259FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
260OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
261PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
262EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
263WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
264ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
265YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
266NECESSARY SERVICING, REPAIR, OR CORRECTION.
267
268IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
269WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
270REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
271LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
272OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
273THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
274RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
275FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
276SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
277SUCH DAMAGES.
278
279=cut
280