http://www.perlmonks.org?node_id=124838
Category: Utility Scripts
Author/Contact Info grinder
Description: Print out random characters, suitable for making hard-to-guess password, or manual IPSec authentification keys (which is why I wrote this in the first place).
#! /usr/bin/perl -ws
#
# 2001/11/09  dwl

use strict;
use constant DEFAULT    => 16;
use constant SRC        => '/dev/urandom';
use constant LINE_WIDTH => 72;

use vars qw/$v/;

my $chars_wanted = shift || DEFAULT;
my $re_class     = shift || 'A-Za-z0-9';
my $re           = qr/^[$re_class]$/;

open R, SRC or die "Random source (@{[SRC]} not available: $!.\n";
my $char;
my $spew = '';
while( $chars_wanted ) {
    read( R, $char, 1 ) or die "Failed to read 1 char from @{[SRC]}: $
+!\n";
    if( $char =~ $re ) {
        $spew .= $char;
        --$chars_wanted;
    }
}
close R;

print "$spew\n";
exit unless defined $v;
print "\n";

my %verbose;
while( <DATA> ) {
        chomp;
        my( $char, $name ) = ($_ =~ /^(.) (.*)$/);
        $verbose{$char} = $name;
}

my $line = '';
my $len  = 0;

for( split //, $spew ) {
        my $case = ($_ =~ s/([A-Z])/lc $1/e) ? 'upper-' : '';
        my $description = (0 == $len ? '' : ' ' ) . $case . $verbose{$
+_};
        my $desc_len = length $description;
        if( $len + $desc_len > LINE_WIDTH ) {
                print "\n";
                $len = 0;
                --$desc_len; # remove space
                $description = substr( $description, 1 );
        }
        print $description;
        $len += $desc_len;
}
print "\n";

=head1 NAME

spew - spew random characters

=head1 SYNOPSIS

B<spew> [B<-v>] [count] [character-class]

=head1 DESCRIPTION

Read characters from a device that emits random data (such as
/dev/urandom), and print them out. This can be used as the
basis for creating passwords, or manual IPSec authentification
keys (using a count of 64 or more is recommended).

If C<count> is omitted, the value of 16 is used.

If C<character-class> is omitted, the character class C<A-Za-z0-9>
is used. To specify hexadecimal characters, use C<0-9a-f>. To use
all the standard printable ASCII characters use the obfuscated C<!-~>
or C< -~> character classes. Note that the latter class probably
needs quoting to avoid being clobbered by the shell.

=head1 OPTIONS

=over 5

=item B<-v>

Verbose. After printing out the character string, reprint the
string using words, suitable for reading out over the telephone. For
instance C<vT9#> would be rendered as C<victor upper-tango nine hash>.

=back

=head1 EXAMPLES

B<% spew>

GByL4t9xOm8oNgZ8

B<% spew -v 6>

qQlaRO

quebec upper-quebec lima alpha upper-romeo upper-oscar

B<% spew 56 0-1>

10100000001101000010111001010011001001100101011110001101

B<% spew -v 40 ' -~'>
Q4EO[ZTs;p{nikzy>3&V@W]ht{bMUu.DCp<<n_{2

upper-quebec four upper-echo upper-oscar left-square upper-zulu
upper-tango sierra semi-colon papa left-curly november india kilo zulu
yankee greater-than three ampersand upper-victor at upper-whiskey
right-square hotel tango left-curly bravo upper-mike upper-uniform
uniform dot upper-delta upper-charlie papa less-than less-than novembe
+r
underscore left-curly two

=head1 BUGS

Very little error checking is performed.

Uses the -s Perl switch for command line parsing, should use
L<Getopt::Mixed> or something similar.

Not portable to Win32 platforms, due to the lack of a /dev/random
analogue.

To be really paranoid, on OpenBSD, one should use /dev/srandom, which
is cryptographically strong. Unfortunately, it blocks too much to be
of any practical use (I guess I need to buy a hardware generator).

=head1 COPYRIGHT

Copyright (c) 2001 David Landgren.

This script is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=head1 AUTHOR

     David "grinder" Landgren
     grinder on perlmonks (http://www.perlmonks.org/)
     eval {join chr(64) => qw[landgren bpinet.com]}

=cut

__DATA__
a alpha
b bravo
c charlie
d delta
e echo
f foxtrot
g golf
h hotel
i india
j juliet
k kilo
l lima
m mike
n november
o oscar
p papa
q quebec
r romeo
s sierra
t tango
u uniform
v victor
w whiskey
x xray
y yankee
z zulu
0 zero
1 one
2 two
3 three
4 four
5 five
6 six
7 seven
8 eight
9 nine
! excla
  space
" double-quote
# hash
$ dollar
% percent
& ampersand
' single-quote
( left-paren
) right-paren
* star
+ plus
, comma
- minus
. dot
/ slash
: colon
; semi-colon
< less-than
= equals
> greater-than
? ques
@ at
[ left-square
\ backslash
] right-square
^ caret
_ underscore
` backtick
{ left-curly
| pipe
} right curley
~ twiddle