
It's Dangerous, a Python cryptographic signing module - zachwill
http://packages.python.org/itsdangerous/
======
ctz
Use of SHA-1 for this signature/MAC purposes in new applications is deprecated
and will be disallowed from next year (source: NIST).

I repeat: do not use SHA-1 in new applications. Do not use this module.

~~~
Luit
Well then fork it and make it use HMAC with SHA256/512... Additionally, "Do
not use this module" is bad advice if it leads to someone making their own MAC
implementation, because that's almost always a bad idea. HMAC-SHA1 still is
good security for this purpose.

I bet that as soon as standards bodies (like NIST) actively encourage you to
use better hash functions (which they will probably do soon) the developer of
this module will decide on what is safe enough for this purpose.

~~~
gambler
You advise to "fork it", but immediately after that you add the notorious "do
not write your own" meme. Can you see the inconsistency of the messages?

Part of security is being up-to-date in regards to things like hashes. If
authors don't update their own libraries and you need to tweak them manually,
how is it different from "writing your own"?

~~~
ebiester
I always thought the advice against "writing your own" spoke of the algorithm
itself, not a library around the algorithm.

~~~
Locke1689
Nope. Google Keyczar: standard algorithms; still screwed up. You should always
use the highest level interface available.

------
tptacek
This facility is "built in" to Rails, with MessageEncryptor and
MessageVerifier. Before you consider writing your own "apply an HMAC-SHA1 hash
to a string" library in Ruby, just take those classes from ActiveSupport
instead. They've been reasonably well tested.

~~~
ashconnor
Alternatively, if you are not using Rails but are still using Ruby, then you
can use OpenSSL::HMAC.

~~~
tptacek
This is a MUCH WORSE IDEA. Don't do this. Even this Python wrapper library
does a better job providing HMAC services to users than OpenSSL's HMAC
primitive does. Leave OpenSSL:* to the suckers^H^H^H^H^H^H crypto library
implementors.

~~~
ashconnor
The wrapper is pretty elegant weighing in at 3 functions; it all depends on
how high-level you want to go.

If people are having trouble they can refer to the Rails ActiveSupport source
code for help.

------
__alexs
Do we really need an entire library to encapsulate
<http://docs.python.org/library/hmac.html> and string.rsplit?

~~~
tptacek
Yes, because Python's "hmac" library doesn't provide a secure "verify" method.

~~~
__alexs
Is == not good enough for you?

~~~
tptacek
Sigh.

<http://codahale.com/a-lesson-in-timing-attacks/>

Preemptively:

* Yes, a realistic attack.

* Yes, very difficult over the Internet.

* Still difficult but not implausible if the attacker can colocate near your app; ie, if you deploy anywhere on EC2.

* Measurement bounds are high nanoseconds LAN, tens of usecs WAN.

* HMAC verification, unlike password hash comparisons, is a place where timing actually does matter.

Not to suggest that I occupy the high road when it comes to snarky comments,
but consider whether your snarky comment in this case suggests an unearned
(and thus dangerous) level of confidence about crypto app security. This
problem (HMAC timing) is so well known that it's generated many hundreds of
comments over the years on HN.

~~~
__alexs
That's still a lot of code just to import a single 6 line function...

~~~
tptacek
The fact that he knew about that function and you (standing in as
"representative Python developer") did not seems to justify the library pretty
nicely from what I can tell.

But, obviously, this code does more than Python's hmac library does, beyond
just knowing how to properly verify the MAC itself.

~~~
__alexs
I wasn't criticising the security of this library, I was criticising it's
reason to exist in the form that it does.

~~~
pmylund
Nice save.

------
obiterdictum
Executive summary:

\- The signature: SHA1 HMAC of data and, optionally, a timestamp to expire
signatures.

\- HMAC key derivation: SHA1 of a secret key and a salt.

~~~
JoachimSchipper
> \- HMAC key derivation: SHA1 of a secret key and a salt.

Note to non-cryptographers: do not use low-entropy (password-ish) secretswith
this, they can be bruteforced. (Using bcrypt/scrypt/PBKDF2 instead would fix
this.)

~~~
the_mitsuhiko
> Note to non-cryptographers: do not use low-entropy (password-ish)
> secretswith this, they can be bruteforced. (Using bcrypt/scrypt/PBKDF2
> instead would fix this.)

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.

~~~
tptacek
Deriving secret keys for signing and encryption systems is the entire reason
PBKDF2 was designed. The parent comment doesn't suggest using a PBKDF2-type
construction to verify packets, but instead only to generate the secret key
used by HMAC-SHA1. That's a one-time operation.

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.

~~~
the_mitsuhiko
> The parent comment doesn't suggest using a PBKDF2-type construction to
> verify packets, but instead only to generate the secret key used by HMAC-
> SHA1. That's a one-time operation.

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.

~~~
tptacek
The salt in PBKDF2 used as a KDF does almost exactly the same thing as the
salt in a password hash: it prevents attackers from precomputing a huge
dictionary of candidate password-key mappings and employing it on every PBKDF-
keyed system the attacker finds. All secure password-handling schemes are
randomized.

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.

~~~
the_mitsuhiko
> I don't know what you mean by "lengthy secret key"

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

~~~
tptacek
Sure. Just know that developers sticking "c0mp4ny_n4m3" in their source file
as an AES or HMAC key is a very common problem. os.urandom is a fine solution
for the problem.

