0

I'm looking for a simple (or as simple as possible) yet secure method for hashing and salting a users password when submitting it to the database and then retrieving from the database. Having spent the past 3 hours researching, there are literally hundreds of different methods that each person will say is the best method.

I'm looking for a relatively simple method that will also keep users accounts secure. Obviously the term secure can be interpreted differently, but i just want it, at the very least, be very difficult for a would-be hacker (or whatever you'd call these saddo's) to gain access to a users account.

I appreciate that i should have at least tried a few things, but they all seem so convoluted and overly secure for my purpose.

I tried using password_hash() but it appears i'm running an earlier PHP version than 5.5. I understand there are issues with the code below, but it's simply a starting point for a person project i'm working on in order to better learn PHP.

Current registration form

$username = $_POST['username'];
$password = $_POST['password'];

try {   

    $result = $db->prepare("INSERT INTO 
                            user_info 
                            SET 
                            username = :user,
                            pass = :pass
                            ");
    $result->bindParam(':user', $username);
    $result->bindParam(':pass', $password);
    $result->execute();
}

catch (Exception $e) {
    echo "Could not create username";
}

if (isset($_POST['submit'])) { 
    foreach ($_POST as $field) {
        if (empty($field)) {
            $fail = true;
        }
        else {
            $continue = false;
        }
    }
    if ($field == $fail) {
        echo "You must enter a username and/or password";
    }
    else {
        echo "Your account has been successfully created.";
    }
     }

The login logic

$username = $_POST['username'];          
$password = $_POST['password'];

try {   

    $result = $db->prepare("SELECT username, pass FROM user_info WHERE username = :user AND BINARY pass = :pass");
    $result->bindParam(':user', $username);
    $result->bindParam(':pass', $password);
    $result->execute();
    $rows = $result->fetch(PDO::FETCH_NUM);
}

catch (Exception $e) {
    echo "Could not retrieve data from database";
    exit();
}

if ($password = $rows) {
    session_start();
    $_SESSION['username'] = $_POST['username'];
    $_SESSION['loggedin'] = true;
    include("inc/redirect.php");

} else {
    if (isset($_POST['login'])) {
        echo "Username or password incorrect (passwords are case sensitive)";
    }
}
Nikki Mather
  • 1,118
  • 3
  • 17
  • 33
  • 2
    For PHP version prior to 5.5, use the Compatibility pack https://github.com/ircmaxell/password_compat/ – Funk Forty Niner Jun 25 '14 at 22:28
  • Look at this: http://stackoverflow.com/questions/401656/secure-hash-and-salt-for-php-passwords and this: http://codahale.com/how-to-safely-store-a-password/ – Styx Jun 25 '14 at 22:36
  • @Styx thanks. In the first URL, someone states to not use sha1, do you know why they'd suggest that's NEVER done? – Nikki Mather Jun 25 '14 at 22:42
  • SHA1 is simple to compute nowadays. Look into this links: http://www.bentasker.co.uk/blog/security/201-why-you-should-be-asking-how-your-passwords-are-stored http://www.warmenhoven.co/2012/03/06/do-not-use-md5-or-sha1-to-simply-hash-db-passwords/ - "(link to program) doeas around 2300.000.000 SHA1 hashes per second and about 5600.000.000 MD5 hashes per second (and these numbers are with 2 year old graphics cards… so that number should have risen to almost double by now" and read about "rainbow tables" – Styx Jun 26 '14 at 18:12
  • Also see Openwall's [PHP password hashing framework](http://www.openwall.com/phpass/) (PHPass). Its portable and hardened against a number of common attacks on user passwords. The guy who wrote the framework (SolarDesigner) is the same guy who wrote [John The Ripper](http://www.openwall.com/john/) and sits as a judge in the [Password Hashing Competition](http://password-hashing.net/). So he knows a thing or two about attacks on passwords. – jww Oct 12 '14 at 01:30

4 Answers4

1

Use sha1 function http://www.php.net/manual/en/function.sha1.php

It's really simple. Pass the password in input parameter then save it in the database.

When you want to check if password is correct you just have to compare the sha1(password) with the stored value.

Example :

$passwordEncrypted = sha1($password)

save $passwordEncrypted in your database

When the user want to login :

check this condition :

if (sha1($password) ==$passwordEncrypted )

Here is the complete code :

$username = $_POST['username'];

$password = $_POST['password'];
$passwordEncrypted = sha1($password) 

    try {   

        $result = $db->prepare("INSERT INTO 
                                user_info 
                                SET 
                                username = :user,
                                pass = :pass
                                ");
        $result->bindParam(':user', $username);
        $result->bindParam(':pass', $passwordEncrypted);
        $result->execute();
    }

    catch (Exception $e) {
        echo "Could not create username";
    }

    if (isset($_POST['submit'])) { 
        foreach ($_POST as $field) {
            if (empty($field)) {
                $fail = true;
            }
            else {
                $continue = false;
            }
        }
        if ($field == $fail) {
            echo "You must enter a username and/or password";
        }
        else {
            echo "Your account has been successfully created.";
        }
         }
geekInside
  • 588
  • 2
  • 8
  • 18
  • Thanks for both the explanation and updated code. Is there any significant negatives to using this method over other methods? I guess i should research sha1, but it has been a long day! – Nikki Mather Jun 25 '14 at 22:39
  • 1
    Someone above provided a link to a SO post, they explicitly state; `Never hash passwords with SHA1 or MD5 or even SHA256! Modern crackers can exceed 60 and 180 billion hashes/second (respectively).` - What is their reasoning for this? – Nikki Mather Jun 25 '14 at 22:42
  • don't use sha1. http://en.wikipedia.org/wiki/SHA-1 In 2005, cryptanalysts found attacks on SHA-1 suggesting that the algorithm might not be secure enough for ongoing use – mayy00 Jun 25 '14 at 22:42
  • There are lots of algorithm. I think the stronger is sha512 hash('sha512', 'yourpassword'); – geekInside Jun 25 '14 at 22:43
  • @CodePoetry I'm satisfied, assuming the sha1 method is secure. A few people seem to be unsure about this particular method, which is why i'd like a little clarification is you know about the specifics of the security of this particular method. – Nikki Mather Jun 25 '14 at 22:49
  • It depends if you have strong constraint of security ==> SHA-512 If you have strong constraints of performance prefer SHA1 – geekInside Jun 25 '14 at 22:59
  • I was wondering if you could take at the login logic i've updated above in my post and let me know what's wrong. I couldn't seem to get your code to work; what i did was store it as a session variable so i could access it from inside that logic file - perhaps not a good idea? Note: i reverted my "guess" to how i had it prior. – Nikki Mather Jun 25 '14 at 23:07
  • @CodePoetry - Fast hash algorithms like SHA* are indeed not appropriate to hash passwords, because they make brute-forcing easier. Instead one should choose an algorithm with a cost factor (like BCrypt or PBKDF2) that controls the necessary time to calculate a single hash-value. – martinstoeckli Jun 26 '14 at 07:48
0

Look at this question:

https://stackoverflow.com/questions/3897434/password-security-sha1-sha256-or-sha512

You can use hash function http://www.php.net/manual/en/function.hash.php

Community
  • 1
  • 1
mayy00
  • 224
  • 5
  • 14
  • Thanks. I'm curious, just how secure is this method? – Nikki Mather Jun 25 '14 at 22:39
  • @mayy00 - Fast hash algorithms are not appropriate for hashing passwords. Instead one should choose an algorithm with a cost factor that controls the necessary time to calculate a single hash-value. – martinstoeckli Jun 26 '14 at 07:13
0

Use salt and sha256 encryption algorithm

<?php
// create user
$password = $_POST['password'];
$salt = mcrypt_create_iv(22, MCRYPT_DEV_URANDOM);
$pass = hash("sha256", $salt.$password.$salt);
// save salt and password hash into database

// to validate user
// 1 - get salt and password hash from database
// 2 - prepend and append salt to the posted password
// 3 - encrypt with the same algorithm
// 4 - compare with stored password hash. 
joaofgf
  • 318
  • 1
  • 6
0

With password_hash() you are on the right track. For PHP versions 5.3.7 - 5.5 you can use the compatibility pack, later when you switch to a newer PHP version, you can simply remove this php file from your project and the code will still run.

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

Even for lower PHP versions than 5.3.7 you can use the compatibility pack‌​. You only have to edit line 55 and change the algorithm from sprintf("$2y$%02d$", $cost); to sprintf("$2a$%02d$", $cost);. This is of course not optimal, but it is the best you can do for PHP between 5.3 and 5.3.7.

The problem with other algorithms like SHA* or MD5 is, that they are ways too fast. It is possible to calculate about 3 Giga SHA-1 per second with common hardware, that makes brute-forcing too easy. To test a whole english dictionary you would need only a fraction of a millisecond. That's why one should use a hash algorithm with a cost factor like BCrypt or PBKDF2, they allow to control the necessary time to calculate a single hash.

martinstoeckli
  • 23,430
  • 6
  • 56
  • 87