mdn / content

The content behind MDN Web Docs
https://developer.mozilla.org
Other
9.16k stars 22.46k forks source link

No example for using HKDF #25216

Closed owlstead closed 1 year ago

owlstead commented 1 year ago

MDN URL

https://developer.mozilla.org/en-US/docs/Web/API/HkdfParams

What specific section or headline is this issue about?

The direction to the examples for the DeriveKey function

What information was incorrect, unhelpful, or incomplete?

The link to the DeriveKey function is there for the examples, but only key agreement and password based key derivation are shown there.

What did you expect to see?

An example on the linked-to page.

Do you have any supporting links, references, or citations?

No response

Do you have anything more you want to share?

If pressed I can look and see if I can create an example.

MDN metadata

Page report details * Folder: `en-us/web/api/hkdfparams` * MDN URL: https://developer.mozilla.org/en-US/docs/Web/API/HkdfParams * GitHub URL: https://github.com/mdn/content/blob/main/files/en-us/web/api/hkdfparams/index.md * Last commit: https://github.com/mdn/content/commit/387d0d4d8690c0d2c9db1b85eae28ffea0f3ac1f * Document last modified: 2023-02-20T04:32:55.000Z
wbamberg commented 1 year ago

If pressed I can look and see if I can create an example.

That would be great! Alternatively, could you review an example if someone else wrote one?

owlstead commented 1 year ago

Sure, I would even prefer a review. I do security reviews (e.g. at codereview.stackexchange.com but I'm not a Javascript developer at heart. That means that I can write a perfect example, but I would use Javascript as if it was Java. More precisely, I would merge the PBKDF2 example with an answer on StackOverflow.

wbamberg commented 1 year ago

@owlstead , I made a PR to the examples repo at https://github.com/mdn/dom-examples/pull/212. Please review!

I thought I would be able to do something like this:

  function deriveSharedSecret(privateKey, publicKey) {
    return window.crypto.subtle.deriveKey(
      {
        name: "ECDH",
        public: publicKey,
      },
      privateKey,
      "HKDF",
      false,
      ["deriveKey"]
    );
  }

...to make the HKDF key derivation key, and this seems to work in Chrome, but in Firefox I get an "Operation is not supported" exception. But the deriveBits->importKey version from https://stackoverflow.com/questions/67938461/web-cryptography-implement-hkdf-for-the-output-of-ecdh/67942717#67942717 seems to work in both.

owlstead commented 1 year ago

Ugh, I don't know why WebCryptoAPI lets you jump through hoops like that. Usually you call deriveXxx because you want to create a key. If you need to call deriveBits and then importKey then I seriously doubt what the use is of deriveKey.

I'm not entirely sure about above code though. For starters, it doesn't seem to use the params as defined here, but seems to use the params for ECDH key agreement instead.

I'd rather expect something like:

  return window.crypto.subtle.deriveKey(
    {
      name: "HKDF",
      hash:  {name: "SHA-256"} ,
      salt: new ArrayBuffer(0),
      info: new ArrayBuffer(0)
    },
    masterKey,
    {
      name: "AES-GCM", // this is an API error, it should just be "AES" if anything
      length: 256
    },
    false,
    ["encrypt", "decrypt"]
  );

No doubt the master key should have option deriveKey enabled, and maybe it needs to be of type "HMAC" (I hope not, but it could be).

wbamberg commented 1 year ago

Thanks for taking a look, @owlstead .

I'm not entirely sure about above code though. For starters, it doesn't seem to use the params as defined here, but seems to use the params for ECDH key agreement instead.

The code I quoted above is not the HKDF key derivation code though, it's the ECDH code that we use to generate input key material for the the HKDF key derivation.

Because AIUI HKDF is used to derive keys from some already high-entropy input, like an ECDH shared secret: so we can use it to generate multiple keys from a single input key.

The part of the PR where we actually use HKDF is https://github.com/mdn/dom-examples/pull/212/files#diff-344a17c835ad74d9a93e418382a02c38b8cd916a7d6f654152f3cfdc19b4a1d2R18-R35:

  /*
  Given some key material and some random salt,
  derive an AES-GCM key using HKDF.
  */
  function getKey(keyMaterial, salt) {
    return window.crypto.subtle.deriveKey(
      {
        name: "HKDF",
        salt: salt,
        info: new Uint8Array("Encryption example"),
        hash: "SHA-256",
      },
      keyMaterial,
      { name: "AES-GCM", length: 256 },
      true,
      ["encrypt", "decrypt"]
    );
  }
owlstead commented 1 year ago

Ah, yeah, if that can be pointed to then that would be fine! Sorry, I didn't know that it took 2 links, and a page source -> view javascript to get to it.

wbamberg commented 1 year ago

Ah, yeah, if that can be pointed to then that would be fine! Sorry, I didn't know that it took 2 links, and a page source -> view javascript to get to it.

It doesn't: the code for this example is in a different repository, so it's in a different PR: https://github.com/mdn/dom-examples/pull/212 and can be reviewed there like any other PR. I just wanted to link to the exact bit of that PR in my comment, to make it clearer.

owlstead commented 1 year ago

Do you know if there are any specific requirements with regard to the input parameters? In that case that kind of info could be added. If not I'll hit accept I guess.