Breaking SHA256: length extension attacks in practice
kerkour.com
kerkour.com
My impression was that H(s||m) was reasonable with e.g. SHA-3, assuming you have a fixed key size. The only downside I can think of is that you have to remember not to do it with variable length keys or with SHA-2. Am I missing something?
https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.S...
HopMAC(K,M)=H(K || H(M))
HMAC(K,M)=H(K || H(K || M))
[0]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-kangarootwe...
[1]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.S...The big reason I can think of not to use H(k, m) (or hand-rolled SHA3 KMAC) is that it will quietly fail open if you switch to a normal SHA2 hash.
I think (and to be clear this is just addressed at the world as a lament, not directed at you) the issue is that people have an incorrect concept of what the phrase "rolling your own cryptography" even means; when I give talks on security, I always note that while there are tricky issues with some primitives for some use cases involving stuff like "does your code leak information via timing, power usage, caches, etc." that by-and-large the issue isn't about implementing a well-established low-level primitive--or, I will claim (maybe to my peril! ;P), even a high-level protocol--yourself instead of using an existing implementation: it is about coming up with your own design, whether it be your own checksum / hash function / signature algorithm... or your own protocol / scheme for using these primitives to accomplish a goal, as the stuff you will do wrong is not knowing all the corner cases in how to wield the pieces as these low-level cryptographic primitives are not and pretty much can't be leak-proof abstractions: they are little bits of math that often have to be used exactly correctly and even then only still provide some level of protection / risk mitigation against an adversary... when developers waltz in and assume the low-level hash function is in some sense perfect and provides some unbreakable abstract functionality, you are going to think something is trivial that is in fact very very hard.
Or you can use a hash where the internal state is larger than the output, which is the case of SHA3.
Note that this just protects against length extension, these are not MACs.
Side note. The problem with JWTs is bigger than this. I "steal" web tokens all the time to get access to stuff outside the context the tokens were handed out in. If someone comes up with something really clever in this area there is money to be made.
And isn't this the same as stealing a cookie or something?
What about `H(s || m || s)`?
[1] https://doi.org/10.1007/978-3-540-73458-1_26
Like if your db is mongo and the 12 byte ID != 12 byte of secure randomness:
https://www.mongodb.com/docs/manual/reference/method/ObjectI...
I think the OP point still stands, just use HMAC instead of inventing crypto schemes.
HMAC(secret, username || email)
Imagine you have `bob` and `bob@example.com` as inputs. This HMAC can trivially be reused (or learned) by registering `bobb` and `ob@example.com`.If you ever have multiple fields being concatenated, use fixed-width length prefixes before each field:
HMAC(secret, 0x0003 || bytes("bob") || 0x000e || bytes("bob@example.com"))I always just serialize the inputs with JSON or something. Any weirdness an attacker might try would just be escaped so they'll never be able to match the original input.
Completely valid point, I was asking purely out of curiosity since this isn't my area of expertise but I find these kinds of vulnerabilities intriguing.
The solution newer algorithms seem to have settled on is to instead get fancier in the finalization step, for example by having internal state that doesn't make it into the final hash but would be required to compute the longer hash (just like using SHA512/256 to avoid length extension attacks).
Length extension attacks are in every crypto 101 class, everyone who designs crypto systems knows about them and acts accordingly. For example by using Galois field arithmetic to generate authentication codes, not hash functions (bonus: it is faster).
The OP advice is reasonable... just use HMAC. As far as I know it always available if hash is.
Not sure why it was removed, that makes the whole thing much more interesting to me.