3

I have a simple registration script done in php and I was just curious if the way I am doing it is secure enough to store user passwords. I am generating a 32bit random salt and appending it to an sha1 hashed password.

//create new validator object
    $validator = new data_validation();
    //validate user input
    $firstName = $validator->validate_fname($firstName); //is the first name a string?
    $lastName = $validator->validate_lname($lastName); // is the last name a string?
    $username = $validator->validate_username($username); // is the username a string?
    $email = $validator->validate_email($email); //is the email in valid format?

    //make sure there isn't duplicate emails
    $valQuery = $link->query("SELECT email FROM users WHERE email = '" .$email. "'");

    if ($valQuery->num_rows == 1) {
        echo "An email is already registered with that address";
        return false;
    }

    // generate a random salt for converting passwords into sha1
    $salt = $link->real_escape_string(bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)));
    $saltedPW =  $password . $salt;
    $hashedPW = sha1($saltedPW);

    mysqli_connect($db_host, $db_user, $db_pass) OR DIE (mysqli_error());
    // select the db
    mysqli_select_db ($link, $db_name) OR DIE ("Unable to select db".mysqli_error($db_name));

     // our sql query
    $sql = "INSERT INTO users (first_name, last_name, username, email, password, salt) VALUES ('$firstName', '$lastName', '$username', '$email', '$hashedPW', '$salt');";

    //save the updated information to the database          
    $result = mysqli_query($link, $sql) or die("Error in Query: " . mysqli_error($link));

    if (!mysqli_error($link)) 
    {
        $row = mysqli_fetch_assoc($result);
        $_SESSION['user_id'] = $row['user_id'];
        $_SESSION['loggedin'] = TRUE;
        header("Location: ../home");
    }

Also, I am using a combination of procedural and oop php. Most of it is done in procedural, but there are a few oop classes such as the validation class you see used in the above script. Will this cause any performance issues using both styles?

Ty Bailey
  • 2,392
  • 11
  • 46
  • 79
  • possible duplicate of [Secure hash and salt for PHP passwords](http://stackoverflow.com/questions/401656/secure-hash-and-salt-for-php-passwords) – Brendan Long Oct 29 '12 at 02:41
  • Not a duplicate at all. I don't see anything even similar to my script or question? And I guess I'm just trying to get an opinion if this script would be secure enough to store user passwords at a massive scale? – Ty Bailey Oct 29 '12 at 02:43
  • @TyBailey Your question is just a specific case of that one -- how to securely hash passwords in PHP. The answers on that question apply to yours as well (no, your method is not secure). – Brendan Long Oct 29 '12 at 02:48
  • That's all you had to say. No need to accuse me of post a duplicate question. I appreciate your answer below, but just because some questions are asked similarly does not mean they are duplicate. The question you directed to is full of useful information, but it does not answer my question. You however, did. So thank you. – Ty Bailey Oct 29 '12 at 02:53

2 Answers2

6

No. Stop what you're doing, read How to securely hash passwords, then read Secure hash and salt for PHP passwords:

Most importantly:

  • Use scrypt when you can; bcrypt if you cannot.
  • Use PBKDF2 if you cannot use either bcrypt or scrypt.

See this answer for a comparison of PBKDF2, bcrypt and scrypt.

Also refer to the often-linked article How To Safely Store A Password:

[MD5, SHA1, SHA256, SHA512, SHA-3, etc] are all general purpose hash functions, designed to calculate a digest of huge amounts of data in as short a time as possible. This means that they are fantastic for ensuring the integrity of data and utterly rubbish for storing passwords.

PHPass is probably the easiest way to do bcrypt hashing in PHP. You can also do it the hard way using the crypt function and CRYPT_BLOWFISH if you want, but be aware that there's a lot of ways to get it wrong, and the interface is fairly arcane (like how you specify salt values).

Community
  • 1
  • 1
Brendan Long
  • 53,280
  • 21
  • 146
  • 188
  • Thank you for the tips! -- Can you possibly explain the difference between bcrypt and scrypt and why scrypt is safer? I read some of the information you directed me to, but neither of them offer a comparison of the two. – Ty Bailey Oct 29 '12 at 02:45
  • 1
    @TyBailey There's some good explanation on [this question I asked a while ago](http://security.stackexchange.com/a/5639/1983). The short version is that there's these three major key derivation functions: PKBDF2 uses a variable amount of processor time by letting you tune how many iterations of the hash function to run, but it's easy to implement in hardware (which is bad). bcrypt also makes processor time controllable, but is relatively expensive to implement in hardware. scrypt has variable CPU time and memory requirements, and memory is *really* expensive in hardware implementations. – Brendan Long Oct 29 '12 at 02:57
  • 1
    Also, PBKDF2 is an [IETF standard](https://tools.ietf.org/html/rfc2898), which can matter in some situations (if you're required to use it). Both PBKDF2 and bcrypt are around 12 years old I think, while scrypt is only a couple years ago. In security, older is better (mainly because it's the only proof we have that a function isn't trivial to break). It's also much easier to find implementations of PBKDF2 and bcrypt, since they're so old. – Brendan Long Oct 29 '12 at 03:01
2

Switching between procedural and OO in itself will not affect performance. The overhead of loading and instantiating classes is negligable. However, the managing a non-OO codebase that grow can be a non-negligible task--especially juggling everything in global namespace.

Adding an additional field to your insert (the salt) also will not affect anything. Using the salt does not add overhead to the sha1 algorithm by tacking it to the end of the password.

I am a little confused at how you choose to generate the random salt, but it doesn't look very system intensive either.

Ray
  • 40,256
  • 21
  • 101
  • 138
  • then what does the salt do exactly? It generates a random salt per password, appends it to the password then sha1's the password with the generated salt attached. Are you saying I don't need to store it in the db? – Ty Bailey Oct 29 '12 at 02:49
  • No, its fine to generate and store (you'll need it to decrypt), but I find the way your doing it to be interestig. – Ray Oct 29 '12 at 02:51