-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Security] Add BCrypt password encoder #5974
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@elnur Could you look at the gist I pasted into the issue. That code has a support for all bcrypt password hashing algorithms and it also creates properly base64 encoded salt. For all I care you can just copy paste it here and add the tests... |
@mvrhov, what do you mean by all bcrypt password hashing algorithms? |
My wording was a bit off. There is more than one hashing algorithm that can be used with crypt (bcrypt is just one). https://gist.github.com/4040680. It's also important how long the salt is and how it's encoded. The code in the gist is written against 2.1. The 2.2 branch now includes SecureRandom which can be used for salt generation. Then it just needs to be properly encoded. |
@mvrhov, as you can see, my current implementation of the encoder generates a salt 22 characters long, but thanks for pointing me to |
Please have a look at You should at least copy my code in function gensalt_blowfish($random) for generation of the salt. Also, the use of sha1 and and uniqid is a bad idea. It is better to use random bits from mt_rand directly, if you are going to use mt_rand as a random source. May I also suggest that you put the code to get n random bytes in its own method? Terje |
For the random bytes sequence, we should rely on SecureRandom as @mvrhov suggested. This is highly reusable and if we need to fix/improve the random generation, only |
@maoueh That is all well and good. But I hope he do not forget to fix the other things I mentioned as well. A key feature from my gensalt_blowfish function that is missing in his code is to account for that bcrypt uses a different base64 encoding than the usual. |
How do I make a Pull Request then? |
First, you fork symfony repository if not have done so already by using the fork button above. You then clone your fork
Add elnur repository in your own symfony repo fork:
You fetch his repo to get his branches and checkout a new branch tracking his
At this point, you have his code and you make modifications. You commit your changes then push to your own repository:
You go on github on your symfony fork page, url should be: https://github.com/TerjeBr/symfony. You will see a Pull Request button. Hit it. In the base repo drop down, choose That should do the trick. |
@TerjeBr Here is fully explained: http://symfony.com/doc/current/contributing/code/patches.html |
Will this do? |
@TerjeBr No, you should send your PR to Follow those instructions that are a bit different:
For the coding standard violations of your commits (in PR #6023). Conditionnal and function call should (usually) not be break on two lines, there should be 4 spaces instead of 2. |
@maoueh I tried to do what you wrote, but elnur/symfony was not a valid choice for the base repository. It is not in the drop down list, and I also tried to just type it in, but it was refused. So I did what I thought was the next best thing and just choose the symfony/symfony repository. I changed the tabspacing and did a new git push origin bcrypt-password-encoder-tb. How do I update the pull request then to also have the latest changes I did? |
Ok, ignore my last question. I just saw that the pull request had updated itself. |
@TerjeBr Interesting, I tried this with someone else and it worked as expected. Don't know what could cause this, maybe his repo is locked or something. Yes PR update themself when you push to the branch. |
I'll switch to |
*/ | ||
public function encodePassword($raw, $salt = null) | ||
{ | ||
$salt = $this->generateSalt(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The salt
can't be generated in this function as it returns only the encoded password.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure it can be generated here. The salt will be in the first 29 characters of the returned value, and the actual encoding of the password in the next 31 characters, giving a total of 60 characters in the returned string. (See php's documentation of the function crypt)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. Thanks.
@fabpot, @stof, can we require PHP >= 5.3.7 for Symfony because of the security fix of the Blowfish algorithm? |
It's probably a better idea to just raise an exception for older PHP versions. |
@schmittjoh, an exception stating they need to upgrade PHP or what? |
Yeah. We have other algorithms which one can use with older versions, there On Sun, Nov 18, 2012 at 7:58 PM, Elnur Abdurrakhimov <
|
I like how Kevin Herrera has solved this in his implementation of bcrypt. He checks on the php version and also adds a parameter to force the borken implementation if the user/programmer should wish that. Especially look at the function setImplementation($implementation) Terje |
@schmittjoh, okay, I'll sleep on this. :) |
@elnur, you did not give any comments on what I said. Did you have a look at Kevin Herreras implementation? |
public function __construct(SecureRandomInterface $secureRandom, $cost) | ||
{ | ||
$this->secureRandom = $secureRandom; | ||
$cost = (int)$cost; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing space after the type cast
@TerjeBr, yea, I took a look at the Herrera's implementation. I'll dig deeper when I finish the other issues. |
Note that it would be nice if you also support PHP 5.5 native function password_hash if available (see https://gist.github.com/3707231). You should probably enforce PASSWORD_BCRYPT instead of PASSWORD_DEFAULT to be sure that you use bcrypt though (it might change in later versions of PHP). |
I read the RFC about the PHP crypt API and it is very informative reading indeed. One thing we have done wrong is that the salt has no need to be cryptographically strong, and that a way better way to create the raw bytes used in the salt is to use the function mcrypt_create_iv() |
@TerjeBr the compat library already exists: https://github.com/ircmaxell/password_compat |
@stof Then it is all there more reason to just use that API then, since the compat library already exists. |
Okay, I'm done. I'd do more but I have very little spare time lately. If anyone thinks something else should be added, please open another PR after this one is merged. |
)); | ||
|
||
return new Reference('security.encoder.bcrypt'); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will not work if you define several encoders using bcrypt (for different classes) as you are forcing the id.
You should return the data needed to build the encoder instead, like done for other encoders
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you return the reference to the service "security.secure_random" then, that the bcrypt encoder needs in its constructor?
Symfony\Component\Security\Core\Encoder\EncoderFactory->createEncoder($config) only allows a plain array with no references to the DI container to be passed in $config['arguments'].
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, you may need to refactor some stuff. But the way you do it currently is broken as soon as you have several classes using bcrypt (they would all use the config of the last one, thus not respecting the cost)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess @elnur could take a look at how it is done in the method Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory->createAuthProvider()
There a new definition is created in the DI container for each instance. I guess that the same thing needs to be done here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another (and more clean solution) is to rewrite the class Symfony\Component\Security\Core\Encoder\EncoderFactory so that it does not try to create the Encoder objects on its own (using $reflection->newInstanceArgs()), but instead makes use of the DI to create a new service. In that way the created encoder service may depend on other services in a clean way. But that is a major rewrite of that class, so I guess it would have to be approved by @fabpot first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyone got any more input on how to resolve this?
@elnur do you have time to complete this PR ? |
I could do it. But only if the task is no longer assigned to @elnur |
Not yet. Still very busy. |
If it will wait until 2.3, I think I'll be able to finish it. |
I want to publish the last beta early next week. So, it that can be finished and reviewed by the end of this week, that can be included. |
@TerjeBr do you think you can do it this week ? If yes, it would be great. |
Well, yes, I guess I can, if I work on it also in the weekend. @elnur , do you have time today to check in what you have done already? (It is ok if it has buggy or non-working code.) |
So, did it make it into the beta? |
Closing in favor of #6808 |
This PR was submitted for the master branch but it was merged into the 2.2 branch instead (closes #6808). Commits ------- 0cb74a2 Added BCrypt password encoder. Discussion ---------- Bcrypt password encoder Bug fix: no Feature addition: yes Backwards compatibility break: no Symfony2 tests pass: yes Fixes the following tickets: #5932 License of the code: MIT Documentation PR: symfony/symfony-docs#1936 --------------------------------------------------------------------------- by TerjeBr at 2013-01-19T18:53:21Z Finishing PR #5974 --------------------------------------------------------------------------- by jalliot at 2013-01-20T14:07:54Z This looks very good! :) But be careful to CS or this will not be merged. --------------------------------------------------------------------------- by TerjeBr at 2013-01-20T14:17:35Z I do not understand. What do you mean by "CS"? --------------------------------------------------------------------------- by jalliot at 2013-01-20T14:20:33Z [Coding standards](http://symfony.com/doc/current/contributing/code/standards.html). You should run [PHP-CS-Fixer](https://github.com/fabpot/PHP-CS-Fixer) on your code to fix it. --------------------------------------------------------------------------- by TerjeBr at 2013-01-20T14:47:23Z The only thing php-cs-fixer.phar did was to realign some of the doc-block comments. But thank you any way for pointing out the script to me. --------------------------------------------------------------------------- by TerjeBr at 2013-01-20T15:52:07Z Why does it look like @elnur added the commits? It was me. --------------------------------------------------------------------------- by stof at 2013-01-20T16:32:12Z @TerjeBr check your git configuration to be sure it uses your email address when committing --------------------------------------------------------------------------- by TerjeBr at 2013-01-20T17:30:58Z Now the commit is in my name. But see what happens if I squash the commit wit git rebase .... --------------------------------------------------------------------------- by TerjeBr at 2013-01-20T17:33:08Z Now it looks like elnur added the commit. --------------------------------------------------------------------------- by stof at 2013-01-26T15:57:59Z @fabpot is there a chance to have this in 2.2 ?
Bug fix: no
Feature addition: yes
Backwards compatibility break: no
Symfony2 tests pass: yes
Fixes the following tickets: #5932
Todo: —
License of the code: MIT
Documentation PR: symfony/symfony-docs#1936