Last active
August 29, 2015 14:18
-
-
Save pmeulen/3dff8bab3227ed340dd1 to your computer and use it in GitHub Desktop.
Generate a secure random password in the the "Base32" alphabet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Generate a secure random password in the the "Base32" alphabet | |
// Uses openssl secure random function for RNG generation | |
// Because the set of characters has 32 = 2^5 distinct values, characters can be | |
// easily selected, without bias (i.e. each character has the same chance | |
// of being selected), by using 5 bits of randomness per character. | |
// Note: strlen(base32_alphabet) MUST be exactly 2^bits_per_value | |
// RFC 4648 - Base32 alphabet | |
// 01234567890123456789012345678901 | |
$base32_alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; | |
$password_length=8; // The length of the password to generate | |
$bits_per_value=5; // The 32 possible characters in the Base32 alphabet can be represented in exactly 5 bits | |
$random_bytes_required=(integer)( ($password_length * $bits_per_value) / 8 ) + 1; | |
$crypto_strong=false; | |
$random_bytes=openssl_random_pseudo_bytes($random_bytes_required, $crypto_strong); // Generate random bytes | |
if (!$crypto_strong) | |
die('openssl_random_pseudo_bytes() is not cryptographically strong'); | |
if (FALSE === $random_bytes) | |
die('openssl_random_pseudo_bytes() failed'); | |
if (strlen($random_bytes) < $random_bytes_required) | |
die('Logic error'); | |
// Transform each byte $random_bytes into $random_bits where each byte | |
// is converted to its 8 character ASCII binary representation. | |
// This allows us to work with the individual bits using the php string functions | |
// Not very efficient, but easy to understand. | |
$random_bits=''; | |
for ($i=0;$i<$random_bytes_required;++$i) | |
$random_bits.=str_pad( decbin( ord($random_bytes[$i]) ), 8, '0', STR_PAD_LEFT); | |
// Get 'bits' form $random_bits string in blocks of 5 bits, convert bits to value [0..32> and use | |
// this as offset in $base32_alphabet to pick the character | |
$password=''; | |
for ($i=0;$i<$password_length;++$i) | |
{ | |
$random_value_bin=substr($random_bits, $i * $bits_per_value, $bits_per_value); | |
if ( strlen($random_value_bin) < $bits_per_value ) | |
die('Logic error'); | |
$password.=$base32_alphabet[ bindec($random_value_bin) ]; | |
} | |
echo $password; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment