On Sat, 5 May 2001, cherukuwada subrahmanyam wrote:
> Hi,
> Is there any easy way to generate random string of particluar length.
> The idea is to generate passwords randomly.
Here is some code which produces wordlike passwords via random probes into
a dictionary. The results are wordlike, but not words.
The code could probably be more efficient, but it works.
I've used this for an automated "forgot my password" mailback mechanism;
the password is marked as "usable once only", so the user has to change it
as soon as it is used.
---- cut ----
#!/usr/bin/perl -w
use strict;
# Generate a random word based on a corpus.
# parameters are: number of characters of context
# length of string to return
$| = 1;
# Number of probes to make to determine possible following char
my $CONTEXT = $ARGV[0] || 1;
# Length of word to generate
my $LENGTH = $ARGV[1] || 8;
# Read the dictionary and clean it up. Remove newlines and
# translate all characters to lower case.
open Z,"knuth_words" or die "Can't open dictionary: $!";
$/ = undef;
my $corpus = <Z>;
$corpus =~ s/\n/ /g;
$corpus =~ tr/A-Z/a-z/;
# All 'my' variables are defined outside the loop for maximum speed.
my $c;
my @choices;
my $count;
my $scan = " ";
my $out = "";
# Keep going until we have enough characters.
while (length($out) < $LENGTH) {
# Do $CONTEXT number of probes to get context for the next letter.
# We initially start out with no results from probes.
$count = $CONTEXT;
@choices = ();
while ($count--) {
# Select random start point inside dictionary.
my $start_pos = int rand length $corpus;
# select a character by scanning for the current character,
# starting at the random point we just calculated, and extracting
# the character right after that.
#
# We do this with index and substring because they are considerably
# faster in this application than pattern matching is. (Believe me,
# I tried pattern matching first!)
$c = substr($corpus,(index $corpus,$scan,$start_pos)+1, 1);
# If the character isn't useful, try another random probe.
redo if $c =~ /[' ]/;
# Save it if it is useful.
push @choices,$c;
}
# Choose one of the characters we pulled out at random, and add it to
# the word. It becomes the context for the next probe.
$scan = $choices[int(rand($CONTEXT))];
$out .= $scan;
}
# Word is full up. print it.
print $out,"\n";
---- cut ----
Some sample output follows.
Context 1, length 8:
blthines ssshylel chineent stilanon musblust pongabll dratiffe chtuneed
leckesma syerefad maliness hoateste cicictra rtyretif iserapea giatagup
Context 2, length 12:
praleposmedi ineresabanec vactisculass crondgatichi rexisolleste
Context 4, length 16:
ratiflarichollan asckichymalastat perrsiomicthinia jatiobatalymerob
The output wavers on the edge of intelligibility, which is just what we
want. I find output from 8 to 12 characters long easiest to actually
remember.
--- Joe M.