I was looking about best practice for password protect, everybody are talking about bcrypt and others hashing classes. But I can't get how To verify password if it contains unique random salt .
For cookies its fine, but without em - each time would be unique crypted value, how can I verify users password with random values? Oo . Or bcrypt only for cookies?
Then what I should do with password in db?
Please describe to me my mistakes - what I've lost when learning about it.
The bcrypt algorithm creates a random salt that is stored as part of the hash in a standardised way.
See How do you use bcrypt for hashing passwords in PHP? for a working example.
See also:
Secure hash and salt for PHP passwords
(edited heavily since my answer was wrong before)
There will be a group of function in the next php version, for details see the accepted RFC.
Anthony, the author of the RFC and the patch was kind enough to provide a compatibility library written in php so you can start using this new functionality now!
Behind the scenes it uses crypt with the strongest algorythm currently known.
Related
Use SHA512 as encryption in Multicraft panel (which you can change the settings for MD5), but I need to use an older version of the same database. This old version did not have the option to encrypt with SHA512, but only with MD5. Thus, all passwords are invalid with MD5.
It's possible convert all SHA512 passwords in MySQL database to MD5?
SHA512 and MD5 are hashes, not encryption algorithms. By design, they are not reversible.
The only way to convert these values is to wait for each user to log in, validate their password against the existing SHA512 hash, and rehash¹ their input with MD5. This is the reverse of how password hashes are updated to more secure standards.
But please, please, don't do this. MD5 is hopelessly broken. You would be doing your users a huge disservice to revert from SHA512 to MD5. Find a way to use the newer version of your software.
¹As noted by zaph in a comment, "rehashing" is an oversimplification, and depending on how your panel is actually implemented it might be using insecure password storage today.
To provide reasonable security each password must also have a unique random salt (which protects against things like rainbow tables) and each hash must be iterated enough times to make brute forcing impractical. As computers get more powerful the number of iterations must be increased. Today it is common to iterate tens or hundreds of thousands of times.
Cryptography is shockingly difficult to get right. Instead of trying to follow all the best practices manually, use libraries and functions that operate at the right level of abstraction and have been audited for security. An algorithm like bcrypt (via PHP's built-in password_hash function, where it is currently the default algorithm) would be a good choice.
Short answer: No.
Long answer:
By design, both MD5 and SHA512 are one-way hashes. In order to convert SHA512 to MD5, you would need to know both the original password for every password your are trying to convert, and also the salt that was used to encrypt them. You almost certainly wouldn't know every password for every one of your users.
One-way hashes work by actually casting the same algorithm every time a user logs in. The user types in their password, the algorithm is applied to it, and if it perfectly matches the copy in the database that has already been hashed, then the user is logged in. You can't use any sort of algorithm to work out what the original password was, only to compare if the output of applying a specific password would be to a password that is already encrypted.
MD5 is also a far weaker hashing algorithm than SHA512. Converting to MD5 would make your password far less secure, and this would be something that you probably wouldn't want to do. Instead, you should be looking at a way to incorporate the new database system.
I know that there are alots of questions about this subject but i really need to ask this.
Today I've been working on encrypting passwords with md5.
So what I've done is.
I got 4 salts. (they changes depending on user values)
from email id and substr then md5 them
from email and id substr other positions
a long string, substr it and then md5 it
another long string, substr it and then md5 it
Then i md5 salt1 and 3 and the password with salt 2 and salt4
After this I have to change the password automatically whenever a user changes his email or his id getting changed.
What do you guys think about this?
Nothing.
MD5 is broken and bad.
Using the mailaddress as salt is a good idea. But using md5 is not. Use instead bcrypt, scrypt or pbkdf2.
Don't invent your own ecryption, unless you really know what you are doing, and trust me, you don't
First, let us define a few terms.
Encryption is when you encode a message so that it cannot be read. Encryption involves a plaintext, a cipher and a key. It is like putting a book (the plaintext) in a locked room (cipher), which can only be opened using a known tool (a key). There are many kinds of encryption, but that is a simple description. Encryption is two-way, meaning that you can encode and decode the message.
Cryptographic hash is when you take any kind of data and generate a fixed size value for it (usually called a hash or a digest). Cryptographic hashes are one-way, which means that you cannot reverse the process.
A salt is a unique string, or a collection of bits, similar to a nonce (a unique number that is only used once). Salts are only used to make it infeasible for a cracker to process a list of hashes. They are not supposed to be used as a secret (i.e. like a cryptographic key). The only reason people usually talk about randomness when it comes to salts is because they want to generate a unique salt (if the randomness is not great enough they may get colliding salts, for instance).
Okay, now to how you should hash a password.
A relatively safe way of hashing a password is to simply tack on a unique hash onto a password, and then save the salt with the password:
$pass = 'this is my password';
$salt = uniqid('', true);
$hash = sha1($pass . $salt);
// INSERT INTO users ('hash', 'salt') VALUES ('$hash', '$salt') WHERE ...
That is an okay way of doing it if your website does not retrieve any sensitive data from its users.
If you deal with sensitive data, or if you just want to make sure that you are doing everything you can to keep stuff safe, then there is a PHP function that does the hashing for you. It is called crypt() (read the documentation to learn how it works). Here is an example of how to hash a password using the function:
$pass = 'this is my password';
$salt = 'unique string';
$hash = crypt($password, '$2y$07$'.$salt.'$');
echo $hash;
That will securely hash a password.
The thing to realize is that the crypt() function is much more secure than anything you can come up with (unless you are a specialist in the area).
In newer versions of PHP (5.5.0+) there is a password hashing API that makes it even simpler to hash a password.
There are also various hashing libraries out there. PHPass is a popular one.
It is bad, because it uses MD5.
MD5 is a very fast operation. It can be executed billion of times per second on graphic cards hardware. It is considered bad practice to use it for any password related things.
Use bcrypt. Use a random salt. Use the upcoming PHP API for hashing, verifying and rehashing passwords. This include file implements it for versions starting with PHP 5.3.7: https://github.com/ircmaxell/password_compat
Well, "MD5 is broken and bad" is a little exagerated. Even if it can be brute-forced with a lot of CPU, it is not "broken" and is still a very useful algorithm for a lot of things involving hashing.
So "MD5 should not be used for password encryption" sounds much better to me.
When using PHP, an easy and safe option is to rely on the password_hash() (which natively generates a random salt) and password_verify() functions.
The advantage is that the encryption algorithm will transparently be updated with each new PHP version (at the moment PASSWORD_DEFAULT is set to bcrypt, but should bcrypt be "broken" it can be set to a newer algorithm), which makes any code using those functions quite resilient.
I personally do not recommend involving of the user id and his email into the hashing of his password.
You can deal with the password by:
Dynamic salt per user based on random string generated on user registration
Prepend one part of the salt and append the other around the password
Double md5: md5(md5($password))
Etc.
a simple way would be to generate a random salt for each user and hash your password like this
public function encodePassword( $raw, $salt ) {
return hash('sha256', $salt.$raw);
}
For high security hash, you can check this link which explain how to implement PBKDF2:
http://crackstation.net/hashing-security.htm#phpsourcecode
I'm the developer of a new website built in PHP and I'm wondering what exactly is the best
thing to use for hashing. I've looked at md5 and sha1 but is there anything more secure.
I'm sorry if this is a nooby question but I'm new to PHP Security and I'm trying to make my
site as secure as possible. Also what is a salt?
Thanks,
Waseem
First off md5 and sha1 have been proven to be vunrable to collision attacks and can be rainbow
tabled easily (When they see if you hash is the same in their database of common passwords).
There are currently two things that are secure enough for passwords, that you can use.
The first being sha512. sha512 is a sub-version of SHA2. SHA2 has not yet been proven to be
vunrable to collision attacks and sha512 will generate a 512 bit hash. Here is an example of
how to use sha512:
<?php
hash('sha512',$password);
The other option is called bcrypt. bcrypt is famous for its secure hashes. Its
probably the most secure one out there and most customizable one too.
Before you want to start using bcrypt you need to check if your sever has it enabled, Enter
this code:
<?php
if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH) {
echo "CRYPT_BLOWFISH is enabled!";
}else {
echo "CRYPT_BLOWFISH is not available";
}
If it returns that it is enabled then the next step is easy, All you need to do to bcrypt a
password is (Note for more customizability you need to see this How do you use bcrypt for hashing passwords in PHP?):
crypt($password, $salt);
Now to answer your second question. A salt is usally a random string that you add at the end of
all you passwords when you hash them. Using a salt means if some one gets your database
they can not check the hashes for common passwords. Checking the database is called using a rainbow table. You should always use a salt when hashing!!
Here are my proofs for the SHA1 and MD5 collision attack vulnerabilities:
http://www.schneier.com/blog/archives/2012/10/when_will_we_se.html, http://eprint.iacr.org/2010/413.pdf, http://people.csail.mit.edu/yiqun/SHA1AttackProceedingVersion.pdf, http://conf.isi.qut.edu.au/auscert/proceedings/2006/gauravaram06collision.pdf and Understanding sha-1 collision weakness
The whole purpose of the salt is to slow down an attacker from comparing a list of pre-generated hashes against the target hash.
Instead of needing to pre-compute one "hashed" value for each plaintext password, an attacker needs to precompute 16384 "hashed" values for each plaintext password (2^7 * 2^7).
That kinda pales today but was pretty big when the crypt function was first developed - the computational power to pre-compute that many passwords times the number of plaintext password you suspect (dictionary) was pretty high.
Not so much today which is why we have things like shadow passwords, other core password functions besides crypt and every sysad wanting you to pick a password that would not show up in a dictionary.
If the hashes you want to generate are for passwords this is a well accepted method of implementing it.
http://www.openwall.com/phpass/
If you're planning to do this for passwords, then do not use MD5 or SHA1. They are known to be weak and insecure, even with salt.
If you're using them for other purposes (eg providing a hash of a file to confirm its authenticity, or a random hash database column to provide a pseudo-random sort order) then they are fine (up to a point), but not for passwords or anything else that you would consider needing to be kept secure.
The current best-practice algorithm for password hasing is BCrypt, with suitable salting.
And the best way to implement BCrypt password hashing in PHP is to use PHP's new password API. This API will be featured as a set of built-in functions in the next version of PHP, v5.5, due for release in the next few months. The good news is that they have also released a backward-compatibility version for users of current versions of PHP (5.3 and 5.4), so even though PHP 5.5 isn't released yet, you can start using the new API immediately.
You can download the compatibility library from here: https://github.com/ircmaxell/password_compat
Also: You asked what "salt" is. Since I've mentioned it a couple of times in this answer, I should address that part of the question too.
Salt is basically an additional string added to the password when hashing it, in order to make it harder to crack.
For example, an attacker may know in advance what the hashed value is for a given password string, or even a whole lot of given password strings. If he can get hold of your hashed data and you haven't used a salt, then he can just compare your hashes against his list of known passwords, and if any of your users are using an easy to guess password, they'll be cracked in seconds, regardless of what hashing method was used.
However, if you've added a secret extra string to the password when you hash it, then the hashed value won't match the standard hash for the original password, thus making it harder for the attacker to find the value.
The good news is that if you're using the API I mentioned above, then you don't need to worry too much about the details of this, as the API handles the salting for you.
Hope that helps.
I have a login system
where, for example, Joe can login with the username joe without any problems.
Currently, I am using a password encryption that uses the username as a salt. This is creating issues for logging in. For example,
SELECT * FROM `users` WHERE LOWER(`username`) = LOWER(`:username`)
$stmt->bindValue(':username', $_POST['user']);
This works fine. THe trouble involves the password:
SELECT * FROM `users` WHERE LOWER(`username`) = LOWER(`:username`)
AND `password` = :password
$stmt->bindValue(':username', $_POST['user']);
$stmt->bindValue(':password', encrypt($_POST['password'], $_POST['user'])); //encrypt(password, salt)
As you can see, the password encryption wouldn't check with the database because the user has logged in with joe instead of Joe
Is there a workaround to this, or should I use something else as a salt? If so, what should I use as a salt? This is my encrypt function:
function encrypt($password, $salt) {
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($salt), $password, MCRYPT_MODE_CBC, md5(md5($salt))));
}
First off, what's the issue with using strtolower($_POST['user']) as the salt? It looks like it would work.
Now in general, salts should be unpredictable. Usernames aren't really that unpredictable, so although this won't be the end of the world your users' security will be better if you replace the username with a randomly generated string of modest length (it need not be crypto-strength random, just unpredictable).
But the biggest issue here is the use of MD5, which has been considered unsafe for some time. Security would improve if you switched to some other hash function; SHA-1 is not a particularly bad choice (it does have an undesirable property: it's fast to calculate), but the best fit for such applications are hash functions with a variable load factor such as bcrypt.
There are a couple issues here:
The case-sensitivity of your salt
Your method of password "encryption"
The first issue is what you've asked about, so let's take a look at that.
So your passwords are salted with the user name, and you expect to be able to use the username the user entered during login as the salt. This will work, if you settle on a normalization scheme for your salt. Instead of using it as-entered, convert it to lowercase or uppercase before using it in your function.
The other option is to perform two queries to the database: one to pull the username as it's stored, and the second to actually check the password. This isn't optimal, but it would really be the least of your troubles.
Is there a workaround to this, or should I use something else as a salt? If so, what should I use as a salt?
Since you asked, let's look at the second issue: your method of password "encryption."
Trying to invent your own password hashing/encryption scheme is never a good idea, for a number of reasons. Your best option is to use an already widely accepted password hashing scheme, such as bcrypt or some derivative of PBKDF2. These are great because they both include both salting and key stretching. They are designed to be slow (relatively, anyway) so brute-forcing these types of hashes is made very computationally expensive.
Using one of the aforementioned password hashing schemes will solve your first problem as well, as these schemes use built-in per-user salts. Depending on how you choose to implement these schemes, you will not (should not) need to provide your own salt. The top libraries will generate salts for you.
Try taking a look at these libraries for password hashing:
Openwall's PasswordHash class - Written for PHP4, but works on the latest versions as well. Supports bcrypt, but will fall back to its own scheme if bcrypt isn't supported (PHP < 5.3, mostly).
Anthony Ferrara's (ircmaxell's) PHP Password Library - Great library, but requires PHP 5.3+.
My own PHPassLib - Similar to Anthony's library, but implemented differently. The 3.x branch attempts to be more like Python's PassLib. Also requires PHP 5.3+.
Skip the SQL lower and use PHP's strtolower(). That way your usernames will be consistent across the board.
The problem you're having is one reason that username's shouldn't be used as the salt. A better way to hash passwords is with crypt(). You just need to generate a random salt to use with it. The string it returns contains the hash and the hashing algorithm so you can change the algorithm or difficulty if you want to without having to rewrite code. As long as your hash is 7-bit safe, the whole string will be, so you don't need to base64_encode() anything.
I'm developing a web service where users must login. I will store user data in an SQL database and input/output via PHP. But I don't want to store it openly. How do I encrypt the passwords in PHP so only those who knows the password can unlock it?
I know services like phpBB uses some sort of hiding/encryption on stored passwords.
You need to salt and hash the password, using an appropriately secure algorithm.
PHP's mhash has appropriate hashing functions
A full example here on SO
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.
See this answer for more info
You probably want to hash the password - not encrypt it. Check out SHA-1. Hashing means that you cannot retrieve the original data as you can with encryption. Instead what you do is hash the users input and compare it to the hash in the database to see if they've got the right password. Doing this increases security as if your database was ever compromised - a bunch of hashes are useless.
Well, you shouldn't encrypt them with MD5 (which is not really secured, most hackers have conversion tables).
Hence, you can hash it with SHA1 (which is usually used).
If you want more security, you can add more salt which is a key you can add like this (just an example, usually used) :
salt+sha1(salt+pass)
This combination can be used with many language.
Hash passwords in SHA-1 (sha1 php inbuilt function) with several recursions of salting (same code in the answers above, only loop through several times). This should be sufficient protection, so even if the intruders somehow get their hands on the hashes, they shouldn't be able to crack them...
Save an MD5 hash and to make it more secure, add a salt.
There is the possibility to hash passwords (preferably with a salt):
$salt = random_string($length = 5);
$hash = $salt . sha1($salt . $password);
Or store encrypted (only if your MySQL connection is SSL secured):
INSERT INTO `user` (`user`,`pass`) VALUES("username",ENCRYPT("password","secretkey"))