Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

String::MkPasswd still supported?

by Skeeve (Parson)
on Sep 30, 2014 at 05:25 UTC ( [id://1102411]=perlquestion: print w/replies, xml ) Need Help??

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

Recently I needed a function to generate passwords so instead of writing my own I did a CPAN search and found String::MkPasswd.

Unfortunately the function simply increases the number of lower case letters if you don't give enough minimum characters of each class. Example: If you want at least 2 lower case letters and 2 upper case letters and 8 characters length, you always end up with 2 upper case and 6 lower case letters.

I think this isn't too good so I created a pull request which will spread the missing 4 characters over all character classes.

Now I'm wondering whether or not the module is still supported as there seems to be nothing happening.


s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
+.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e

Replies are listed 'Best First'.
Re: String::MkPasswd still supported?
by karlgoethebier (Abbot) on Sep 30, 2014 at 09:37 UTC
    "... I needed a function to generate passwords so instead of writing my own..."

    You may use the build-in features (/dev/random or /dev/urandom, Fisher-Yates by hand etc.) like described here: Re: Password (pseudo)casual.

    Update:

    "...instead of writing my own..

    Don't mind: it's mine ;-)

    Regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

      I took yours now:
      #!/usr/bin/perl use strict; use warnings; print mkpasswd({ minlen => 8, maxlen => 10, lower => 1, special => 1, upper => 1, digit => 1, }); sub mkpasswd { my($param)= @_; if( not ref $param ) { $param= { minlen => $param, maxlen => $param, }; } if( ref $param eq 'HASH' ) { $param->{minlen}||= 8; $param->{maxlen}||= $param->{minlen} + 2; } my ( @l, @u, @n, @s, @p); open( URANDOM, "</dev/urandom" ) || die $!; read( URANDOM, $_, 4 ); close URANDOM; srand( unpack( "L", $_ ) ); @l = ( "a" .. "z" ); @u = ( "A" .. "Z" ); @n = ( 0 .. 9 ); @s = ( '#', ',', ' ', qw# ! " $ % & ' ( ) * + - . / : ; < = > ? @ [ \ ] ^ _ ` { | } + ~ # ); push( @p, $l[rand(@l)] ) for ( 1 .. $param->{lower} ); push( @p, $u[rand(@u)] ) for ( 1 .. $param->{upper} ); push( @p, $n[rand(@n)] ) for ( 1 .. $param->{digit} ); push( @p, $s[rand(@s)] ) for ( 1 .. $param->{special} ); my $m = $param->{minlen} - @p; $m=0 if $m<0; my $x = $param->{maxlen} - @p - $m + 1; $x=0 if $x<0; my(@j)= ( @l, @u, @s, @n ); $x= $m + rand($x); push( @p, $j[rand(@j)] ) for ( 1 .. $x ); for ( my $i = @p ; --$i ; ) { my $j = int( rand( $i + 1 ) ); next if $i == $j; @p[ $i, $j ] = @p[ $j, $i ]; } return join( "", @p ); }

      s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
      +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e

        License granted without any warranty ;-)

        Regards, Karl

        P.S.: You may send some free beer for the monks to the cellerar's office.

        «The Crux of the Biscuit is the Apostrophe»

