Update PasswordEncoder Minimums
Based on https://github.com/spring-projects/spring-security/pull/10447#issuecomment-966593724, Argon2PasswordEncoder, ScryptPasswordEncoder, and Pbkdf2PasswordEncoder should have their minimums updated.
Please also see gh-7411 gh-4788
see also https://github.com/spring-projects/spring-security/issues/7411#issuecomment-531031619
Hi, did someone take this issue? I would like to contribuite.
@ioanadinuit, thanks for volunteering! The ticket is yours.
One thing we need to keep in mind is what will happen to folks when they upgrade to Spring Security 6.
Ideally, existing hashes will still work which is not as simple with Pbkdf2PasswordEncoder, which does not support upgrading. It may be necessary to implement https://github.com/spring-projects/spring-security/issues/9833 before changing PBKDF2 default settings.
@Sc00bz, I'd prefer to go off of the recommendations on the OWASP cheat sheet. They vary just slightly from your recommendations in your comment. Do you have any concerns with going with the recommendations from the cheat sheet?
Please also see gh-7411
@jzheaux That OWASP cheat sheet is based on my recommendations.
The four changes I suggested to this project's defaults:
Argon2's setting are
m=4 MiB, t=3, p=1either set it to 10 MiB or 7 iterations.
OWASP cheat sheet has for Argon2:
m=37 MiB, t=1, p=1m=15 MiB, t=2, p=1
The curator trimmed the list at the first two. Numbers came from these formulas:
Argon2i: m≥74219/(3*t-1)*α, t≥3, p=1
Argon2{id,d}: m≥74219/(3*t-1)*α, t≥1, p=1
m≥36.24 MiB, t=1, p=1
m≥14.50 MiB, t=2, p=1
m≥9.06 MiB, t=3, p=1 ****
...
m≥4.26 MiB, t=6, p=1
m≥3.62 MiB, t=7, p=1 ****
scrypt's settings are
N=2^14, r=8, p=1(16 MiB) either setNto 2^16 (64 MiB) orpto 4.
OWASP cheat sheet has for scrypt:
N=2^16 (64 MiB), r=8 (1024 bytes), p=1****N=2^15 (32 MiB), r=8 (1024 bytes), p=2N=2^14 (16 MiB), r=8 (1024 bytes), p=4**** ...
PBKDF2 settings are SHA1, 185k iterations, 256 bits of output. This should be changed to SHA512 and 120k iterations.
OWASP cheat sheet has for PBKDF2:
PBKDF2-HMAC-SHA1: 720,000 iterations PBKDF2-HMAC-SHA256: 310,000 iterations PBKDF2-HMAC-SHA512: 120,000 iterations ****
Note using SHA512 is better than the others if the one calculating it has a 64 bit CPU. SHA1 and SHA256 are better if the one calculating it has CPU instructions for them.
bcrypt setting is cost 10. Cost 9 is actually quite strong and is similar to PBKDF2-SHA512 with 230k iterations in strength.
It was a hard fought battle to get the recommended down to cost 10. Note cost "8.1" is the minimum for bcrypt, but it's an integer so 9.
P.S. A new GPU came out since those recommendations. It's ~3% faster compute and 20% more memory bandwidth.
Argon2 m=4 MiB, t=7, p=1 is now m=4 MiB, t=8, p=1.
Argon2 m=10 MiB, t=3, p=1 is now m=11 MiB, t=3, p=1.
scrypt N=2^16 (64 MiB), r=8 (1024 bytes), p=1 is now N=2^17 (128 MiB), r=8 (1024 bytes), p=1
scrypt N=2^14 (16 MiB), r=8 (1024 bytes), p=4 is now N=2^14 (16 MiB), r=8 (1024 bytes), p=5
PBKDF2-HMAC-SHA512 120,000 iterations is now 130,000 iterations.
bcrypt is still cost 9.
Note this is how minimums work. Normally every year a new GPU comes out that's 20%+ faster. Last few years have been abnormal. If I were to guess, I'd guess there's going to be a jump in minimums around October.
Please see gh-4788
@Sc00bz Thanks for the updated numbers. The trouble is that we don't know what hardware users are leveraging to run their servers and minimums are a tradeoff. The attackers will always have better optimized hardware for cracking than the defenders will for validating passwords because the defenders need to do more than passwords and it is unlikely they will leverage GPUs. It's all about trade offs. Using a workfactor that is too large will potentially cause a DoS for the application servers.
The best we can do is follow the guidance for now and ensure we can support upgrading in the future. This is why we are also looking to implement gh-9833
... the defenders need to do more than passwords and it is unlikely they will leverage GPUs.
Argon2, bcrypt, PBKDF2, and scrypt can't run on a GPU for the defender. Well they could but it would be very slow. Minimums are set to prevent attackers from getting >10 kH/s/GPU.
Using a workfactor that is too large will potentially cause a DoS for the application servers.
Note bcrypt cost 9 is super fast because it is a good algorithm. PBKDF2-HMAC-SHA512 with 130,000 iterations is slow because PBKDF2 is a bad algorithm. If bad algorithms are causing DoS issues, then you should deprecate those algorithms.
@Sc00bz There are tradeoffs to setting the work factor and recommended settings are the deployed environment (i.e. hardware) of the application which as a framework we don't have access to. We can certainly do our best approximate, but it is just that.
Argon2, bcrypt, PBKDF2, and scrypt can't run on a GPU for the defender.
PBKDF2 is not resistant to GPU attacks. PBKDF2 is typically recommended for when compliance is necessary (i.e. NIST and FIPS)
Note bcrypt cost 9 is super fast because it is a good algorithm.
BCrypt is good, but it has little to do with being fast. In fact the opposite is true. The goal of password storage is to discourage an attacker from cracking the password by requiring too many resources (memory, CPU, time, money, etc) to make it worth their while which means they should be slow.
PBKDF2-HMAC-SHA512 with 130,000 iterations is slow because PBKDF2 is a bad algorithm. If bad algorithms are causing DoS issues, then you should deprecate those algorithms.
Modern password storage is designed to be future proof by adjusting the work factor. Specifically work factor is designed to be increased over time as hardware becomes more powerful and cheaper. If it takes too long today, then the work factor is not appropriate today but likely will be in the future.