Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[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

Closed
wants to merge 2 commits into from

Conversation

elnur
Copy link
Contributor

@elnur elnur commented Nov 10, 2012

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

@mvrhov
Copy link

mvrhov commented Nov 10, 2012

@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...

@elnur
Copy link
Contributor Author

elnur commented Nov 10, 2012

@mvrhov, what do you mean by all bcrypt password hashing algorithms?

@mvrhov
Copy link

mvrhov commented Nov 10, 2012

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.

@elnur
Copy link
Contributor Author

elnur commented Nov 10, 2012

@mvrhov, as you can see, my current implementation of the encoder generates a salt 22 characters long, but thanks for pointing me to SecureRandom — I'll take a look at it.

@TerjeBr
Copy link

TerjeBr commented Nov 15, 2012

Please have a look at
Terjes BcryptEncoder

You should at least copy my code in function gensalt_blowfish($random) for generation of the salt.
The code you have is all wrong when it comes to generating the salt.
base_convert only returns 36 possible 'digits', and it is supposed to be 64!

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?
Then that part of the code can easily be replaced.

Terje

@maoueh
Copy link
Contributor

maoueh commented Nov 15, 2012

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 SecureRandom will need to be changed. I'm pretty sure @elnur will update is code to use SecureRandom when he will have the time.

@TerjeBr
Copy link

TerjeBr commented Nov 15, 2012

@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.
Also, in newer PHP implemetations the prefix in the salt should be $2y$ and not $2a$.

@maoueh
Copy link
Contributor

maoueh commented Nov 15, 2012

@TerjeBr Agreed. Maybe you can send a PR to @elnur repository so he can include your changes more easily? Or maybe he prefer to do it by himself?

@TerjeBr
Copy link

TerjeBr commented Nov 15, 2012

How do I make a Pull Request then?
I am new to this github thing.

@maoueh
Copy link
Contributor

maoueh commented Nov 15, 2012

First, you fork symfony repository if not have done so already by using the fork button above.

You then clone your fork

git clone [email protected]:TerjeBr/symfony.git

Add elnur repository in your own symfony repo fork:

cd symfony
git remote add elnur git://github.com/elnur/symfony.git

You fetch his repo to get his branches and checkout a new branch tracking his bcrypt-password-encoder branch:

git fetch elnur
git checkout -b bcrypt-password-encoder-modif elnur/bcrypt-password-encoder

At this point, you have his code and you make modifications. You commit your changes then push to your own repository:

... add & commit here
git push origin bcrypt-password-encoder-modif

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 elnur/symfony repo. In head repo, keep yours. For the base branch choose bcrypt-password-encoder and for the head branch choose bcrypt-password-encoder-modif.

That should do the trick.

@alvarezmario
Copy link
Contributor

@TerjeBr
Copy link

TerjeBr commented Nov 15, 2012

#6023

Will this do?

@maoueh
Copy link
Contributor

maoueh commented Nov 15, 2012

@TerjeBr No, you should send your PR to elnur/symfony repository instead so you collaborate with him instead of sending a new PR on the symfony/symfony repository. @elnur will merge your changes and those will appear in this very PR after he did the merge.

Follow those instructions that are a bit different:

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 elnur/symfony repo. In head repo, keep yours. For the base branch choose bcrypt-password-encoder and for the head branch choose bcrypt-password-encoder-tb.

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.

@TerjeBr
Copy link

TerjeBr commented Nov 15, 2012

@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.
The line breaks is so the lines will not go off my 80 char wide editor screen.

How do I update the pull request then to also have the latest changes I did?

@TerjeBr
Copy link

TerjeBr commented Nov 15, 2012

Ok, ignore my last question. I just saw that the pull request had updated itself.

@maoueh
Copy link
Contributor

maoueh commented Nov 15, 2012

@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.

@elnur
Copy link
Contributor Author

elnur commented Nov 16, 2012

I'll switch to SecureRandom and add documentation during this weekend. Also I'll take look at @TerjeBr's suggestions.

*/
public function encodePassword($raw, $salt = null)
{
$salt = $this->generateSalt();
Copy link
Member

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.

Copy link

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)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Thanks.

@elnur
Copy link
Contributor Author

elnur commented Nov 18, 2012

@fabpot, @stof, can we require PHP >= 5.3.7 for Symfony because of the security fix of the Blowfish algorithm?

@schmittjoh
Copy link
Contributor

It's probably a better idea to just raise an exception for older PHP versions.

@elnur
Copy link
Contributor Author

elnur commented Nov 18, 2012

@schmittjoh, an exception stating they need to upgrade PHP or what?

@schmittjoh
Copy link
Contributor

Yeah. We have other algorithms which one can use with older versions, there
is no need to support blowfish on them if it has a security vulnerability.

On Sun, Nov 18, 2012 at 7:58 PM, Elnur Abdurrakhimov <
[email protected]> wrote:

@schmittjoh https://github.com/schmittjoh, an exception stating they
need to upgrade PHP or what?


Reply to this email directly or view it on GitHubhttps://github.com//pull/5974#issuecomment-10489792.

@TerjeBr
Copy link

TerjeBr commented Nov 18, 2012

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

@elnur
Copy link
Contributor Author

elnur commented Nov 18, 2012

@schmittjoh, okay, I'll sleep on this. :)

@TerjeBr
Copy link

TerjeBr commented Nov 18, 2012

@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;
Copy link
Member

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

@elnur
Copy link
Contributor Author

elnur commented Nov 19, 2012

@TerjeBr, yea, I took a look at the Herrera's implementation. I'll dig deeper when I finish the other issues.

@TerjeBr
Copy link

TerjeBr commented Nov 19, 2012

@jalliot commented in my PR:

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).

