php salt my passwords per user sha512 - am I doing this right?
Asked Answered
T

4

10

I'm trying to correctly do a per user and site wide salt for my passwords. Here's what I've got:

require('../../salt.php'); //this is above the web root and provides $salt variable
$pw = mysql_real_escape_string($_POST['pw']);
$per_user_salt = uniqid(mt_rand());
$site_salt = $salt //from salt.php that was required on first line
$combine = $pw . $per_user_salt . $site_salt;
$pw_to_put_in_db = hash("sha512", $combine);

Is this right? Thanks

Theorist answered 25/6, 2011 at 17:6 Comment(15)
This isn't really an answer to whether you're doing it right. (1) No need to use mysql_real_escape_string. The resultant hash() would change any invalid SQL to a letter/number. (2) Ensure you're storing your $per_user_salt in a safe, secure way to retrieve it when your users are trying to login with their password.Piercing
@Charles Sprayberry, for storing - do I need to do anything different than INSERT INTO users (per_user_salt) VALUES ($per_user_salt) ?Theorist
@Andypandy - Assuming that's the only field you want to save in your users table, almost. Make sure that you wrap $per_user_salt in quotes (single or double) as your hash is a string (i.e. INSERT INTO users (per_user_salt) VALUES ('$per_user_salt').Franke
Why do you store the 'per user salt'? Wouldn't it be better to make an algorithm that depends on data already present in the database, which makes it less obvious which salt was used? It's not a requirement in any way, but it might make your passwords a little more secure.Bradberry
Shouldn't you use mysql_real_escape_string() right before the database query and not at the beginning?Milurd
@manhim, correct me if im wrong, but the only part open to sql injection is the user input for 'pw', my salt and per_user_salt are generated by me... however according to @charles sprayberry, i don't even need to escape the pw there since i'm hashing it... i'm going to leave it because i needed it escaped elsewhere also...Theorist
@kilzone, i'm not sure what you mean - i think it is an algoritham based on data in the db... the data is the per_user_salt and the algorithm is combining salt . pw . per_user_salt then hashing... if you have a better recommendation please let me know... I've never done this before..Theorist
@Andypandy Since you are hashing it you do not need this function. The result is mostly-assured to be alpha-numerals.Milurd
@andy Well for example if you use md5($_POST['pw']) as 'salt' you have a salt that is user depending but does not have to be stored in the database. Your hash would be hash("sha512", $pw . md5($pw) . $site_salt);, which is about as secure as a random generated number (as long as you don't tell anyone your algorithm). The big upside is, that hacking your database (for example using injection) will not result in the per_user_salt being shown, as it is not stored.Bradberry
@kilzone, i see what you're saying - so if I changed my $combine to $combine = $pw . $per_user_salt . $site_salt . $site_salt . $per_user_salt . $pw; that would be more secure...? or is there a simpler way to make it way more secure like $combine = $pw . $per_user_salt . $site_salt . md5($pw);...Theorist
@andy The whole point of the 'salt' is to avoid rainbow tables to be used to de-hash something into a password, so anything you do before hashing makes it more secure. Both options you have are more secure, since the $combine becomes more complex, but I like your last option best. However, in the end it comes down to personal preference. Just remember that your salt-trick is a form of security-through-obscurity, the less people know about how you make your $combine the better. Try to come up with something uncommon, like the two you just posted and you'll be fine.Bradberry
@kilzone, also one more question - what's the best way to secure the algorithm?Theorist
Problem is that PHP does not have a 'compiled' structure for code (unless you use Zend Guard, but that is too expensive), so anyone that accuires access to your PHP server can just read the plain text version of your algorithm. Best practise is not to store your hashing code in your root (preferably the folder above the root and if that's not possible use a subfolder) and don't tell anyone that and how you are salting the passwords.Bradberry
This article might be of interest: codahale.com/how-to-safely-store-a-passwordDaiseydaisi
@Sven, damn I was planning to say that right now!Sarajane
T
-2

Based on comments here is what I'm going to do: Change my $combine to something that is unique per user but not stored in db. So something like: $combine = $pw . md5($pw) . 'PoniesAreMagical' . $site_salt . md5($pw);, etc etc etc... Thanks for the help...

So - for those of you trying to figure out how to do this for the first time (like me)... its all about the algorithm... make something obscure, unique, difficult to figure out; because if someone wants to get into your system, they are going to have to figure this out. Thanks to all for awesome comments.

Theorist answered 1/7, 2011 at 5:13 Comment(2)
i don't think this is the best option, and i disagree with @killzone in the comments to your question. the idea of a salt is to prevent rainbow table attacks with user-unique salts. even with knowledge of your algorithm it should be impossible to create rainbow tables. if you use md5($w) as salt anybody knowing the internals of your algorithm can easily create a rainbowtable for your complete user base — after all he has all the inputs he needs: a password, the hash of the password (easily computed), the "ponies"-constant, and the site-salt. security through obscurity never really works!Earnest
best and simplest is just to create a random salt per user and store it in the db. this way the salt is unique to each user and cannot be derived from other inputs (like the password) — so it does not help the bad guys if they get to know your algorithm usedEarnest
S
0

often people use a unique salt concatenated with the password, then use hmac method to add the sitewide hashing key:

http://www.php.net/manual/en/function.hash-hmac.php

$password = hash_hmac('sha512', $password . $salt, $sitewide_key);
Showy answered 25/6, 2011 at 18:17 Comment(2)
by the way, your unique salt will have to be the same every time you hash the password for comparison. this means you will have to store the unique salt for that user somewhere. sometimes people use a string based on the username for this reason. $salt = substr(md5($username), 1); or whatever depending on your security level. it makes database lookups much easier.Showy
if your algo is going to be public knowledge, a good tip may be to use your sitewide key in the generation of your salt as well. $salt = md5($username . $sitewide_key);Showy
F
0

This is fine just removed "" from "sha512" :)

$pw = $_POST['pw'];
$per_user_salt = uniqid(mt_rand());
$site_salt = $salt //from salt.php that was required on first line
$combine = $pw . $per_user_salt . $site_salt;
$pw_to_put_in_db = hash(sha512, $combine);

dont have to use md5 sha512 is secure enough it self

Freetown answered 8/6, 2013 at 10:56 Comment(0)
C
0

Use crypt, it's available in all languages and your password hashes will be useable by other programs as well:

$hash = crypt("secret", "$6$randomsalt$");
Carrillo answered 13/6, 2013 at 18:12 Comment(0)
T
-2

Based on comments here is what I'm going to do: Change my $combine to something that is unique per user but not stored in db. So something like: $combine = $pw . md5($pw) . 'PoniesAreMagical' . $site_salt . md5($pw);, etc etc etc... Thanks for the help...

So - for those of you trying to figure out how to do this for the first time (like me)... its all about the algorithm... make something obscure, unique, difficult to figure out; because if someone wants to get into your system, they are going to have to figure this out. Thanks to all for awesome comments.

Theorist answered 1/7, 2011 at 5:13 Comment(2)
i don't think this is the best option, and i disagree with @killzone in the comments to your question. the idea of a salt is to prevent rainbow table attacks with user-unique salts. even with knowledge of your algorithm it should be impossible to create rainbow tables. if you use md5($w) as salt anybody knowing the internals of your algorithm can easily create a rainbowtable for your complete user base — after all he has all the inputs he needs: a password, the hash of the password (easily computed), the "ponies"-constant, and the site-salt. security through obscurity never really works!Earnest
best and simplest is just to create a random salt per user and store it in the db. this way the salt is unique to each user and cannot be derived from other inputs (like the password) — so it does not help the bad guys if they get to know your algorithm usedEarnest

© 2022 - 2024 — McMap. All rights reserved.