Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

spew - print out random characters

by grinder (Bishop)
on Nov 12, 2001 at 19:19 UTC ( #124838=sourcecode: print w/replies, xml ) Need Help??
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]}: $
    if( $char =~ $re ) {
        $spew .= $char;
close R;

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

my %verbose;
while( <DATA> ) {
        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


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


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>.



B<% spew>


B<% spew -v 6>


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

B<% spew 56 0-1>


B<% spew -v 40 ' -~'>

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
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

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).


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 (
     eval {join chr(64) => qw[landgren]}


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
" 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
Replies are listed 'Best First'.
Re: spew - print out random characters
by blakem (Monsignor) on Nov 12, 2001 at 19:56 UTC
    I'm not especially familiar with /dev/urandom but I understand that it can "run out" of randomness and have to wait for some more to be "collected". As such it should be used sparingly, but you're tossing out over 50% of the random chars that you fetch from it.

    Since you wont be using high bit ascii, you could zero out the most significant bit, mapping it 1 to 1 with the low bit ascii. This would significantly reduce the amount of randomness that you have to throw out.

    This works on my x86 linux machine.... endianness might matter, but I'm not sure.

    read( R, $char, 1 ) or die "Failed to read 1 char from @{[SRC]}: $!\n" +; vec($char, 7 , 1) = 0; # map high-bit ascii to low-bit ascii
    Update: As stefan k pointed out to me, /dev/urandom doesn't block when the entropy pool runs out. Instead, when no true random bits are available it will return pseudorandom bits instead. Its still probably a good idea to avoid pulling more bits than necessary though, just to keep the entropy pool happy and the pseudorandoms at bay ;-)


      OpenBSD talks about /dev/srandom, which produces a cryptographically strong source of bits, but it just blocks on my machine. I wonder if I have to fiddle with a kernel setting to make it work.

      update: turns out that on OpenBSD, you cannot just open R, '/dev/srandom' and hope that it works. Apparently (and this strikes me as incredibly klugey, but maybe it's more bulletproof), you have to do something like:

      dd if=/dev/srandom of=./bits bs=4096 count=1

      and after a suitably impressive wait you will have some strong random bits waiting for you in ./bits.

      Otherwise an alternative is to grab some bits from a random seed. Maybe for v2.0. I think Linux has /dev/random which blocks if the entropy pool is exhausted, which would be the way to go on that platform. Trouble is that OpenBSD doesn't implement that device, it is RFU.

      update: It looks like the lava lamp is dead.

      g r i n d e r

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://124838]
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (4)
As of 2023-11-28 19:05 GMT
Find Nodes?
    Voting Booth?

    No recent polls found