@TerjeBr
Copy link

TerjeBr commented Nov 19, 2012

I read the RFC about the PHP crypt API and it is very informative reading indeed.
May be we should just use that API, and implement a copy of the API in PHP for those versions of PHP that does not have it?

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()

@stof
Copy link
Member

stof commented Nov 21, 2012

@TerjeBr the compat library already exists: https://github.com/ircmaxell/password_compat

@TerjeBr
Copy link

TerjeBr commented Nov 21, 2012

@stof Then it is all there more reason to just use that API then, since the compat library already exists.

@elnur
Copy link
Contributor Author

elnur commented Dec 1, 2012

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');
}
Copy link
Member

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

Copy link

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'].

Copy link
Member

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)

Copy link

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.

Copy link

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.

Copy link

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?

@stof
Copy link
Member

stof commented Jan 11, 2013

@elnur do you have time to complete this PR ?

@TerjeBr
Copy link

TerjeBr commented Jan 11, 2013

I could do it. But only if the task is no longer assigned to @elnur

@elnur
Copy link
Contributor Author

elnur commented Jan 15, 2013

Not yet. Still very busy.

@stof
Copy link
Member

stof commented Jan 15, 2013

@fabpot is there a chance to still include it in 2.2 if @TerjeBr completes this quickly or is it too late and should wait until 2.3 ?

@elnur
Copy link
Contributor Author

elnur commented Jan 15, 2013

If it will wait until 2.3, I think I'll be able to finish it.

@fabpot
Copy link
Member

fabpot commented Jan 15, 2013

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.

@stof
Copy link
Member

stof commented Jan 15, 2013

@TerjeBr do you think you can do it this week ? If yes, it would be great.

@TerjeBr
Copy link

TerjeBr commented Jan 15, 2013

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.)

@TerjeBr TerjeBr mentioned this pull request Jan 19, 2013
@TerjeBr
Copy link

TerjeBr commented Jan 26, 2013

So, did it make it into the beta?

@fabpot
Copy link
Member

fabpot commented Feb 5, 2013

Closing in favor of #6808

@fabpot fabpot closed this Feb 5, 2013
fabpot added a commit that referenced this pull request Feb 5, 2013
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 ?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants