HMAC: add Blake2b signature algorithm
Hi, JWT has never formalized Blake2b as a signing algorithm, hence the BLAKE2B algorithm ID I chose in the code was made up by me and I don't know if this should be merged of not, maybe we could use the @experimental tag on the class, I don't know.
But if this is nowhere near a standard (in JWT I mean, Blake2b is a standard), why proposing it? Because of this:
+--------------+-------------------+-----+------+-----+----------+-----------+---------+
| benchmark | subject | set | revs | its | mem_peak | mode | rstdev |
+--------------+-------------------+-----+------+-----+----------+-----------+---------+
| EddsaBench | benchSignature | | 100 | 5 | 4.359mb | 20.221μs | ±2.59% |
| EddsaBench | benchVerification | | 100 | 5 | 4.359mb | 45.970μs | ±0.62% |
| Sha256Bench | benchSignature | | 100 | 5 | 4.359mb | 60.589μs | ±6.34% |
| Sha256Bench | benchVerification | | 100 | 5 | 4.359mb | 95.866μs | ±4.34% |
| Sha384Bench | benchSignature | | 100 | 5 | 4.359mb | 61.166μs | ±1.13% |
| Sha384Bench | benchVerification | | 100 | 5 | 4.359mb | 104.584μs | ±0.76% |
| Sha512Bench | benchSignature | | 100 | 5 | 4.359mb | 60.701μs | ±5.33% |
| Sha512Bench | benchVerification | | 100 | 5 | 4.359mb | 114.601μs | ±1.13% |
| Sha256Bench | benchSignature | | 100 | 5 | 4.359mb | 837.150μs | ±3.02% |
| Sha256Bench | benchVerification | | 100 | 5 | 4.359mb | 36.188μs | ±3.82% |
| Sha384Bench | benchSignature | | 100 | 5 | 4.359mb | 803.909μs | ±3.31% |
| Sha384Bench | benchVerification | | 100 | 5 | 4.359mb | 38.787μs | ±3.91% |
| Sha512Bench | benchSignature | | 100 | 5 | 4.359mb | 791.626μs | ±1.59% |
| Sha512Bench | benchVerification | | 100 | 5 | 4.359mb | 36.873μs | ±3.04% |
| NoneBench | benchSignature | | 100 | 5 | 4.359mb | 0.123μs | ±38.90% |
| NoneBench | benchVerification | | 100 | 5 | 4.359mb | 0.170μs | ±2.33% |
| Sha256Bench | benchSignature | | 100 | 5 | 4.359mb | 2.218μs | ±8.02% |
| Sha256Bench | benchVerification | | 100 | 5 | 4.359mb | 2.410μs | ±0.20% |
| Sha384Bench | benchSignature | | 100 | 5 | 4.359mb | 2.262μs | ±13.38% |
| Sha384Bench | benchVerification | | 100 | 5 | 4.359mb | 2.451μs | ±0.33% |
| Sha512Bench | benchSignature | | 100 | 5 | 4.359mb | 2.285μs | ±6.95% |
| Sha512Bench | benchVerification | | 100 | 5 | 4.359mb | 2.491μs | ±10.81% |
| Blake2bBench | benchSignature | | 100 | 5 | 4.359mb | 0.562μs | ±2.72% |
| Blake2bBench | benchVerification | | 100 | 5 | 4.359mb | 0.760μs | ±0.83% |
+--------------+-------------------+-----+------+-----+----------+-----------+---------+
Threw it out to pull in some attention: https://twitter.com/Ocramius/status/1511338900043841537
I'm okay too (100% agree with the documentation comments).
Looks okay to me, would you please add the docs?
Sure, tomorrow
Woah, this is great.
One consideration to check here: is the generated hash longer or shorter, and how much? A longer hash would mean lower CPU load, but higher I/O load.
I see Blake2B is supposed to produce 64 bytes? If that is the case, it is most likely a big win also for everything I/O related.
EDIT: as for security guarantees, it seems like Blake2b is theorically a lot better than sha256
I see Blake2B is supposed to produce 64 bytes?
It can range between 16 and 64, but default implementation including libsodium's one is 32 bytes, so same output length as sha256. the most common JWT sym-algo
For long-term tokens, a minimum of 24 bytes is required for collision resistance. 16 bytes are fine for short-lived tokens. 32 bytes are safe for all use cases, adds a security margin.
Using 64 bytes would be useless in the case of JWT.
Speed is the same regardless of the output size; what really matters is the block size (how many bytes are processed at one) and it is always 512 bits in BLAKE2b.
So, like @Slamdunk I'd also recommend using 32 bytes output.
BLAKE2b also accepts an optional "personalization" parameter (sometimes called "context" in other hash functions and constructions). The purpose is to produce a different output in case the same key is used in different contexts, in order to avoid cross-protocol attacks.
Setting it to a constant such as the "JWT" string may not be a bad idea.
BLAKE2b also accepts an optional "personalization" parameter
libsodium doesn't expose it on high-level API (see https://libsodium.gitbook.io/doc/hashing/generic_hashing#notes).
I like the idea but I want to stick to a standard implementation as much as possible.
I know, I'm libsodium's author :)
It's available as crypto_generichash_blake2b_salt_personal().
The parameter is available in all other BLAKE2b implementations as well.
Some interesting discussions in https://mailarchive.ietf.org/arch/msg/jose/YAQf8peqpqNTNpK2VJFFckbR1P4/. @jedisct1 maybe you can help out?
From that mail thread:
As for process for adding it, I would write Internet-Draft specifying the use in JOSE and then use the I-D as specification for expert review. One might do a comment round through this list first to catch the worst issues...
Sounds like it may take a while, if it ever happens at all.
From that mail thread:
As for process for adding it, I would write Internet-Draft specifying the use in JOSE and then use the I-D as specification for expert review. One might do a comment round through this list first to catch the worst issues...
Sounds like it may take a while, if it ever happens at all.
Like all standards. It take years for a proposal to become accepted as a standard, if that ever happens, and by the time it finally happens, the algorithm is already obsolete.
Like all standards. It take years for a proposal to become accepted as a standard, if that ever happens, and by the time it finally happens, the algorithm is already obsolete.
Yeap... looking at timelines as https://datatracker.ietf.org/doc/rfc8037/ makes me shiver... I don't have the capacity to create the draft (I'm even struggling to keep up with basic OSS).
We must decide if we want to push this further (just remove references from HMAC as native Blake2b MAC is different from HMAC-Blake2) and accept the usage of a non-standard algorithm or hold this until someone creates the Internet Draft and submit it for review (following RFC7518's procedure).
Even if not the case here, sigantures using BLAKE2B as hash would be significantly more problematic: The only space/time efficient signature algorithm allowing variable hashes that is even close to widespread is ECDSA, and ECDSA requires bit order of hash, which BLAKE2 just does not specify.
That bit also came from the thread and makes me feel like the "Designated Experts" might reject BLAKE2b's submission, idk. I'm honestly not knowledgeable enough on the nitty-gritty details of hashing to understand if not requiring bit order of hash would be a potential problem for Blake2b's adoption - I don't really mind the fact it's not widespread atm.
I'm generally okay with adding a non-standard algorithm if you're all up to it.
"de facto" standards work.
If common implementations are compatible with each other, this is enough to make something a lot of people can use and take advantage of.