Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,

I want to generate a random string as unique as possible - the reason being, it is for a login script and when someone forgets their password, I want them to input their email address, the script generate a unique string (letters,numbers, whatever) which gets emailed to the user - then they must go to a url, enter the string and set their new passwords.

If anyone can suggest a way of doing this I would be very appreciative. Many Thanks.

John

Replies are listed 'Best First'.
(Ovid) Re: Unique Sequence
by Ovid (Cardinal) on Sep 08, 2001 at 02:34 UTC
    use Digest::MD5; my $md5 = Digest::MD5->new; my $remote = $ENV{ REMOTE_ADDR } . $ENV{ REMOTE_PORT }; my $unique = $md5->md5_base64( time, $$, $remote, $email ); $unique =~ tr|+/=|-_.|; # Make non-word characters URL-friendly

    That will generate a unique, URL-friendly 22 character string for them.

    Cheers,
    Ovid

    Vote for paco!

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: Unique Sequence
by dws (Chancellor) on Sep 08, 2001 at 02:34 UTC
    merlyn prefers a simple MD5-based scheme, which he demonstrates here. I've adopted this technique, and am reasonably happy with it.

    (Note: this is very close to the scheme that Ovid posted seconds before above.)

Re: Unique Sequence
by blakem (Monsignor) on Sep 08, 2001 at 02:44 UTC
    Here is a quickie random password generator that I've used in the past...
    #!/usr/bin/perl -wT use strict; sub passgen { # sub to gen random passwd my $len = shift; # one integer param for length of passwd my @chars = (0..9,'A'..'Z','a'..'z'); # which chars are leg +al my $passwd; $passwd .= $chars[rand @chars] for (1..$len); # make the passwd return $passwd; } #### Testing Loop #### for my $len (6..9) { # for various lengths for my $i (1..3) { # try it a few times my $passwd = passgen($len); print "$i.)L=$len randpass = '$passwd'\n"; } print "\n"; } =sample output 1.)L=6 randpass = 'rqLb1V' 2.)L=6 randpass = 'zdrG8f' 3.)L=6 randpass = '5Rl2mA' 1.)L=7 randpass = 'Z4AiWxX' 2.)L=7 randpass = 'gnx6RFy' 3.)L=7 randpass = 'HbZJ6Zw' 1.)L=8 randpass = 'yp5euXPx' 2.)L=8 randpass = 'JZXNkGui' 3.)L=8 randpass = 'oaVlhw1f' 1.)L=9 randpass = 'DcFWjoSie' 2.)L=9 randpass = 'YMZ5mXOM4' 3.)L=9 randpass = 'm6Kgo8HJu'

    -Blake

Re: Unique Sequence (boo)
by boo_radley (Parson) on Sep 08, 2001 at 03:22 UTC
    I have used string::random for this very purpose in the past. Flexible and quick; patterns may be specified for output - you may specify uc and lc letter, numbers, punctuation, etc, to precisely control what the output will look like. (Yes, I know that specifying a pattern makes it technically "not random". Thank you.)
(crazyinsomniac) Re: Unique Sequence
by crazyinsomniac (Prior) on Sep 08, 2001 at 05:13 UTC
    I sometime use something along these lines, which does pretty well (you can make it into a sub if you like).
    #!/usr/bin/perl -w my $gmtime =join '', gmtime; my $time = time; my $rand = rand time; my @salt = ('.','/','A'..'Z',0..9,'a'..'z'); my $salt = join '', (@salt)[rand @salt, rand @salt]; my $uniquetempass = crypt( $gmtime.$rand.$time, $salt); print 'gmtime ', $gmtime, "\n"; print 'time ',$time,"\n"; print 'rand ', $rand,"\n"; print 'salt ', $salt, "\n"; print $uniquetempass, "\n";

     
    ___crazyinsomniac_______________________________________
    Disclaimer: Don't blame. It came from inside the void

    perl -e "$q=$_;map({chr unpack qq;H*;,$_}split(q;;,q*H*));print;$q/$q;"

Re: Unique Sequence
by George_Sherston (Vicar) on Sep 08, 2001 at 02:27 UTC
    I have a similar situation and my choice was $unique = int rand 1000000000 Not guaranteed 100% unique, but I'm prepared to bet on it. The more zeroes, the closer to true uniqueness! n.b. I'm pretty much making this up as I go, so this is almost certainly not the canonical solution: but it has the merits that it is simple and one knows how it works.

    § George Sherston
Re: Unique Sequence
by Anonymous Monk on Sep 08, 2001 at 20:24 UTC
    John,

    This begs the question - where are you going to store the unique string so when (if) the user comes back you can match the entered string?

    If you're using some type of flat file store, or in-memory storage - all the above should work fine. However, if your using a database, most rdbms all ready have this capability built in. Sybase has identity columns and Oracle has sequences (Mysql has ??) these are guarenteed (sp?) to be unique and can be most useful for your situtation.

    -derby