Re: String::MkPasswd still supported?
by davido (Cardinal) on Sep 30, 2014 at 06:12 UTC

    Supported or not, it just uses Perl's rand, which isn't suitable as a cryptographically secure pseudo-random number generator.


    Dave

      I know that rand isn't the best choice if it comes to cryptographically secure randomness.

      But would you agree that it is safe enough to generate a user's first-time password which she needs to change upon first login anyway?


      s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
      +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e

        It seems reasonable, but I don't know all the possible attack vectors. Bytes::Random::Secure would provide strings that are based on a CSPRNG using the random_string_from function, but then you would have to do additional work to assure they contain the minimum requirement of upper/lower case, etc.

        If nothing else exists, it might be worthwhile to create a module that does what you want, but bases it on a CSPRNG.

        Update: This should generate ten passwords of length 8, consisting of a minimum of two lower-case ASCII letters, and two upper-case ASCII letters, with the balance consisting of a mix of other random characters (including alpha) from those available on a standard EN-US keyboard.

        use Bytes::Random::Secure; use List::Util 'shuffle'; use constant CSPRNG => Bytes::Random::Secure->new( NonBlocking => 1 ); sub uppers { return CSPRNG->string_from( join( '', 'A'..'Z' ), shift // 2 ); } sub lowers { return CSPRNG->string_from( join( '', 'a'..'z' ), shift // 2 ); } sub mixed { return CSPRNG->string_from( join( '', 'A'..'Z', 'a'..'z', '0'..'9', '!@#$%^&*()_+{}|[]\<>?,./: +;"\'' ), shift // 4 ); } sub gen_pass { my $uc = uppers(); my $lc = lowers(); my $mix = mixed(); return join( '', shuffle( split //, "$uc$lc$mix" ) ); } for ( 1 .. 10 ) { print gen_pass(), "\n"; }

        One possible shortcoming is that it does use List::Util::shuffle, which is a perfectly good implementation of the Fisher-Yates Shuffle, but it relies on the built-in rand again. So while the characters are generated by a CSPRNG, the ordering of those characters is handled by built-in rand. At least the characters themselves are being generated by the ISAAC algorithm, with a CSPRNG seeded using 256 bits of entropy supplied by a non-blocking call to Crypt::Random::Seed. CRS will use /dev/urandom in this case on Linux systems, or will make an API call on Windows systems.

        If someone is really paranoid they might look for a shuffle that uses a pluggable random source so that it could be handed a CSPRNG to use in shuffling.

        To be honest, it would probably be better to just forget about the minimum number of lowercase and uppercase characters, and make a single call to string_from. This will provide better entropy, as it doesn't constrain four of the digits to some narrower range, and it would eliminate the need to shuffle. Generate, then check against a dictionary, as well as looking for pathological cases like all the same digit, or sequential digits.


        Dave

        Note that an 8-character alphabetic password has log(26*2)/log(2)*8 = 45.6 bits of randomness. As of 5.20, perl uses drand48, which is named for its 48 bits of internal state. Nominally, it has enough randomness to fill that password, but it's seeded with only 32 bits. So if your program starts up, generates one password, and then exits, only about 1 in 12000 (= 2**(45.6-32)) of the possible passwords can be generated.

        If you're generating many passwords at once, they are going to be highly correlated. Someone can in principle use their password to guess what the next password will be. There are about 5 or 6 (= 2**(48-45.6)) possible next passwords. An old node of mine shows how this can be done (Predict Random Numbers).

        Bottom line: Use a secure random number generator.

Re: String::MkPasswd still supported?
by LanX (Saint) on Sep 30, 2014 at 09:26 UTC
    I read your 8 day old bug report and as you state there this behavior is well documented.

    Please note that it follows the way many password policies are phrased, taking lowercase as default.

    What you want is a fundamental change of concept, so would only be fair to provide the necessary code to the author.

    First step could be to follow Choroba's recommendation to simply adjust the number of min capital letters with the help of a random generator.

    Next step could be to patch this behavior into the code.

    And if the author doesn't reply, fork.the module and ask CPAN to take over maintenance.

    Cheers Rolf

    (addicted to the Perl Programming Language and ☆☆☆☆ :)

Re: String::MkPasswd still supported?
by Khen1950fx (Canon) on Sep 30, 2014 at 14:49 UTC
Re: String::MkPasswd still supported?
by choroba (Cardinal) on Sep 30, 2014 at 08:11 UTC
    If you want at least 2 lower case letters and 2 upper case letters and 8 characters length, you always end up with 2 upper case and 6 lower case letters.
    So what about using a random number generator to generate the minupper in the range 2 .. 8?
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1102411]
Approved by Athanasius
Front-paged by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (2)
As of 2024-04-19 21:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found