SubtleCrypto.deriveKey()

The SubtleCrypto.deriveKey() method returns a Promise of a newly generated CryptoKey derivated from a master key and a specific algorithm given as parameters.

Syntax

var result = crypto.deriveKey(algo, masterKey, derivedKeyAlgo, extractable, keyUsages);

Parameters

  • algo is an object defining the derivation algorithm to use. Supported values are:
    • {"name": "ECDH", "public": publicKey}
    • {"name": "DH", "public": publicKey}
    • {"name": "PBKDF2", salt, iterations, hash} where salt is an ArrayBuffer or an ArrayBufferView, iterations is the number of iterations and hash is a DOMString identifying the hashing algorithm to use.
    • {"name": "HKDF-CTR", hash, label, context}
  • masterKey is a CryptoKey representing the master key to be used by the key derivation algorithm.
  • derivedKeyAlgo is an object defining the algorithm the derived key will be used for or a DOMString as a shortcut for {"name": derivedKeyAlgo}. For AES a length property is also required, possible values are 128, 192 or 256 bits.
  • extractable is a Boolean indicating if the key can be extracted from the CryptoKey object at a later stage.
  • keyUsages  is an Array indicating what can be done with the derivated key. Possible values of the array are:
    • "encrypt", allowing the key to be used for encrypting messages.
    • "decrypt", allowing the key to be used for decrypting messages.
    • "sign", allowing the key to be used for signing messages.
    • "verify", allowing the key to be used for verifying the signature of messages.
    • "deriveKey", allowing the key to be used as a base key when deriving a new key.
    • "deriveBits", allowing the key to be used as a base key when deriving bits of data for use in cryptographic primitives.
    • "wrapKey", allowing the key to wrap a symmetric key for usage (transfer, storage) in unsecure environments.
    • "unwrapKey", allowing the key to unwrap a symmetric key for usage (transfer, storage) in unsecure environments.

Return value

Exceptions

The promise is rejected when one of the following exceptions are encountered:

  • InvalidAccessError when the master key is not a key for the requested derivation algorithm or if the CryptoKey.usages value of that key doesn't contain "deriveKey".
  • NotSupported when trying to use an algorithm that is either unknown or isn't suitable for derivation, or if the algorithm requested for the derived key doesn't define a key length.
  • SyntaxError when keyUsages is empty but the unwrapped key is of type "secret" or "private".

Example

Here's an example showing how to use deriveKey() to create a Secure Remote Password (also known as Proof of Secret) from a user's password.

// salt should be Uint8Array or ArrayBuffer
var saltBuffer = Unibabel.hexToBuffer('e85c53e7f119d41fd7895cdc9d7bb9dd');

// don't use naïve approaches for converting text, otherwise international
// characters won't have the correct byte sequences. Use TextEncoder when
// available or otherwise use relevant polyfills
var passphraseKey = Unibabel.utf8ToBuffer("I hëart årt and £$¢!");

// You should firstly import your passphrase Uint8array into a CryptoKey
window.crypto.subtle.importKey(
  'raw', 
  passphraseKey, 
  {name: 'PBKDF2'}, 
  false, 
  ['deriveBits', 'deriveKey']
).then(function(key) {

  return window.crypto.subtle.deriveKey(
    { "name": 'PBKDF2',
      "salt": saltBuffer,
      // don't get too ambitious, or at least remember
      // that low-power phones will access your app
      "iterations": 100,
      "hash": 'SHA-256'
    },
    key,

    // Note: for this demo we don't actually need a cipher suite,
    // but the api requires that it must be specified.

    // For AES the length required to be 128 or 256 bits (not bytes)
    { "name": 'AES-CBC', "length": 256 },

    // Whether or not the key is extractable (less secure) or not (more secure)
    // when false, the key can only be passed as a web crypto object, not inspected
    true,

    // this web crypto object will only be allowed for these functions
    [ "encrypt", "decrypt" ]
  )
}).then(function (webKey) {

  return crypto.subtle.exportKey("raw", webKey);

}).then(function (buffer) {

    var proofOfSecret = Unibabel.bufferToHex(buffer);
    // this proof-of-secret / secure-remote password
    // can now be sent in place of the user's password
});

Note: Because there are no native tools to convert between Uint8Array, Unicode, hex, and base64, you'll probably want to use something like Unibabel or Buffer to convert between them.

Specifications

Specification Status Comment
Web Cryptography API
The definition of 'SubtleCrypto.deriveKey()' in that specification.
Candidate Recommendation Initial definition.

Browser compatibility

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support 37 34 (34) No support ? No support
PBKDF2 42 34 (34) No support ? No support
HKDF-CTR 42 No support No support No support No support
DH No support 35 (35) No support No support No support
Feature Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support (Yes) 37 34.0 (34) No support ? No support
PBKDF2 (Yes) 42 34.0 (34) No support ? No support
HKDF-CTR (Yes) 42 No support No support No support No support
DH No support No support 35.0 (35) No support No support No support

See also

Document Tags and Contributors

 Contributors to this page: dchest, teoli, agix, Wladimir_Palant, Davidx7, coolaj86, lewisl9029
 Last updated by: dchest,