-
-
Notifications
You must be signed in to change notification settings - Fork 33.1k
Fixed #26033 -- Added argon2 password hasher. #5876
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
Thanks for the patch. Design decisions (such as the choice of what algorithms to support in core) are usually made on the django-developers mailing list. I would post this idea there to get feedback. |
Ok thanks. Post. |
Since Florian mentioned he’d like some feedback from me or @dstufft on the mailing list: Sadly I can’t really comment on the Django portions but the usage of Argon2 libraries is rather straight forward as long as you stay away from the I have two minor general comments:
|
This PR is ready to be merged. |
Is there a specific reason to go with the low_level api? |
django/contrib/auth/hashers.py
Outdated
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.
Please use argon2.DEFAULT_HASH_LENGTH
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.
Done. We do have to be careful: if argon2.DEFAULT_HASH_LENGTH
is increased significantly in the future, encode
can return a string longer than the maximum 128.
@apollo13 |
django/contrib/auth/hashers.py
Outdated
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.
Please use 4 space hanging indent:
argon2.low_level.hash_secret(
force_bytes(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.
Done.
@timgraham I saw you set the "missing documentation" label on the issue tracker. Could you help me out and tell me which documentation I should write? |
docs/topics/auth/passwords.txt -- see the similar docs for bcrypt there. Also a mention in the 1.10 release notes. p.s. You can squash commits too. |
django/contrib/auth/hashers.py
Outdated
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.
As above, please use hanging indent.
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.
Done.
@timgraham Thanks. I added the documentation and release notes. Please feel free to change the wording, tone and contents as you like. Before you merge, I will squash the commits. (For now it is easier to keep track of what changed in the PR.) By the way, |
docs/releases/1.10.txt
Outdated
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 other entries" isn't entirely accurate; very few websites well need to keep anything other than PBKDF2PasswordHasher
, the default hasher since Django got its current password hashing mechanism.
I would say:
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
]
If your database contains password encoded with other hashers, you need to add them to the list, or else the corresponding users won't be able to log in. See the documentation of :setting:PASSWORD_HASHERS
for details.
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.
Some people might blindly copy and paste the displayed code to enable Argon2, without reading the remark after it. It does not hurt to list all hashers, so that seems to me to be the safe choice.
This is also how the documentation is written to enable BCrypt. See topics/auth/passwords.txt
.
Off course, I could change it everywhere.
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.
Keeping it consistent is a reasonable choice for now. Leave it as is.
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 would link to "argon2_usage" instead of repeating the example usage parts of it in the release notes.
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.
docs/topics/auth/passwords.txt
Outdated
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'm going to suggest some edits to move argon2 discussion to a separate section with a few todos that I hope can complete: https://dpaste.de/aaF5 You can apply the patch with patch -p1 -i raw.diff
. Thanks, this is coming along!
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.
Done. I added some text on choosing parameters.
2d50fa6
to
57cf060
Compare
93c8ed5
to
abc48a3
Compare
docs/topics/auth/passwords.txt
Outdated
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.
Should we say what the defaults are? Should we consider increasing the defaults for each major release of Django like we do for PBKDF2? https://docs.djangoproject.com/en/dev/internals/howto-release-django/#new-stable-branch-tasks
Please use 1 space between sentences.
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.
It is a good idea to review the defaults for each major release. The analogue of the current rule would be to increase memory_cost
with approximately 20% for each major release. Maybe it would be a better idea to use actual hardware as a reference: adjust the parameters such that the hash takes a certain amount of milliseconds on the cheapest Amazon EC2 instance.
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.
Maybe coordinate changing the defaults with @hynek ?
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 defaults aren’t too likely to change very frequently since even the lowest settings are “safe enough”. Choosing the target verification time is highly individual so I guess the best approach for Django is to decide on a time and tune all checkers to meet it so people don't have to think about it? My own target was roughly 0.5ms–1ms “on my notebook”.
Could you add a |
The problem. The runtime of PBKDF2 is practically linear in the number of iterations. For argon2, it is more complex. If I am not mistaken, it's runtime is proportional to
The first term is for the main iteration of argon2, which goes over all blocks of memory Suppose we double the What to do?
The last would be the best mitigation of the issue at hand, but would over time give us a hash which is a lot weaker than it could have been. Option 2 would also work if a hash is replaced by a different, but slower hash (instead of just when the parameters are changed). |
I am leaning towards option one. The security fix is mainly for pbkdf2 On Wed, Mar 2, 2016, 14:54 Bas Westerbaan notifications@github.com wrote:
|
Argon2 is the winner of the Password Hashing Competition. https://password-hashing.net There are two python bindings available for Argon2: argon2 and argon2-cffi. The first uses ctypes and the latter cffi. As cffi works for most environments, I choose that one. Argon2 has four parameters: time_cost, memory_cost, parallelism and type. I choose to copy the defaults of argon2-cffi. Section 9 of the argon2 specification discusses recommended parameters. https://password-hashing.net/argon2-specs.pdf
@timgraham I added a no-op |
merged in b4250ea, thanks! |
We have a test failure with the release of argon2_cffi 16.1 which changes the hash and adds an extra dollar sign which causes problems with Django trying to split it. How do you think we should proceed? I guess updating Django and requiring the latest version of argon2_cffi might be okay. I just hope this won't be an ongoing issue where argon2_cffi makes changes that aren't compatible? |
Argon2 has a new version 1.3 that introduced a version tag. My suggestions:
JFTR Hashes are backward compatible. You can verif old hashes with the new release. |
I will write a patch for this this week. |
(Oh and I didn't change anything; it's the standard/official bindings that evolved.) |
I created a PR: #6489 |
argon2 is the winner of the Password Hashing Competition.
argon2
andargon2-cffi
. The first usesctypes
and the lattercffi
. Ascffi
works for most environments, I choose that one.argon2
has four parameters:time_cost
,memory_cost
,parallelism
andtype
. I choose to copy the defaults ofargon2-cffi
. Section 9 of the argon2 specification discusses recommended parameters.https://code.djangoproject.com/ticket/26033#ticket