Going straightly to my question, I have read about encrypting password while registering the user.Till here im able to register users with encrypted password by using PASSWORD('$PASS'); where $PASS is the users password. My sql table details is as follows :-
FNAME
LNAME
EMAIL
PASS // USED ENCRYPTION AS PASSWORD('$PASS'); HERE.
I can't understand how to decrypt the password & use futher in my code i use the following code to use decrypt the password but its not working. !
<?php
$EMAIL = $_POST['email'];
$PASS = $_POST['pass'];
mysql_connect('host', 'user', 'pass');
mysql_select_db('userdb');
$results = mysql_query(sprintf("SELECT FNAME,LNAME,EMAIL,PASS FROM `details`
WHERE PASS=PASSWORD('$PASS')",
mysql_real_escape_string($EMAIL))) or die(mysql_error());
while($row = mysql_fetch_assoc($results))
{$rows[1] = $row;}
if(!($_COOKIE['pass'] == $rows[1][PASS]))
//cookie is set while registering user , which is the decrypted(original) value of password.
{ die("Error occured"); }
else { echo "Password entered is correct"; }
////.....my further code here.
?>
Its showing Error occured on the page, which means the password is incorrect. I Also add that this code was working correctly before encryption of password in database.Im new to encryption process ,Your little help is needed which will help me to learn more. Thanks in advance.
You don't encrypt passwords, you hash them.
The point is, that you don't actually need the users password, you just need to know that they know it.
As an example, an absolutely terrible way to do that might be a simple count: e.g.
if the users password was 'horse123', you might store that as 8. Then you just count the letters in the password, and if it's 8, you know it's right.
That means that you never need to know the actual password.
Clearly that's awful, as there are many passwords with 8 characters! We need something with less 'collisions'.
Instead, we use one way hash functions. The most common way to do this is to use an MD5 hash. (it's not the best, but it's simple to explain). For how to actually do this, look at http://www.openwall.com/phpass/.
For the short and sweet version:
Get the users password, and do something like:
$pass = md5('somerandomtextthatyouknow'.$_POST['password']);
then, store that in your DB.
When they log in, you do the same again, and check that the hash in your DB.
This way, you never need to know the actual passwords, the passwords can be as long as you like, and if your database is stolen, the hashes are not useful to anyone (because we added in that random text).
So, now you understand that, read:
http://www.openwall.com/phpass/
and absolutely read up on SQL injection and SQL prepared statements, else this is all a bit pointless!
You shouldn't encrypt passwords. You should hash them. This way they can't be decrypted.
You can read more about it here.
Best solution is to use HASH code instead of using encryption and decryption.
md5($pass) - give you 32 bits unique hash code
similarly sha256(), hash()...etc
store these hash codes in your database at the place of password.
Hash code are one way. So it is more secure for your users.
Click here for a more comprehensive way of protecting your passwords and login access using PHP and MYSQL
Related
This question already has answers here:
Using PHP 5.5's password_hash and password_verify function
(4 answers)
How to use PHP's password_hash to hash and verify passwords
(5 answers)
How can bcrypt have built-in salts?
(5 answers)
Closed 5 years ago.
Cryptography
Recently I have been doing a lot of research into cryptography. It led me to discovering that, not only do we have salt, we also have pepper (yes I really only just found out about pepper).
Hashing passwords
This all started when I inherited a project in which passwords were not hashed. Even as a n00b I know that this is just silly.
I have a basic understanding of hashing, but what I knew was apparently outdated.
Original solution
My original hashes and salts were achieved by:
Getting the user's password
Combining it with a salt
Hashing it using MD5
Storing both, the salt and the hash in a table
This worked well, but I am leaning towards using a better technique
New technique
The new way I wish to try is by using PHP's password_hash and password_verify.
Having created a quick test, I can see that I can return a true value with password_verify on a given hash. The one thing that is puzzling me is where the salt comes in?
On the documentation I can see that there was an option to specify a salt in the options array but that is deprecated as of PHP 7.0.
My attempt
I have created some code (untested) just to demonstrate. See below code.
<?php
$pepper = "myPepper";
function register($username, $password)
{
// add the pepper
$password .= $pepper;
// hash the password
$hash = password_hash($password, PASSWORD_BCRYPT, ["cost" => 10]);
// insert into table
$query = $mysqli->prepare("INSERT INTO users(username, password) VALUES(?, ?)");
$query->bind_param("ss", $username, $hash);
// check the success
if ($query->execute())
return true;
else
return false;
}
function login($username, $password)
{
// create the query
$query = $mysqli->prepare("SELECT password FROM users WHERE username = ?");
$query->bind_param("s", $username);
// check if successful
if ($query->execute())
{
// get password from the database
$query->store_result();
$query->bind_result($hash);
$query->fetch();
// verify the passwords are the same
if (password_verify($password . $pepper, $hash))
return true;
else
return false;
}
}
?>
register function
Both these functions are very basic as I just wanted to show a point.
This function takes some parameters (in this case username and password and adds them to the database.
Now, I know how to add my pepper to the password as that is a simple concatenation, but the salt is randomly generated but never returned meaning I have no idea what it is.
login function
Again, very basic in what it does.
Since I have not used password_verify before I am not entirely sure I know the best approach to use to attain the user's password.
With my old login scripts they looked something like this:
function login($username, $password)
{
// create the query
$query = $mysqli->prepare("SELECT salt FROM users WHERE username = ? AND password = ?");
$pass = md5($password);
$query->bind_param("ss", $username, $password);
// check if successful
if ($query->execute())
{
$query->store_result(); // store result to gain access to num_rows
// verify if password and usernames match
if ($query->num_rows == 1)
return true;
else
return false;
}
}
Where I would just hash the password and pass it as a parameter into the SQL query.
With bcrypt I have to withdraw the password from table and then use it in another query. (At least that is what I believe I have to do currently).
Finally, the question part
Disclaimer
I apologise if I offended anyone with my lack of knowledge and / or my poor explanation of my knowledge.
Your help
I crave knowledge. So what I don't know, I want to know. (Obviously to an extent, I like to learn about computers and systems and programming etc).
Password hashing is essential these days and getting it right is very important and that is why I am writing this essay question.
Question(s)
Is my understanding of bcrypt correct?
Does it really not store a salt?
In my basic example of login and register, have I implemented password_hash and password_verify?
Update 1
Following all the comments, I would just like to post this update.
As stated above I like to learn, so when I came across this function it started confusing me because I didn't know what was happening.
I am going to post some examples to try and effectively get my confusion across to everyone.
Let's take this script for example:
<?php
// everything below is hard coded for simplicity (would actually be extracted from a database)
$password = "myPassword"; // the password from the database
$salt = "mySalt"; // I have hard coded this for simplicity
$hash = md5($salt . $password);
// check login status
if (md5($salt . $_POST["password"]) == $hash)
return true;
else
return false;
?>
In this example I understand how the hashing works.
I am storing the password with a salt and hashing it. Then I am checking the posted password with the salt and hashing that. If the two match then I succeed with the login, otherwise the login has failed.
Now, let's take the following example.
<?php
// everything below is hard coded for simplicity (would actually be extracted from a database)
$password = "myPassword"; // the password from the database
$hash = password_hash($password, PASSWORD_BCRYPT, ["cost" => 10]); // salt is taken care of
// check login status
// again I am keeping this so simple (it might not work per se but I just want to learn about the functions)
if (password_verify($_POST["password"], $hash))
return true;
else
return false;
?>
Confusion
I start getting confused when I am running password_verify.
I understand that the salt is taken care of by default in password_hash, but in the first example I know the salt and so I can perform a hash with the posted password to check if they match.
Why, then, does password_verify succeed in verifying the posted password without me having given it the salt?
Surely a salt is designed to make each password unique but somehow password_verify will succeed. I have used var_dump to dump the hash made from password_hash and it changes upon refresh. This really is where the confusion comes from. If the hash of "test" can change to a different hash each refresh, then how does password_verify know the posted password is correct?
I know that I can write a function to verify the user's password. What I really want to know is how can how PHP's password_verify manage to validate to true every time, despite the fact that my hash will change with each refresh.
Note: I understand that I will be storing the password in a database so the refreshing won't be a problem, but I was doing so to try and understand the function.
Comments
#RiggsFolly I know that the salt is done for me. The question is "How does the verify function know the random salt created in the hash function in order to validate to true?"
#RiggsFolly I understand the salt option was deprecated. Had it not been (and I was able to pass it a salt), I think I would understand this function a lot more. The whole idea of the verify function successfully validating a password against a hash without knowing the salt is actually blowing my mind.
Perhaps I am just being stupid.
#Alex Howansky How is the salt returned? A string such as $hash = $2y$10$Vaj4ZonpRJjE6kmfQffvOOeIVW3ZV31JJYVY79GtZ3GtioZKtDwku means nothing, yet somehow password_verify("test", $hash") returns true.
#Machavity Having read the link, I can see that the salt is at the start of the hash, but how can the salt be in the final hash? I apologise for my confusion, and apparent stupidness, but I simply wish to understand password hashing so that I am better prepared for future uses.
#Fred -ii- Those custom function were just simple for the example (I didn't want to link an entire page of code). That being said, my current usage is in a self defined Class called User, where I have a private variable called $conn which stores the mysqli connection. Then from that I use $this->conn->prepare("SELECT * FROM ...") to access the database.
Is that bad for scoping? What is the preferred way to store the connection within a self defined Class?
I am searching the internet for what type of hashing algorithm should I use to store passwords in MySQL database and for sending email confirmation messages with hashed token, the algorithm should include:
1- at least 14 chars random salt (uding udev random)
2-a key that will be stored on the server
3-timestamp
4-a very strong and secure hashing algorithm using the function hash_***(is this the best?)
I haven't found elegent code that workds, could you please show me
Thank you
Follow the examples provided in PHP the Right Way under password hashing:
require 'password.php';
$passwordHash = password_hash('secret-password', PASSWORD_DEFAULT);
if (password_verify('bad-password', $passwordHash)) {
// Correct Password
} else {
// Wrong password
}
DO NOT under any circumstances "invent" your own algorithm. These are notoriously tricky to get right and unless you have a background in cryptography you will almost certainly get it dangerously wrong.
How to decrypt password in plain text which are in ms-SQL database?
$encrypted_password="k??aU?????y-??N???tDRz????{?4R???G?aS4t?T";
$salt = "611233880";
So I need to decrypt password so that I insert into other database with md5 encryption.
I used this code, but not get success
$iv2 = '';
for($i=0;$i<16;$i++){
$iv2 .= "\0";
}
$plain_text_CBC = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $salt, $encrypted_password, MCRYPT_MODE_CBC, $iv2);
var_dump($plain_text_CBC);
$plaintext = openssl_decrypt($encrypted_password, 'AES-256-CBC', $salt, 0, $iv2);
var_dump($plaintext);
Need Help
The idea behind encrypted (or hashed) passwords is that it is a one way operation. Not quite like shredding, but that's the idea. If you take exactly the same input and shred it you should get exactly the same output. You may not be able to reconstruct the input from it, but you can confirm someone gave you the right input by looking at the output.
Some weak algorithms have been know to be hacked buy in principle what you are asking for is impossible.
The ought to be no reason reason to decrypt. You can always do the hashing operation twice - first with the old algorithm, then with the new one - and then compare with the entry in the database.
NEVER EVER store plaintext (or weakly encrypted) passwords. Just ask LinkedIn...
You don't simply decrypt a password. It should be hashed which means it is a one way encryption.
If you want to change your password hashing implementation, here is a way to do it.
You have the clear text password available when a user is in the process of logging in. So that's where you will have to place code to rehash the password with the new algorithm.
If you are using the new native password hashing functions (PHP Version >= 5.5) then you can use password_needs_rehash. If you are on a lower PHP Version but still >= 5.3.7 then you can use the userland implementation to get the same API to the password hashing functions.
So when a user is attempting to log in and the password needs rehashing, check if the hashes match with the old hashing function and then create and save the new one to the database. Over time you will be able to migrate most users and then you can think about a solution to migrate the rest of your userbase with a forced password reset if they never logged in during your migration timeframe.
Firstly, you encrypting your data by 2 different algorithms. Why? One algorithm is enough.
Answer: You can't decrypt old password.
Solution: You should encrypt data you wrote into password field and compare result with data in database. If they are equal, you will pass password check.
For example:
$login = mysqli_real_escape_string($_POST['login']);
$password = mysqli_real_escape_string($_POST['password']);
$password_hash = md5($input); // you can use there any other algorithm, just example
// make next query and control result
$sql = 'select count(id) from users where login = \'$login\' and password = \'$password_hash\'';
// now if there are 1 row with this login and same password hash let user log in to your site
If you write your code in the MVC structure, you can use the function n_decrypt() to decrypt passwords.
So after researching this quite a bit I'd like to know if this is the best practices way of doing it or not.
When I send the user's password to the DB I'm doing this:
// DB input:
$mySalt = time(); // generate random salt such as a timestamp
$password = crypt($_POST['password'], $mySalt);
// submit $password and $mySalt to DB here via PDO
And when I go to check the password at login I'm doing this:
// At login:
// retrieve the password and the salt from the DB
if(crypt($_POST['password'], $saltFromDb) === $passFromDb)
// allow login
Would this be the correct way to do that or am I missing something? Thank you for any advice.
What you need instead is to use the inbuilt salting and hashing functions supplied within crypt. Here is an example using a good hashing algorithm call blowfish (bcrypt): How do you use bcrypt for hashing passwords in PHP?
In this case the slower the algorithm the better.
When getting it from DB you would simply use crypt() to evaluate the entire string to understand if it validates as the correct password etc.
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.