Also, PBKDF2 has nothing whatsoever to do with rate limiting login attempts. The attack PBKDF2 tries to blunt is offline, not online. PBKDF2 and bcrypt remain effective even when the imposed expense of a single hash compare is less than the network overhead of making a login request.
I am officially an idiot now. I see where the original comment is going with. Namely the "salt" part of the library, not the verification of the signature. You can just use a different secret key or derive one yourself.
I sincerely apologize for missing that and the comments that resulted from that.
That said: the secret key is the important part there, not the salt. The salt is just used to alter the secret key that the use of the serializer in two different places for different purposes does not create the same signature. The intended usage of the whole thing is to not use the salt at all but to provide different secret keys. The "salt" part was taken from the original django implementation with the idea to stay mostly compatible with their format.
Could that be improved by switching to PBKDF2? Probably, but breaking a lengthy secret key is an impossible operation currently, even with SHA1.
> Also, PBKDF2 has nothing whatsoever to do with rate limiting login attempts.
That's not what I meant. I meant that PBKDF2 on a server is feasible because you can rate limit the endpoint. I don't want my servers to be on 100% CPU because someone spams the login form.
I don't know what you mean by "lengthy secret key", but if you're talking about a string that a human would recognize as language, that's not a strong key. Strong keys come from /dev/keygeneration --- er, I mean, /dev/random and from schemes like PBKDF2.
The attack on a human-intelligible crypto key occurs offline, and HMAC verifying keys are usually long-lived, so the attacker has both a lot of time and a lot of incentive to go after that key. Do not use human-intelligible strings as HMAC keys.
I've heard a lot of smart people worry about adaptive password hashes becoming a DOS vector for their application, and while stipulating that they are indeed smart people, they haven't thought this problem through very well. Every application can be DOS'd, usually in much more effective ways than by forcing the server to hash lots of passwords. Availability attack vectors in web apps are so common that they aren't even objectives on penetration tests; what would be the point?
Also, HMAC "authenticates" and "verifies" messages; it doesn't "sign" them. "Signature" has a subtly different meaning in crypto.
`os.urandom(120)` for instance. That's what Flask and Django document. I can see how this is not obvious from the documentation which puts a human readable string in there and I will update it appropriately.
> Also, HMAC "authenticates" and "verifies" messages; it doesn't "sign" them. "Signature" has a subtly different meaning in crypto.
I agree. The use of the word signing for this however is quite widespread and I adopted the same meaning (and implementation) as with the original Django one for compatibility.
(Alternative: drop the SHA1/bcrypt/whatever and just use a really strong secret key. 128 bits of randomness is impossible to brute-force.)
itsdangerous has nothing to do with passwords. It's about signing small messages and these messages are obviously created at runtime.
> nonsense and just use a really strong secret key
That's how you should use itsdangerous: use a strong secret key.
$ python
>>> import os
>>> os.urandom(64)
dd if=/dev/random bs=64 count=1 2>/dev/null | hexdump
The point of PBKDF2 and friends is to make it expensive to brute force acquired hashes. It effectively 'rate limits' hash-in-hand brute force attempts. It's designed to protect hashes once they are in hostile environments.
The use cases you described (session keys, activation links) are the perfect example of such environments.
It does not matter what hashing function you use for the login. It matters in case your database leaks.
> The use cases you described (session keys, activation links) are the perfect example of such environments.
They are not. Because you don't want to reverse engineer the contents of the message (the message is there in plain text). That's the reverse of what you want to do with passwords. In case of the password you want to brute force what the password is, in case of a signed message you want to forge a signature.
That was my point... I suppose I'm not sure I understood why you brought up login entry point rate limiting?
PBKDF2 for this would be possible, but a terrible idea. The reason why PBKDF2 works for password verification purposes on web apps is because you can rate limit the login entry point. Doing that for sessions or activation links like what you would use itsdangerous for is an easy way to have other people DDOS your app.
PBKDF2/bcrypt etc. is not the solution for this problem.