Derive a 32-byte key from a password deterministically in PHP

前端 未结 3 755
[愿得一人]
[愿得一人] 2021-01-18 16:11

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

3条回答
  •  孤独总比滥情好
    2021-01-18 17:02

    Here is my updated function

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

提交回复
热议问题