w3c / webcrypto

The W3C Web Cryptography API
https://w3c.github.io/webcrypto/
Other
265 stars 53 forks source link

Add support for BLAKE2 (RFC7693) #313

Open Jorropo opened 2 years ago

Jorropo commented 2 years ago

Description

BLAKE2 is a fast software friendly hash function. It is also a SHA3 finalist.

I would like to add it to as an optional part of the webcrypto API.

Spec

it can be found here:

Tests

There is an extensive test vector list available here https://github.com/BLAKE2/BLAKE2/tree/master/testvectors (CC0 1.0 Universal license).

Support

It is already supported into many cryptographic libraries, and implementing it is really easy, so it shouldn't be lots of work to implement for vendors.

Reasons BLAKE2 is a usefull hash function

JS API

Using it would be similar to the current SHA extension. Consumers would call crypto.subtle.digest with the name, data and optionally the key and get returned a promise, that when resolved would return the digest body.

Name and variants

BLAKE2{s,b}-$SIZE

(note this proposal doesn't include BLAKE2x (arbitrarily sizable digests) or BLAKE2{s,b}p (parallel variant with reduced block depency for increased performance), this proposal stick to RFC7693)

So that allows you to combine them to make the name to pass to digest. For example:

Vendors are allowed to only support either of the variant if they wish too.

Normative restriction on variant support

If a vendor support any digest size of a variant, they must also support all other available digest sizes. So supporting BLAKE2b-512 require you to also supports BLAKE2b-8, BLAKE2b-16, ...

The reason to do this is that the digest size is not actually part of the algorithm, but only a parameter.

Optional key parameter

Unlike SHA, BLAKE2 accepts a key (bytes) that is 0 <= x <= (blocksize/2) big. This can be passed as an optional third parameter to digest.

If the key is undefined, then assume a 0 sized key. Else if the type does not match BufferSource throw with TypeError. Else if the key is bigger than allowed throw with DataError.

Note the optional here, means optional to consumers, not vendors, vendors MUST support the key parameter if they want to support BLAKE2.

Return value

An ArrayBuffer containing the resulting digest, and sized matching the size parameter.

Usage example

function buf2hex(b) { return [...new Uint8Array(b)].map(x => x.toString(16).padStart(2, '0')).join('') }

const body = new TextEncoder("utf-8").encode("hello")
const h1 = crypto.subtle.digest("BLAKE2b-256", body)

const key = new TextEncoder("utf-8").encode("world")
const h2 = crypto.subtle.digest("BLAKE2s-128", body, key)

console.log(buf2hex(await h1)) // 324dcf027dd4a30a932c441f365a25e86b173defa4b8e58948253471b81b72cf
console.log(buf2hex(await h2)) // d956ebc7895f6f2f0d00b5ad04b10749

Implementation interest

I currently have personal interest into getting this added. I can draft a spec PR and make a W3C's testsuite friendly version of the already existing test cases if reception seems positive. I'm also interested into implementing this into the major engines.

twiss commented 2 years ago

Hello :wave: Thanks for the detailed proposal, and apologies for the delayed response.

To me, adding BLAKE2 seems a bit specific: SHA-3 is probably more widely used, and BLAKE3 is probably faster. So perhaps it makes more sense to wait until there's an RFC for BLAKE3 and then add that?

That being said, if you want to propose to add it, the process is outlined here: https://github.com/w3c/webcrypto/issues/280#issuecomment-1151509624.

One minor, much more specific comment if you do so: I wouldn't add the digest size in the algorithm name. Algorithms can have parameters, so you could have for example { name: 'BLAKE2b', length: 256 } as the algorithm identifier. And then, you could also add the key as an optional property of that object, rather than adding a new parameter to subtle.digest. See HkdfParams for inspiration, for example.

Neustradamus commented 2 years ago

To follow it :)