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
|
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 ;-)
-Blake
| [reply] [d/l] |
|
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
| [reply] [d/l] [select] |
|
|