What is best for storing passwords? Should I be Encrypting or hashing password for you users table ?
What do you prefer, and why? Could you please provide an example of secure password storage.
Considering passwords generally don't have to be checked / hashed / whatever that often (they are when one is logging in, and registrering ; but that's pretty much it), speed is generaly not much of a concern : what matters is security.
What's generally done is :
when a user registers, he types his (new) password)
that password is salted + hashed, and the result is stored in database
Then, when a user wants to log-in, he types his password
What is typed is salted + hashed, and compared to the value stored in the database.
The main key is : never store the real password in the DB -- only a hash of it ; and salt it before hand, to avoid attacks by rainbow-tables.
And it seems this is already what you're doing -- so good point for you ;-)
Which hashing function should be used ? Well, sha1 is often considered as OK ; md5 is less OK now ; sha512 should be more than OK, I guess.
I'd do this usually:
<?php
function createHash($pwd, $salt = ''){
$hash = '';
if(!$salt){
$salt = hash('sha256',mt_rand().time().$pwd.'2130A');
}
if($pwd[0] & 0){
if($pwd[strlen($pwd)-1] & 1){
$hash = hash('sha256', $pwd.$salt).$salt;
}else{
$hash = $salt.hash('sha256', $pwd.$salt);
}
}else{
if($pwd[strlen($pwd)-1] & 1){
$hash = $salt.hash('sha256',$salt.$pwd);
}else{
$hash = hash('sha256', $salt.$pwd).$salt;
}
}
return $hash;
}
function getSalt($pwdHash){
if($pwd[0] & 0){
if($pwd[strlen($pwd)-1] & 1){
$salt = substr($pwdHash,64);
}else{
$salt = substr($pwdHash,0,64);
}
}else{
if($pwd[strlen($pwd)-1] & 1){
$salt = substr($pwdHash,0,64);
}else{
$salt = substr($pwdHash,64);
}
}
return $salt;
}
var_dump(createHash('testPassword',getSalt($pwdHashFromDb)) == $pwdHashFromDb); // true
Salting provides higher security than a usual hash.
The salt position depends on the entered password, and thus this makes the salt less vulnerable to be captured.
Raw password is never known or stored
balance between security and speed (for websites).
Hashing rather than encrypting passwords can help protect you against insider threats. Since the hash is a one-way process, for the most part users' stored, hashed passwords should not be decipherable. Rather, you can only run newly-inputted password attempts through the same has to see if the result is the same.
If you store encrypted passwords I would think that would imply that they could also be decrypted, which might be problematic if you have an untrustworthy insider.
This might be a good answer to the interview question, "How can you stop your DBA from making off with a list of your users’ passwords?"
I have posted a question here https://stackoverflow.com/questions/10308694/what-is-the-right-method-for-encoding-hashed-passwords-for-storage-in-ravendb with some sample code. Though the question itself might prove to be boneheaded, perhaps the code sample can be useful to you, if the c# code is intelligible.
Related
This is my password encrypting code :
// Create a 256 bit (64 characters) long random salt
// Let's add 'something random' and the username
// to the salt as well for added security
$salt = hash('sha256', uniqid(mt_rand(), true) . 'something random' . strtolower($username));
// Prefix the password with the salt
$hash = $salt . $password;
// Hash the salted password a bunch of times
for ( $i = 0; $i < 100000; $i ++ )
{
$hash = hash('sha256', $hash);
}
// Prefix the hash with the salt so we can find it back later
$hash = $salt . $hash;
I lost the tutorial site. Do anyone know how to decrypt this encryption. Thank you very much. Appreciate your help
There is no *de*cryption algorithm because there's no *en*cryption algorithm. What you're doing is a hash, which is a non-reversible operation. And that's exactly the point, you do not want to store anything that would even allow you the chance of knowing what the actual secret password is.
A hashing function is not the same thing as encryption. Check the Wiki on hashing. Bottom line is: a hash is a one way algorithm. You can't decrypt it in one go. You could brute-force it, but (especially with sha256) that would take ages. If you were to have a machine, dedicated to cracking a sha256 hash, it'd take ~= 10^64 years!. If 10^64 is meaningless, here's the number in full:
100.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000
And even then, there's no guarantee the result will be right: you could end up with a hash collision (google it). If you do: cheer up, you'd be the first, AFAIK.
For more on encryption vs hashing, refer to this answer to a previous SO question
So the answer is: You can't decrypt (or rather de-hash) what you have.
I'm trying to transition to Blowfish for an authentication system. Bear with me, I'm not a cryptographer and my understanding of Blowfish is not quite there yet.
The current setup uses sha1 and salts. The salts are generated for each user and stored in the database. It boils down to this:
$salt = $this->getSalt($username);
$hash = sha1($password . $salt);
if ($hash == $hashInDB)
{
// user is authenticated, set session id etc ...
}
The getSalt() method gets the salt stored in the database for the specified user.
Now if I understand everything correctly, with crypt I should be doing:
$salt = '$2a$07$' . $this->getSalt($username) . '$';
$hash = crypt($password, $salt);
if ($hash == crypt($password, $saltInDB))
{
// The user is authenticated, set session id etc..
}
To clarify, for the second example the $saltInDB variable, is a value like `'$2a$07$arandomsaltcreatedatregistration$'.
Am I doing it right?
Your example is almost correct.
When you create a hash with the crypt() function, you will see that the used parameters (algorithm, cost and salt) are part of the generated hash (the begin of the hash):
$2a$07$LCzy1mE0b9lS8Uyx9HEeUgHm8zH1iDDZ5...
That means, you can replace $saltInDB with $hashInDB, the crypt() function will extract the needed parameters automatically from $hashInDB. This also answers your question about storing the salt, just store the hash value in the database, the salt is included there. And yes you should generate a new salt for each password.
The '$' after the salt is not needed.
More information about how to generate a bcrypt-hash you can find here, if you are looking for a well established library, i can recommend phpass.
I'd like to use Portable PHP password hashing framework to hash passwords. But I find that its demos don't use salt for hashing a password. But it use a dummy salt for checking password which I find it strange and I don't understand this idea at all,
$dummy_salt = '$2a$08$1234567890123456789012';
if (isset($dummy_salt) && strlen($hash) < 20)
$hash = $dummy_salt;
I wonder, if I want to use convention method which I can generate the unique salt and store it for each user in my database, how can I use Portable PHP password hashing framework to generate salts?
This is the function I use to hash passwords but I have been told that sha512 has the same issue as sha1, wise to trust the expert like Portable PHP password hashing framework,
function hash_sha512($phrase,&$salt = null)
{
//$pepper = '!##$%^&*()_+=-{}][;";/?<>.,';
if ($salt == '')
{
$salt = substr(hash('sha512',uniqid(rand(), true).PEPPER_KEY.microtime()), 0, SALT_LENGTH);
}
else
{
$salt = substr($salt, 0, SALT_LENGTH);
}
return hash('sha512',$salt.PEPPER_KEY.$phrase);
}
Let me know if you have any idea. Thanks.
From the phpass article linked to from that page:
Besides the actual hashing, phpass
transparently generates random salts
when a new password or passphrase is
hashed, and it encodes the hash type,
the salt, and the password stretching
iteration count into the "hash
encoding string" that it returns. When
phpass authenticates a password or
passphrase against a stored hash, it
similarly transparently extracts and
uses the hash type identifier, the
salt, and the iteration count out of
the "hash encoding string". Thus, you
do not need to bother with salting and
stretching on your own - phpass takes
care of these for you.
...so it's not surprising that the examples don't use salting! You may be over-seasoning your code.
The code sample with the dummy salt is an example of how to prevent a timing attack by making sure that whether a user exists or not, the validation of the user takes the same amount of time, effectively by doing a dummy authentication for non-existent users. It needs a dummy salt because if the user doesn't exist, it won't have a stored salt to use.
I have a password being passed from my iPhone app to the database via a php script, user.php.
The variable $pass is populated by the following:
$pass = str_replace("'", "", $_REQUEST['pass']);
How can I encrypt this before it's inserted into my database? I've read a little about the different techniques, but looking for the best way to manage this.
Thanks to everyone.
While the answer below is technically still correct, php has new recommendations with regards to the hashing algorithms to use. Their recommendation, as of php >= 5.5.0, is to use the password_hash and password_verify functions to hash and verify hashed passwords . As an added benefit, these functions automatically include an individualized salt as part of the returned hash, so you don't need to worry about that explicitly.
If you don't care about retrieving the actual password's value (from the database encrypted value), you can run a one-way hash algorithm on it (such as sha1). This function will return a specific length string (hash) which cannot be used to find the original string (theoretically). It is possible that two different strings could create the same hash (called a collision) but this shouldn't be a problem with passwords.
Example:
$pass = sha1($_REQUEST['pass']);
One thing, to make it a little more secure is to add a salt to the hash and run the hash function again. This makes it more difficult to generate a password hash maliciously since the salt value is handled server-side only.
Example:
$pass = sha1(sha1($_REQUEST['pass']).sha1("mySalt#$#(%"));
Use php's crypt library. Md5 is not encryption, it is hashing.
Also, salt your passwords. Why?
This answer
Another good answer
First, you should create a random user salt. Then you should store that and the password hash in the database.
$salt = md5(unique_id().mt_rand().microtime());
$pass = sha1($salt.$_REQUEST['pass']);
and save the $salt and $pass in the database. Then when they go to login you look up their row and check the hash:
$user = query('SELECT * FROM `user` WHERE username = ?', array($_REQUEST['username']));
if($user)
{
// If the password they give maches
if($user->pass === sha1($user->salt. $_REQUEST['pass']))
{
// login
}
else
{
// bad password
}
}
else
{
// user not found
}
Creating a user salt for each account insures rainbow tables are useless and anyone that broken into your server would have to brute-force each password.
Use crypt with some salt. Such as
$user = strip_tags(substr($_REQUEST['user'],0,32));
$plain_pw = strip_tags(substr($_REQUEST['pass'],0,32));
$password = crypt(md5($plain_pw),md5($user));
as on http://www.ibm.com/developerworks/opensource/library/os-php-encrypt/
Most basic: Hash it with MD5 or SHA1
$newpass = md5($_REQUEST['pass']);
or
$newpass = sha1($_REQUEST['pass']);
Recently I started storing the username hashed as well, so login attempts are secure using only hashed data for comparisons.
You can "salt" the hashes with extra data so if they are compromised, it's value cannot be found (try googling some simple hashed words).. i.e. use a site-wide string just to alter the standard hash like md5("mySiteSalt!!" . $_REQUEST['pass']); or something more advanced.
You should use SHA1 to hash your passwords for storage in the database. It's the simplest, yet most effective way to store passwords:
$password = sha1($password);
It's also exceptionally safe. Though the integrity of it is beginning to creep, it's rather easy to upgrade this function to SHA-256 (which is incredibly secure).
To find out why md5, sha1 and their speedy friends might not be a good idea, you should read the post Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes by Thomas Ptacek. The gist:
Finally, we learned that if we want to
store passwords securely we have three
reasonable options: PHK’s MD5 scheme,
Provos-Maziere’s Bcrypt scheme, and
SRP. We learned that the correct
choice is Bcrypt.
Note: it's PHK, not php.
I have to save the Users Email-passwords in my system ( php + mysql ).
I do it now this way:
alt text http://codecookie.net/showcase/cred_save.png
Is this secure? And when not what is a better way to do it?
Salted hashes are one of the better ways of dealing with 'storing' passwords (you're not really storing it as such). Note that the password is unrecoverable, so your app should cater for this by having a 'reset password' function.
I'd recommand to use hmac with a random, long generated salt. The salt helps user who uses passwords like "a" and hmac prevents length-extension attacks.
Sounds good to me :) Since you don't store the actual password but a salted hash this approach should be secure.
only store the hashed salted password. this is essentially the only really secure way, in my opinion. encrypted passwords can be decrypted, hashed salted passwords need to be brute-forced.
function salt_password($password)
{
$salt_1 = '7a##!P^#29g';
$salt_2 = 'mw3*#~2%21mD';
//whatever random nonesense you can come up with
return sha1($salt_1.$password.$salt_2);
}
function store_password($user,$password)
{
$password = salt_password($password);
//insert username and password in whatever table;
}
function login($user,$password)
{
//select username and password info from db
if(salt_password($password) == $selected_password_from_db))
{
return true;
}
else
{
return false
}
}