/** * Decrypt then verify a password * * @param string $password - The user-provided password * @param string $stored - The encrypted password hash * @param EncryptionKey $secret_key - The master key for all passwords * @return boolean */ public static function verify(string $password, string $stored, EncryptionKey $secret_key) : bool { // First let's decrypt the hash $hash_str = Crypto::decrypt($stored, $secret_key); // Upon successful decryption, verify the password is correct $isArgon2 = \hash_equals(CryptoUtil::safeSubstr($hash_str, 0, 9), \Sodium\CRYPTO_PWHASH_STRPREFIX); $isScrypt = \hash_equals(CryptoUtil::safeSubstr($hash_str, 0, 3), \Sodium\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRPREFIX); if ($isArgon2) { return \Sodium\crypto_pwhash_str_verify($hash_str, $password); } elseif ($isScrypt) { return \Sodium\crypto_pwhash_scryptsalsa208sha256_str_verify($hash_str, $password); } return false; }
/** * Decrypt then verify a password * * @param HiddenString $password The user's password * @param string $stored The encrypted password hash * @param EncryptionKey $secretKey The master key for all passwords * @return bool Is this password valid? * @throws InvalidMessage */ public static function verify(HiddenString $password, string $stored, EncryptionKey $secretKey) : bool { $config = self::getConfig($stored); // Base64-urlsafe encoded, so 4/3 the size of raw binary if (Util::safeStrlen($stored) < $config->SHORTEST_CIPHERTEXT_LENGTH * 4 / 3) { throw new InvalidMessage('Encrypted password hash is too short.'); } // First let's decrypt the hash $hash_str = Crypto::decrypt($stored, $secretKey, $config->ENCODING); // Upon successful decryption, verify the password is correct return \Sodium\crypto_pwhash_str_verify($hash_str->getString(), $password->getString()); }