Today I learned that \"password\" tends to mean a memorizable string of an arbitrary number of characters, while \"key\" means a highly random string of bi
But I'd still appreciate answers from experts since this feels very unofficial and home-grown and makes me wonder whether it's breaking any "best practices" of security.
I was surprised not to find a simple function built into PHP.
/**
* It seems like we just need a way of getting a 32-byte key when all we have is a human-memorizable password and a salt for that user. But this function feels home-grown; what is the most secure way to do PBE (password-based encryption)?
*
* @param string $password
* @param string $salt Since this function must be deterministic (return a value consistently based on the inputs), it must accept a salt as an argument rather than generate a random salt every time. Storing a different salt for each user improves security.
* @param int $length
* @return string
*/
public static function deriveKey($password, $salt, $length = self::KEY_BYTES) {
$iterations = max([intval(config('hashing.bcrypt.rounds')), 15]);
$chars = 2 * $length; //In hex, a byte is always expressed as 2 characters. See more comments below and https://stackoverflow.com/a/43132091/.
$rawOutput = false; //Default is false. When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits. Hexit = hexadecimal digit (like "bit" = binary digit). There are 16 hexits: the numbers 0 to 9 and the letters A to F.
$key = hash_pbkdf2('sha256', $password, $salt, $iterations, $chars, $rawOutput); //A sha256 is 256 bits long (32 bytes), but the raw_output argument will determine how many characters the result has. https://stackoverflow.com/a/2241014/ and https://crypto.stackexchange.com/q/34995/
return $key;
}
I wonder if Halite or Libsodium-php offer this kind of function.
It seems like Libsodium has a crypto_pwhash function that probably is what I'm looking for (and uses Argon2).