I am working on a registration form where I need to encrypt password, I've heard that it is recommended for me to use the Blowfish encryption for passwords, How do you implement a blowfish encryption using PHP crypt() function? also, I am planning to retrieve the password later for logging in.
The short answer is use crypt with a salt beginning with the characters $2a$, a two digit cost parameter, $, and 22 digits from the alphabet ./0-9A-Za-z. That only works on systems that support the Blowfish encryption algorithm. However, PHP 5.3 implements it natively. See PHP manual — crypt for more details.
Example:
crypt('rasmuslerdorf', '$2a$07$somesillystringforsalt')
The salt string triggers the appropriate algorithm. The two digit cost parameter is the base-2 logarithm of the iteration count for the underlying Blowfish-based hashing algorithm and must be in range [04 – 31]. In the example 07 tells the algorithm to use 27 or 128 iterations. The higher this number, the longer it will take to execute BUT, in the context of hashing user passwords, that is a GOOD thing.
This answer to a similar question explains in more detail what BCrypt is,how it relates to Blowfish, and why you should use it. There are many other related topics here on Stack Overflow.
phpass is an excellent, easy to use password hashing framework that works on all systems, using Blowfish if it’s supported, and falling back to other algorithms if it’s not.
You should never need blowfish to encrypt a password like this. The registration form should be over HTTPS, which will handle defense against an attacker on the wire. The password its self should be hashed (never encrypted). bcrypt is a good password hash function based on blowfish. But there are plenty of posts related to secure password storage on SO.
Related
I've been looking at encryption methods for a while now and what I've found so far is that Bcrypt is one of the best ways to do so right now. What I don't get yet is the way that Bcrypt works precisely. I understand that it takes longer to solve which is why it makes bruteforcing so hard.
But I don't understand whether it requires other measures such as a random salt to make it secure. Especially after reading about md5 and how having a random salt is almost mandatory before a hash becomes secure.
The sample code I found on php.com is this:
$options = [ 'cost' => 12, ];
echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options)."\n";
?>
I'm guessing the cost simply makes it so it runs through the function 12 times to encrypt the word "rasmuslerdorf". And the "PASSWORD_BCRYPT" selects the Blowfish algorithm.
Are there any big differences between PASSWORD_DEFAULT and PASSWORD_BCRYPT?
Is it enough for me to use the default function to encrypt the password on registration. And than compare the password after encrypting it that the user enters on login to the encrypted password in the database?
I'm guessing the cost simply makes it so it runs through the function 12 times to encrypt the word "rasmuslerdorf"
No, the cost parameter effects an exponential amount of work to be done.
But I don't understand whether it requires other measures such as a random salt to make it secure.
The password_hash() function automatically generates a random salt whenever you run it; alternatively, a custom salt can be passed via the options:
password_hash('bla', PASSWORD_BCRYPT, ['salt' => ...]);
By passing a custom salt you're assumed to know what you're doing. For all practical purposes you should be safe to stick with automatically generated salts.
Are there any big differences between PASSWORD_DEFAULT and PASSWORD_BCRYPT?
The PASSWORD_DEFAULT algorithm is provided to future-proof your code by always using the strongest algorithm available at that time (provided you update PHP). The notable difference is in storage requirements; whereas Bcrypt always uses 60 characters, you need to cater for bigger storage (e.g. 255 characters) for whatever will be used in the future.
And than compare the password after encrypting it that the user enters on login to the encrypted password in the database?
Please look at password_verify() for examples on how to verify the password a user enters.
The Bcrypt algorithm is the default algorithm. So, PASSWORD_DEFAULT and PASSWORD_BCRYPT are the same. The default algorithm can be configured in your php.ini file, but if you did not know that then it is most likely still the default.
The cost number is not how many times it is hashed. How many times it is hashed is calculated by using the formula, 2^cost. So, if the cost is 12 then it will be hashed 2^12 times (4096).
You do not have to think about salts when using the function. It creates the salt itself and appends it to the output hash:
$[algorithm]$[cost]$[salt 22 chars][rest is the hash]
You should never touch the hash, when using the password hashing functions. To verify a password against the has you should use password_verify().
The function you are using was made so that people can hash passwords without knowing what is happening in the background. That is a good thing, because when it comes to hashing passwords it is very easy to get it wrong, even if you think you know what you are doing.
Given that the rule of thumb is to store salted hashes of the password string, not the encrypted form of it, why does the PHP crypt() function use the DES-based algorithms? Isn't DES an encryption algorithm? The manual says
... crypt() will return a hashed string using the standard Unix DES-based algorithm or alternative algorithms that may be available on the system ...
What I understand from here is that crypt() only uses the algorithm as implemented by the system. And surely DES is implemented as an encryption algorithm rather than a custom hashing algorithm for crypt.
PS - I know that DES was way back in the past and nobody should use it anymore.
The idea of DES-based password hashing is, basically, to encrypt a block of zeroes with the password and passed salt for some number of rounds. Any half-decent encryption makes key recovery hard even in the face of known plaintext, so that’s why it’s possible to make strong password hashes out of encryption functions.
I think the PHP default is compatible with this scheme.
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 want to create a membership site so i want to make the passwords as safe as possible. I can see from reading sites including this one the md5, sh1 encryption are a serious no no. I've seen some other things like bcript, scrypt, sha256, sha512 and PBKDF2. I have found some php scripts implementing these but not really found anything of note to do with the database.
Do i have to create a row containing the salt?
Verifying the password do i have to do something like hash(salt+password) = $hash?
Because i'm not the most experienced at passwords i'm not really sure of the best practices, how when you hash the password + salt what happens then, how the passwords are retrieved...
I think because i dont really understand the logic behind it i'm feeling a little confused about how to go about it.
If you use Bcrypt, Scrypt, or PBKDF2, the salt is part of the hash you get, so no, you don't have to worry about storing it separately. Otherwise (SHA-*), yes — but you shouldn't use those anyways. Bcrypt, Scrypt, and PBKDF2 are actual password-hashing functions.
I'd recommend Bcrypt, since you tagged this php. It's built-in. Scrypt isn't.
A common best practise (see e.g. Linux passwd) is to store the password hashes as
$<algorithm>$<salt>$<hash>
for example this string:
$6$Lxgyf7h6DtkrqwT$0w/BoB6neYjEtdQdUEs3ftnnNguBNTug8.g/9UeMmZ9bN/cDJCE0dj8.4D/8HPN5bMqFPJ4ECnGl5M2iqBmmv/
is a salted SHA-512 (algorithm id 6) password hash salted with Lxgyf7h6DtkrqwT that should be understood by most servers out of the box.
The benefit of this is that you can actually support different algorithms at the same time. So some users may still have e.g. SHA-256 passwords, while for any user changing his password you switch to a more secure algorithm.
A good starting point to read about modular hashing schemes, read this article in Wikipedia on the crypt (Unix) function. The hype around bcrypt (and the misinformation that crypt would equal DES hashing) is indicative of a certain naiveness of PHP developers with respect to password security. bcrypt is not bad (well, it relies on computational complexity instead of stronger algorithms AFAIK, but it certainly seems to beat MD5). But I would advise using something like this scheme which is A) portable, and B) extensible, so that you can at any time smoothly transition to stronger password hashes.
In 99% of programming languages (including PHP), this functionality is available out of the box via the crypt function, by choosing an appropriate salt, starting with $6$ and the appropriate length of salt characters.
And to clean up some of the misinformation systematically spread by bcrypt advocates: this is not using just one round of sha-512, but the default apparently (see http://www.akkadia.org/drepper/sha-crypt.html ) is 5000 rounds of SHA-512. And you can choose to increase the number. So for my understanding the "but bcrypt can be scaled up when needed" claim also holds for crypt-SHA512. In contrast to bcrypt, this should be available on any Linux system using glibc 2.7 onward. bcrypt is an extension only available on some distributions or with some extensions. On Debian and probably Ubuntu you apparently need to install the extension
libpam-unix2 - Blowfish-capable PAM module
My question is how do I get the same result from mcrypt as I would get from crypt, with respect to blowfish?
I am wanting to use the phpass framework for password hashing and verifying. Which works really well as long has you have PHP 5.3 because blowfish is included with crypt().
My host is running PHP 5.2.x with the mcrypt library.
Going through the docs and googling about blowfish with crypt, it appears that the result is '$a2$', the two character iteration value, '$', the salt ( padded or cut to 22 characters ), then a 32 base64 string representing the hash.
My problem is I can't find explanations of the MCRYPT_MODE_modenames that make sense to me. And how do I feed mcrypt() the number of iterations I want? Or are the two functions using different forms of blowfish that dont cross translate?
Mcrypt, and crypt() are two totally different functions. Mcrypt is two-way encryption, whereas crypt is one-way encryption. As far as I am aware crypt() is inside of php 5.2. Also, if I was you I'd just reference crypt() itself. And I'd also use bcrypt from it.
$hashed_password=crypt($password_to_be_hashed,'$2a$04$saltstringhere');
Finally, just change the two digit cost factor inside of the two digits after the $2a$. That will allow you to change the amount of cputime that is going to be required for it. Remember it goes up logarithmically(if i remember correctly). The default value is 07.
Finally crypt_blowfish is the two-way encryption algorithm of blowfish that takes keys up to 448 bits. The blowfish inside of crypt is bcrypt, is based upon blowfish but was designed for storing passwords as it hashes them. This is known as one-way encryption.