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
}
}
Related
I'm using the password_hash function to secure the user's password on the login page. However, on the register page I ask the user to prompt his password twice, but I can't compare both hashes cause they are different even if the password is the same.
Should I compare both passwords as strings and then hash the password? or what is the best practice to do it?
The password_hash is used to hash a password, generating a new salt if necessary (you may pass your own salt, but this is not necessary), while the password_verify function is used to compare them (this function uses the salt stored alongside the hash in order to perform the proper comparison).
When creating the passwords, the user provides it twice on plaintext, so all you need to check is $password1 == $password2.
If you wish to verify the password obtained from the database, you need to do:
$password_hash = <some database query>
if (password_verify($password, $password_hash)) {
login_success();
} else {
login_failure();
}
You could compare the passwords in the register page the same way, but there's no need.
You do not have to hash the passwords. They are just strings and can be compared as such:
if ($_POST['password'] !== $_POST['password_verify']) {
die('Passwords are not the same...');
}
You can also hash the real password and then use the password_verify function to make sure it is the same. I do not know why you would do that, but there may be a good reason to:
$hash = password_hash($_POST['password'], PASSWORD_DEFAULT);
$verify = $_POST['password_verify'];
if ( ! password_verify($verify, $hash)) {
die('Passwords are not the same...');
}
Somebody should pls guide me on how i can fetch out hashed password from database and match the password entered by a user when login in
i used php crypt() function with bcrypt algorithms to hash the password when registrian the user
thank you all in advance
From the documentation:
$hashed_password = crypt('mypassword'); // let the salt be automatically generated
if (crypt($user_input, $hashed_password) == $hashed_password) {
echo "Password verified!";
}
You need to pass in the original hash, otherwise crypt will generate a random salt and the passwords are very unlikely to match. I.e.
//BROKEN - will almost always print "Bugger off!".
$hash = crypt('Hello world');
$attempt = crypt('Hello world');
if($hash === $attempt){
echo "Access granted!";
}else{
echo "Bugger off!";
}
You don't need to "fetch" the hash from the database, you just hash the given password (from a login attempt I assume) and match THAT hash against the password column of a database. if a match is found where the password column matches the hash that you just made AND the username is a match, then the password is valid.
Thank you all, if i really get your explanations you mean i should hash the coming password from a user attempting to login and then compare the hash value with the one in DB
EXAMple
$salt=//the bcrypt algorithms format, cost parameter and the salt goes here, thesame with the one use when registrian
$coming_pass= crypt( $password, $salt)
mysqli_query ( SELECT from user WHERE username= $username AND
password= $coming_pass)
you just send the unencrypted password into the same crypt process as you did with the encrypted password, then they should match.
PHP has built in Options to do that, look at Creating a Hash, and Verifying a Hash
pseudo-code
hashed password = hp
plain text password = p
seed (Random Number generated by server) = s
hash algorithm (md5, sha1, sha256, ...) = hash
Example with Seeded Hash
hp = hash(p + s)
the order you set the seed is not important, as long you do it the same way every time, by Concatenate the password and seed
Example without Seeded Hash
hp = hash(p)
you will need to save the hp and seed, the p should NEVER be saved by the server, as Plain Text Passwords is a security issue.
C# Code Example:
static public bool IsPasswordCorrect(string hp, string seed, string enteredPasword)
{
return (hp == Sha1(String.Concat(enteredPasword, seed)));
}
this way you have no direct way to get the password from the database, and only the actual Client will have the Plaintext Password.
if you want a 2-way encryption algorithm, you will need to look at RSA, but it is way more complicated and requires a lot of knowledge to make secure.
Is there a way to compare passwords stored in database after being encrypted in sha2() and the password entered by users during login without encrypting the login-time-password? Actually I want to match the passwords character by character and pass for a match in either of upper case or lower case i.e. in other words is there a function or method to de-crypt the saved password before comparison?
What you want to do sounds fishy.
Anyway no you can't recover a hashed string
You can't "decrypt" a SHA hash. Instead, compare the SHA version of the entered password with the stored passwords in the database (also hashed).
$enteredpass = $_POST['password'];
$enteredpass = sha2($enteredpass);
$realpass = sha2('password123'); //Yup, best password EVAR!! xD
if ($enteredpass == $realpass) {
echo "THE PASSWORD IS CORRECT!! :D";
}
else {
echo "THE PASSWORD IS INCORRECT!!";
}
You probably want to use a database, but this is just a simple example... ;)
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.
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.