SubtleCrypto.deriveKey()

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

Syntax

const result = crypto.subtle.deriveKey(
    algorithm,
    masterKey,
    derivedKeyAlgorithm,
    extractable,
    keyUsages);

Parameters

  • algorithm 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.
  • derivedKeyAlgorithm 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.
Recommendation Initial definition.

Browser compatibility

Update compatibility data on GitHub
DesktopMobile
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidEdge MobileFirefox for AndroidOpera for AndroidiOS SafariSamsung Internet
Basic supportChrome Full support 37Edge Full support 12Firefox Full support 34
Full support 34
No support 32 — 34
Disabled
Disabled From version 32 until version 34 (exclusive): this feature is behind the dom.webcrypto.enabled preference (needs to be set to true). To change preferences in Firefox, visit about:config.
IE No support NoOpera Full support 24Safari Full support 7WebView Android Full support 37Chrome Android Full support 37Edge Mobile Full support 12Firefox Android Full support 34
Full support 34
No support 32 — 34
Disabled
Disabled From version 32 until version 34 (exclusive): this feature is behind the dom.webcrypto.enabled preference (needs to be set to true). To change preferences in Firefox, visit about:config.
Opera Android Full support 24Safari iOS Full support 7Samsung Internet Android Full support 6.0

Legend

Full support  
Full support
No support  
No support
User must explicitly enable this feature.
User must explicitly enable this feature.

See also

Document Tags and Contributors

Last updated by: kgeorgiou,