I am creating a custom CMS and have built a login system and was wandering how vulnerable hashing the passwords this way would be compared to just using the md5 php function like this:
<?php $token = md5($salt . $password . $pepper); ?>
Most people just add a salt but adding pepper just makes sense if your going to add salt :)
Here is how I am doing it
<?php $token = hash_hmac('sha512', $salt . $password . $pepper, $key); ?>
The $key would be a value in the database that is unique to each user.
The $salt and the $pepper are randomly generated strings.
The $password is the password of course.
Added on 07/24/09
Thanks for all your responses. Does anyone have an examples of how they do a hash script for creating passwords to store in a database?
Similar to: https://stackoverflow.com/questions/1111494
Make sure you read this:
http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/
And this:
bcrypt is obsolete
Your method is using a stronger hash.
I don't see you opening yourself to any extra vulnerabilities.
MD5 is not suitable for any cryptographic purpose, use SHA-1 or preferable SHA-256.
http://www.mscs.dal.ca/~selinger/md5collision/
Related
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.
Before I start I'd like to apologise for bringing up this subject once again, as many users did, but with a research I did, I wasn't happy with what I've found. I just hope to come up with something really helpful here.
Since md5 or sha1 are considered bad practice (even when using salts ???), I have tried to create this function for hashing my password
$password = $_POST['password']; // lets say that my password is: my_sercretp#ssword123
function encrypt_the_password($password){
$salt = "lorem_ipsumd0l0rs1t#m3tc0ns3ct3tur#d1p1sc1ng3lit";
return hash('sha256', $salt.$password);// can use also different algorithm like sha512 or whirlpool
}
$hashed_password = encrypt_the_password($password);
Note that this one I use it in a personal website with only one user, me. In case of having more than one users I come up with something like this:
$password = $_POST['password'];
function generate_salt() {
$salt = uniqid(md5("lorem_ipsumd0l0rs1t#m3tc0ns3ct3tur#d1p1sc1ng3lit".microtime()));
$salt = hash('sha256', $salt);// can use also different algorithm like sha512 or whirlpool
return $salt;
}
function encrypt_the_password($password,$salt){
return hash('sha256', $salt.$password);// can use also different algorithm like sha512 or whirlpool
}
$hashed_password = encrypt_the_password($password,generate_salt());
Is this secure enough (in each case) or can this improved more???
MY EDIT: I tried to come up with something new using the crypt() function. Here's my code in case of having a site with only one user, admin:
$password = $_POST['password'];
$salt = "L0r3mIpsUmD0l0rS1tAm3t";
$hashed_password = crypt($password', '$2a$12$' . $salt);
and in case of having a site with more than one users:
$password = $_POST['password'];
function generate_salt() {
$salt = uniqid(sha1("L0r3mIpsUmD0l0rS1tAm3tc0ns3CT3tur4d1p1sc1ng3lit".microtime()));
$salt = substr(sha1($salt), 0, 22);
return $salt;
}
$hashed_password = crypt($password', '$2a$12$' . generate_salt());
Is this ok or needs improvements???
Improve it by not making up your own algorithm. Your algorithm is insecure because your salt is constant and you only hash with one iteration of SHA256, which is computationally cheap.
Instead, use Bcrypt, which is both computationally expensive and verified by people who know what they're doing, so it's much safer than your solution.
You should use the password functions that will come inbuilt in PHP 5.5. There's a fallback library by ircmaxell that can provide the functions in earlier versions of PHP: https://github.com/ircmaxell/password_compat
It will always use the most recent hashing technique available, and in case even update the records for you. Make sure you read the README coming along with this library.
Do not make your own hashing function.
I am rewriting a PHP Login system and I just faced this
function createSalt()
{
$string = md5(uniqid(rand(), true));
return substr($string, 0, 3);
}
$salt = createSalt();
$hash = hash('sha256', $salt . $hash);
Actualy I never worked with salting before, I searched a bit and found it useful.
But my answer is, Is this a good way to work with salt?
Wouldn't $string = sha1(uniqid(mt_rand(), true)) be better?
And what about returning only 3 characters of the hash? I really don't get it.
What you think?
Consider using PHP's crypt() instead of reinventing the wheel. It is specifically designed for password hashing, and offers hash algorithms suited for that purpose.
I prefer sha1 or sha256, md5 is super-outdated, the sha-functions are way better. But this is my opinion, choose what you want.
What is really important in this case is the salt. A salt is always stored in plaintext together with the hash and is used to improve the length of a password (if you want to hash the password, might be something else of course) to prevent attacks based on rainbow/lookup tables. This is no protection against cracking the password by using bruteforce (which works quite well against md5, so use sha256 which is harder to crack).
Therefore it is totally unimportant if you use 32 random chars for the hash, or something like md5(mt_rand()) - important is the length. I would use something like
$hash = md5(mt_rand()) . md5(mt_rand());
md5() results in 32 bytes string, based on a random number (mt_rand() is better then uniqueid()). With this simpel line you get a very "strong" hash which should secure every password against rainbow tables.
I don't agree with the given function createSalt() - mainly for the same reasons as you.
My approach to this would be
define(SALT_LENGTH,32);
function createSalt()
{
$string='';
for ($i=0;$i<SALT_LENGTH;$i++) $string.=chr(rand(0,255));
return $string;
}
A good salt is a random byte sequence - no MD5 or SHA1 makes any sense, as there is nothing to hash!
I no master PHP programmer but I've been working on the same hash script for a login system.
Im storing it on GitHub - https://github.com/revitalagency/PHP5-Salt-Super-Admin
I created my hash using...
hash_hmac('sha256', $_POST['pass'], GLOBAL_SALT);
GLOBAL_SALT is defined in a config file not in the DB for extra protection.
I am working on a web administration module for mailservers (it's open source if you'd like to take a look).
For that, I need to be able to generate hashed password that is readable by Dovecot. As described on their wiki, their recommended password hashing scheme is SSHA256 (the extra S is for salted).
It's also explained that this could be reasonably simple to implement with something like this PHP code:
$salt = 'generate_a_salt_somehow';
$hash = hash('sha256', $password . $salt);
However, from what I've read about cryptography, that is a rather naíve way to generate salted hashes, but if you're doing it wrong when typing A-E-S in your source code, I figured the same could be true in this case.
So if you have insight into cryptography, I'd love to hear about the most secure way to do this, be it mcrypt, mhash or whatever.
Password generation function in PHP:
$hash = "{SSHA256}".base64_encode(hash('sha256', $password.$salt, true).$salt);
Necessarily "true" - the third parameter...
The Dovecot wiki page you linked to explains what the exact hash format Dovecot uses is. You don't have any choice in the matter -- Dovecot has its expectations on what the hash will look like, so you have to play by its rules:
For most of the salted password schemes (SMD5, SSHA*) the salt is stored after the password hash and its length can vary. When hashing the password, append the salt after the plaintext password, e.g.: SSHA256(pass, salt) = SHA256(pass + salt) + salt.
So an appropriate password generation function in PHP might look like:
$hash = "{SSHA256}" . base64_encode(hash('sha256', $password . $salt) . $salt);
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.