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.

Reply via email to