Skip to content

Instantly share code, notes, and snippets.

@pmeulen
Last active August 29, 2015 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pmeulen/3dff8bab3227ed340dd1 to your computer and use it in GitHub Desktop.
Save pmeulen/3dff8bab3227ed340dd1 to your computer and use it in GitHub Desktop.
Generate a secure random password in the the "Base32" alphabet
<?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