Tuesday, May 28, 2013

PHP - Store Password

Code snip of password verification when we use plain text. (should never happen...)
            $query = $pdo->prepare("SELECT * FROM user WHERE user_name = ? and user_password = ?");
            $query->bindValue(1, $username);
            $query->bindValue(2, $password);
            $query->execute();

            $num = $query->rowCount();

            if ($num == 1) {
                // correct
                $_SESSION['logged_in'] = true;
                header('Location: index.php');
                exit();
            } else {
                // incorrect
                $error = "Incorrect Details.";
            }

All right, let us add some protection to password with MD5. Verification code is the same, and just call md5 to user input.
//
$password = md5($_POST['password']);
//

MD5 is one of the cryptographic hashing methods to make it difficult to get the original password. The method looks perfect but it is vulnerable to Brute Force (hash collision) and Rainbow Table.

Rainbow Table is pretty cool and it not only works to MD5, but all hash methods, such as SHA1.

So, what we should do? In general, we should
  • Use slow hashing algorithm (bcrypt)
  • Use random salt
  • Recreate hash every time when user login

Hash generation code
    public function generateHash($password) {
        $cost = 10;
        $salt = strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.');
        $salt = sprintf("$2a$%02d$", $cost) . $salt;
        $hash = crypt($password, $salt);
        return $hash;
    }

Verification code (regenerate hash when login)
            $query = $pdo->prepare("SELECT user_password FROM user WHERE user_name = ?");
            $query->bindValue(1, $username);
            $query->execute();
            $data = $query->fetch();

            if (crypt($password, $data["user_password"]) == $data["user_password"]) {
                $_SESSION['logged_in'] = true;
                header('Location: index.php');

                $newhash = $chash->generateHash($password);
                $query= $pdo->prepare("UPDATE user SET user_password = ? WHERE user_name = ?");
                $query->bindValue(1, $newhash);
                $query->bindValue(2, $username);
                $query->execute();
                exit();
            } else {
                $error = "Incorrect Details.";
            }

No comments:

Post a Comment