I am using the javascript WebCrypto API window.crypto.subtle.deriveKey() API to generate HMAC keys like this:

this.key = await window.crypto.subtle.deriveKey(
    name: "PBKDF2",
    salt: someSalt, 
    iterations: 50000,
    hash: "SHA-1"
  // default length value!
  { name: "HMAC", hash:"SHA-256"},
  [ "sign", "verify" ]

now, here is what the documentation on the MDN site https://developer.mozilla.org/en-US/docs/Web/API/HmacKeyGenParams mentions about the key length:

The HmacKeyGenParams dictionary of the Web Crypto API represents the object that should be passed as the algorithm parameter into SubtleCrypto.generateKey(), when generating a key for the HMAC algorithm.

A DOMString. This should be set to HMAC.
A DOMString representing the name of the digest function to use. You can pass any of SHA-1, SHA-256, SHA-384, or SHA-512 here.
length Optional
A Number — the length in bits of the key. 
If this is omitted the length of the key is equal to the length of the digest generated by the digest function you have chosen.
Unless you have a good reason to use a different length, omit this property and use the default.

It basically says that the default length of the key is the length of the digest (in bits). I was expecting a key length equal to 256 bits assuming that the digest size in bits for SHA256 is 256. However, dumping the object returned by deriveKey() into the developer console reveals a length of 512 bits (both for chrome and firefox - pretty recent versions). Leaving apart that this kind of issues are difficult to discover and debug (since initially you see that some message digest computed somewhere else does not match the one computed in the browser), after fixing the issue (by using an explicit length of 256 bits) there are some things which I still do not understand:

  1. Which standard recommends the key length for HMAC based signing, authentication aso?
  2. Is there a bug in the WebCrypto API documentation or in its implementation?
  3. Which is the optimal/recommended key length for HMAC(SHA256) based signing?

deriveKey() is documented here on the MDN site: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveKey

  1. NIST SP 800-107, section 5.3.4 which reads

Let C denote the bit length of the internal hash value that is denoted H in FIPS 180-4. (This H is often called the “chaining value” in descriptions of Merkle–Damgård-style hash functions.) Note that C is not (necessarily) equal to L, the bit length of the hash function’s output (see, for example, SHA-384 or SHA-512/t for any t < 512, for which L < 512 = C). In all currently approved hash functions, L ≤ C (with L = C for SHA-1, SHA- 256, and SHA-512).

The effective security strength of the HMAC key is the minimum of the security strength of K and the value of 2C. That is, security strength = min(security strength of K, 2C).

  1. It looks like the API aims to produce HMACS with security strength of 512-bits according to the NIST document, though it also appears that the API comments do not reflect this. I would assume that the intent is to follow NIST and the documentation is at fault.

  2. Following the NIST publication, a uniform random 512-bit key would be required to make best use of the full security offered by the SHA-256 algorithm.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.