<?php
namespace Grav\Common\User;

abstract class Authentication
{
    /**
     * Create password hash from plaintext password.
     *
     * @param string $password Plaintext password.
     *
     * @throws \RuntimeException
     * @return string|bool
     */
    public static function create($password)
    {
        if (!$password) {
            throw new \RuntimeException('Password hashing failed: no password provided.');
        }

        $hash = self::sha512_crypt($password);

        if (!$hash) {
            throw new \RuntimeException('Password hashing failed: internal error.');
        }

        return $hash;
    }

    /**
     * Verifies that a password matches a hash.
     *
     * @param string $password Plaintext password.
     * @param string $hash     Hash to verify against.
     *
     * @return int              Returns 0 if the check fails, 1 if password matches, 2 if hash needs to be updated.
     */
    public static function verify($password, $hash)
    {
        // Fail if hash doesn't match
        if (!$password || !$hash || self::sha512_crypt($password, $hash) != $hash) {
            return 0;
        }

        return 1;
    }

    private static function sha512_crypt($password, $hash = null)
    {
        if (!$hash) {
            $fp = fopen('/dev/urandom', 'r');

            try {
                $salt = fread($fp, 32);
            } finally {
                fclose($fp);
            }

            $hash = '$6$' . base64_encode($salt);
        }

        return crypt($password, $hash);
    }
}