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.
|