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.
Related
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.
I've been inserting my password in my database with this POST
$txtPass = md5($_POST['txtPass']);
How could I then reverse this hash and turn the stored value in to a normal string?
You can't. Hashing algorithms are one way. That means you cannot "undo" them. What you can do is compare a hashed value to them to see if they match.
if ($hashed_value === md5('some string')) {
//they match
As others have mentioned, a hash is (or should be) a one-way encryption method. However, with the evolution of lookup tables, storing hashes isn't as secure as it once was.
However, one way to make it a little better is to use a salt when you encrypt the password. For example:
$salt = "!##$%^&";
// registration
$password = "letmein";
$dbPassword = md5($salt . $password); // f5eb04f754cff9cd2a4acae54f84dd90
// When they go to login:
$password = $_POST['password'];
$usrPassword = md5($salt . $password);
Then, even if they get the hash through a security hole it'll always have a salted prefix making it (almost never) match the actual hash in the database. So, using the example:
$password = $_POST['password']; // "!##$%^&letmein"
$pwWithSalt = $salt . $password; // "!##$%^&!##$%^&letmein"
Granted, this is a simple example (and you wouldn't make the salt that obvious) however you can at least add another level of complexity which makes the look-up table a little less effective.
I should also mention that crypt has this built-in and may be a better solution than md5
There is no PHP function to "decode" a MD5 hash. If you are really trying to find out the hash's original string then you could use rainbow tables.
These enable you to lookup a known hash's original value. But there is no guarantee that you will be able to find the one you are looking for in any reasonable amount of time, or at all.
I am developing a system using Codeigniter!
All I wanted to know is if it would be possible for someone to find out what the password is if he/she knows the function and steps I have used to generate the encrypted hash?
For now all I have to generate my hash strings is:
$pass = str_split($password, 2);
$hashPass = '';
foreach($pass as $p){
$hashPass .= md5($p);
}
Your hash method is not hash and its very bad idea.. You must hash your password strings!
Here is 2 pretty simple functions for that..
function hash_my_pass($password){
return generate_hash($password);
}
function generate_hash($password){
return hash('sha256', $password . substr($password, 1, 3));
# In this case I put to hash $password + some substr of the password..
# Its good when you hash pass to add something secret..
}
function check_password($password, $hashed_pass){
return generate_hash($password) == $hashed_pass;
}
$password = '123456789';
$hash = hash_my_pass($password);
echo $hash;#this hash you must keep at your DB.
#when user login just compare his pass with the hash from your DB
var_dump(check_password($password, $hash));
Honestly if you are not using Bcrypt in the year 2013 then passwords will be vulnerable. What you have going at the moment is quite low grade if any grade at that matter in terms of "encryption".
I use CodeIgniter with Bcrypt with this class
Then all you have to do is call this file bcrypt.php and then the class name is :
class Bcrypt extends CI_Controller {............}
Keep in mind though with php 5.5 > the new password hashing functions will be supported which will automatically use Bcrypt until a stronger method comes out. Info here
Good luck and at the end of the day stop trying to roll your own "encryption/hashing" algorithms / methods / disasters. Doing so might leave your clients vulnerable.
If they know the actual method of encryption, they have an easiert time hacking it.
For all hashes there exist rainbow tables for instance, which allow for fast reverting of passwords. That's why hashed password usually get salted.
str_split on the other hand is not a hash function, as far as i know.
look at Ion_auth http://benedmunds.com/ion_auth/ and use the bcrypt option - password hashing isn't something to try to create yourself.
i'm testing several combinations of sha1 and md5:
<?php
$test = 'fail test';
echo nl2br ("Text: $test\n");
echo nl2br ("md5: ".md5($test)."\nsha1: ".sha1($test)."\nsha1(md5): ".sha1(md5($test))."\nmd5(sha1): ".md5(sha1($test)));
?>
Output:
Text: fail test
md5: 748410d0085967c496d54dd8fcbecc96
sha1: d730125e8cb8576459173655148fb6896ef44c09
sha1(md5): faa3ebeecfec45e509e93e6b245a69e2a78785ea
md5(sha1): b48e89b85c350c91eb302c1de96d4249
Which one better, or maybe user something else ? If yes, what then ?
Both of them are cryptographic hash functions that operate 1-way only, the main difference being that MD5 output size is 128 bits whereas SHA-1 is 160 bits. In brief, I don't see they are much different to use despite MD5 is more common these days.
Curiously, I can't really see how md5($text) is different from md5(sha($text)) when they all encrypted to a 32 character-long string, what about md5($text."token") for example?
And, what do you mean by better? Is it more good looking or more security? See bcrypt if you prefer security :) Wikipedia: http://en.wikipedia.org/wiki/Bcrypt
Hashing a hash adds no extra security. (In fact, it might make it worse if the person has a hash-of-hash lookup table.)
The best hash will be the one that is computationally the most expensive to perform without any vulnerabilities. I would hash passwords with at least sha-256.
Always hash your passwords with a salted key. This key should be unique per password. It doesn't need to be stored privately. The purpose of a salted password is that the hacker who gained access to your database cannot simply compare the hash with a known list of hashes that correspond to common passwords. Instead, he must try to brute force the password by trying every possible password.
By using a unique salt per password, you guarantee that each hash in the database is different, even if they use the same password.
To salt a password, simply create a random string of characters and append it to the password. Here's a sample hash with a 48-bit salt and sha-256:
function make_password($password)
{
# random 48-bit salt (8 chars when base64 encoded)
$salt = base64_encode(pack('S3', mt_rand(0,0xffff), mt_rand(0,0xffff), mt_rand(0, 0xffff)));
return $salt.hash('sha256', $salt.$password);
}
function check_password($password, $hash)
{
$salt = substr($hash, 0, 8);
return hash('sha256', $salt.$password) == substr($hash, 8);
}
$password = 'password';
$hash = make_password('password');
echo $hash."\n";
var_dump(check_password('password', $hash));
var_dump(check_password('wrong', $hash));
Every time you run it, the hash will be different. To validate a password, you select the row where the username matches, and then call check_password($password_from_user, $hash_from_db).
Here's a sample output:
AzrD1jZzc693714a43ad5dfd4106c0a620ef23ff9915070711fa170a6670b8164862b496
bool(true)
bool(false)
You can use a larger salt or a stronger hashing algorithm if you prefer. But at minimum, I would use something like the above.
You should salt your passwords, ALWAYS. This doesn't stop brute force through a login form but if someone managed to get the details, it would be much harder to crack (rainbow tables would be useless unless they manage to get your salt too)
Essentially, if you adding onto the original data or mangling in a controlled way, it will make security a little better. No-one can ever reverse a hash but they can find other inputs thats match the hash. Mangling the user input will make it harder to login for the hackers.
for example, if a user's pass is 123456, if you add a salt of "salt" to it so it becomes 123456salt, the MD5 of this would be 207acd61a3c1bd506d7e9a4535359f8a. A hacker could crack this to become 123456salt but when it comes to using that on your login form, your code will add salt again and the login will fail.
How much more safe is this than plain MD5? I've just started looking into password security. I'm pretty new to PHP.
$salt = 'csdnfgksdgojnmfnb';
$password = md5($salt.$_POST['password']);
$result = mysql_query("SELECT id FROM users
WHERE username = '".mysql_real_escape_string($_POST['username'])."'
AND password = '$password'");
if (mysql_num_rows($result) < 1) {
/* Access denied */
echo "The username or password you entered is incorrect.";
}
else {
$_SESSION['id'] = mysql_result($result, 0, 'id');
#header("Location: ./");
echo "Hello $_SESSION[id]!";
}
The easiest way to get your password storage scheme secure is by using a standard library.
Because security tends to be a lot more complicated and with more invisible screw up possibilities than most programmers could tackle alone, using a standard library is almost always easiest and most secure (if not the only) available option.
The new PHP password API (5.5.0+)
If you are using PHP version 5.5.0 or newer, you can use the new simplified password hashing API
Example of code using PHP's password API:
<?php
// $hash is what you would store in your database
$hash = password_hash($_POST['password'], PASSWORD_DEFAULT, ['cost' => 12]);
// $hash would be the $hash (above) stored in your database for this user
$checked = password_verify($_POST['password'], $hash);
if ($checked) {
echo 'password correct';
} else {
echo 'wrong credentials';
}
(In case you are still using legacy 5.3.7 or newer you can install ircmaxell/password_compat to have access to the build-in functions)
Improving upon salted hashes: add pepper
If you want extra security, the security folks now (2017) recommend adding a 'pepper' to the (automatically) salted password hashes.
There is a simple, drop in class that securely implements this pattern, I recommend:
Netsilik/PepperedPasswords
(github).
It comes with a MIT License, so you can use it however you want, even in proprietary projects.
Example of code using Netsilik/PepperedPasswords:
<?php
use Netsilik/Lib/PepperedPasswords;
// Some long, random, binary string, encoded as hexadecimal; stored in your configuration (NOT in your Database, as that would defeat the entire purpose of the pepper).
$config['pepper'] = hex2bin('012345679ABCDEF012345679ABCDEF012345679ABCDEF012345679ABCDEF');
$hasher = new PepperedPasswords($config['pepper']);
// $hash is what you would store in your database
$hash = $hasher->hash($_POST['password']);
// $hash would be the $hash (above) stored in your database for this user
$checked = $hasher->verify($_POST['password'], $hash);
if ($checked) {
echo 'password correct';
} else {
echo 'wrong credentials';
}
The OLD standard library
Please note: you should not be needing this anymore! This is only here for historical purposes.
Take a look at: Portable PHP password hashing framework: phpass and make sure you use the CRYPT_BLOWFISH algorithm if at all possible.
Example of code using phpass (v0.2):
<?php
require('PasswordHash.php');
$pwdHasher = new PasswordHash(8, FALSE);
// $hash is what you would store in your database
$hash = $pwdHasher->HashPassword( $password );
// $hash would be the $hash (above) stored in your database for this user
$checked = $pwdHasher->CheckPassword($password, $hash);
if ($checked) {
echo 'password correct';
} else {
echo 'wrong credentials';
}
PHPass has been implemented in some quite well known projects:
phpBB3
WordPress 2.5+ as well as bbPress
the Drupal 7 release, (module available for Drupal 5 & 6)
others
The good thing is that you do not need to worry about the details, those details have been programmed by people with experience and reviewed by many folks on the internet.
For more information on password storage schemes, read Jeff`s blog post: You're Probably Storing Passwords Incorrectly
Whatever you do if you go for the 'I'll do it myself, thank you' approach, do not use MD5 or SHA1 anymore. They are nice hashing algorithm, but considered broken for security purposes.
Currently, using crypt, with CRYPT_BLOWFISH is the best practice.
CRYPT_BLOWFISH in PHP is an implementation of the Bcrypt hash. Bcrypt is based on the Blowfish block cipher, making use of it's expensive key setup to slow the algorithm down.
Your users will be much safer if you used parameterized queries instead of concatenating SQL statements. And the salt should be unique for each user and should be stored along with the password hash.
A better way would be for each user to have a unique salt.
The benefit of having a salt is that it makes it harder for an attacker to pre-generate the MD5 signature of every dictionary word. But if an attacker learns that you have a fixed salt, they could then pre-generate the MD5 signature of every dictionary word prefixed by your fixed salt.
A better way is each time a user changes their password, your system generate a random salt and store that salt along with the user record. It makes it a bit more expensive to check the password (since you need to look up the salt before you can generate the MD5 signature) but it makes it much more difficult for an attacker to pre-generate MD5's.
With PHP 5.5 (what I describe is available to even earlier versions, see below) around the corner I'd like to suggest to use its new, built-in solution: password_hash() and password_verify(). It provides several options in order to achieve the level of password security you need (for example by specifying a "cost" parameter through the $options array)
<?php
var_dump(password_hash("my-secret-password", PASSWORD_DEFAULT));
$options = array(
'cost' => 7, // this is the number of rounds for bcrypt
// 'salt' => 'TphfsM82o1uEKlfP9vf1f', // you could specify a salt but it is not recommended
);
var_dump(password_hash("my-secret-password", PASSWORD_BCRYPT, $options));
?>
will return
string(60) "$2y$10$w2LxXdIcqJpD6idFTNn.eeZbKesdu5y41ksL22iI8C4/6EweI7OK."
string(60) "$2y$07$TphfsM82o1uEKlfP9vf1fOKohBqGVXOJEmnUtQu7Y1UMft1R4D3d."
As you might see, the string contains the salt as well as the cost that was specified in the options. It also contains the algorithm used.
Therefore, when checking the password (for example when the user logs in), when using the complimentary password_verify() function it will extract the necessary crypto parameters from the password hash itself.
When not specifying a salt, the generated password hash will be different upon every call of password_hash() because the salt is generated randomly. Therefore comparing a previous hash with a newly generated one will fail, even for a correct password.
Verifying works like this:
var_dump(password_verify("my-secret-password", '$2y$10$BjHJbMCNWIJq7xiAeyFaHOGaO0jjNoE11e0YAer6Zu01OZHN/gk6K'));
var_dump(password_verify("wrong-password", '$2y$10$BjHJbMCNWIJq7xiAeyFaHOGaO0jjNoE11e0YAer6Zu01OZHN/gk6K'));
var_dump(password_verify("my-secret-password", '$2y$07$TphfsM82o1uEKlfP9vf1fOKohBqGVXOJEmnUtQu7Y1UMft1R4D3d.'));
var_dump(password_verify("wrong-password", '$2y$07$TphfsM82o1uEKlfP9vf1fOKohBqGVXOJEmnUtQu7Y1UMft1R4D3d.'));
I hope that providing these built-in functions will soon provide better password security in case of data theft, as it reduces the amount of thought the programmer has to put into a proper implementation.
There is a small library (one PHP file) that will give you PHP 5.5's password_hash in PHP 5.3.7+: https://github.com/ircmaxell/password_compat
That's fine with me. Mr Atwood wrote about the strength of MD5 against rainbow tables, and basically with a long salt like that you're sitting pretty (though some random punctuation/numbers, it could improve it).
You could also look at SHA-1, which seems to be getting more popular these days.
I want to add:
Don't limit users passwords by length
For compatibility with old systems often set a limit for the maximum length of the password. This is a bad security policy: if you set restriction, set it only for the minimum length of passwords.
Don't send user passwords via email
For recovering a forgotten password you should send the address by which user can change the password.
Update the hashes of users passwords
The password hash may be out of date (parameters of the algorithm may be updated). By using the function password_needs_rehash() you can check it out.
Here's a PHP + CouchDB.apache.org login system that doesn't store plaintext passwords.
According to the advice that I've read, it should be totally secure.
CMS login code : https://github.com/nicerapp/nicerapp/blob/24ff0ca317b28c1d91aee66041320976a6d76da7/nicerapp/boot.php#L56
calls
https://github.com/nicerapp/nicerapp/blob/24ff0ca317b28c1d91aee66041320976a6d76da7/nicerapp/functions.php#L171
app(s) specific business code :
https://github.com/nicerapp/nicerapp/blob/24ff0ca317b28c1d91aee66041320976a6d76da7/nicerapp/ajax_login.php#L87
calls
https://github.com/nicerapp/nicerapp/blob/24ff0ca317b28c1d91aee66041320976a6d76da7/nicerapp/functions.php#L230
which in turn calls :
https://github.com/nicerapp/nicerapp/blob/2d479b3e22dce9e7073525481b775f1bf7389634/nicerapp/apps/nicer.app/webmail/recrypt.php#L2
and to edit the webmail app config data into the database :
https://github.com/nicerapp/nicerapp/blob/main/nicerapp/apps/nicer.app/webmail/ajax_editConfig.php