After reading an article on Skull Security mentioning the potential weakness of php's mt_rand function because of weak auto-seeding (http://ow.ly/4nrne), I decided to see what -- if any -- entropy I could find available from within php. The idea is to have enough (weak) sources that even if one or two are manipulated, lost or recovered, there's enough left to thwart brute force against the resulting passwords later.
Hopefully the result is both readable and usable, although I don't expect it to be production-quality.
<?php
/**
* Return a random password.
*
* v1.01
* Jumps through many hoops to attempt to overcome autoseed weakness of php's mt_rand function
*
*/
function myRandomPassword() {
// Change this for each installation
$localsecret = 'qTgppE9T2c';
// Determine length of generated password
$pwlength = 10;
// Character set for password
$pwchars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz0123456789';
$l = strlen( $pwchars ) - 1;
// Get a little bit of entropy from sources that should be inaccessible to outsiders and non-static
$dat = getrusage(); // gather some information from the running system
$datline = md5(implode($dat)); // wash using md5 -- it's fast and there's not enough entropy to warrant longer hash
$hardToGuess = $datline;
$self = __FILE__; // a file the script should have read access to (itself)
$stat = stat($self); // information about file such as inode, accessed time, uid, guid
$statline = md5(implode($stat)); // wash
$hardToGuess .= $statline;
$preseed = md5(microtime()) . getmypid() . $hardToGuess . memory_get_usage() . disk_free_space('.') . $localsecret;
$seed = sha1( $preseed ); // final wash, longer hash
// Seed the mt_rand() function with a better seed than the standard one
mt_srand ($seed);
// Pick characters from the lineup, using the seeded mt_rand function
$pw = '';
for ( $i = 0; $i < $pwlength; $i++ ) {
$pw .= $pwchars{ mt_rand( 0, $l ) };
}
// Return the result
return $pw;
}
echo myRandomPassword();
?>
Revision 1.01 adds a local secret.