SubtleCrypto.deriveKey() - Web APIs 编辑

Secure context

This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

The deriveKey() method of the SubtleCrypto interface can be used to derive a secret key from a master key.

It takes as arguments some initial key material, the derivation algorithm to use, and the desired properties for the key to derive. It returns a Promise which will be fulfilled with a CryptoKey object representing the new key.

It's worth noting that the three key derivation algorithms you can use have quite different characteristics and are appropriate in quite different situations. See Supported algorithms for some more detail on this.

Syntax

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

Parameters

Return value

Exceptions

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

  • InvalidAccessError
  • Raised 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
  • Raised 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
  • Raised when keyUsages is empty but the unwrapped key is of type secret or private.

Supported algorithms

The three algorithms supported by deriveKey() have quite different characteristics and are appropriate in different situations.

ECDH

ECDH (Elliptic Curve Diffie-Hellman) is a key-agreement algorithm. It enables two people who each have an ECDH public/private key pair to generate a shared secret: that is, a secret that they — and noone else — share. They can then use this shared secret as a symmetric key to secure their communication, or can use the secret as an input to derive such a key (for example, using the HKDF algorithm).

ECDH is specified in RFC 6090.

HKDF

HKDF is a key derivation function. It's designed to derive key material from some high-entropy input, such as the output of an ECDH key agreement operation.

It's not designed to derive keys from relatively low-entropy inputs such as passwords. For that, use PBKDF2.

HKDF is specified in RFC 5869.

PBKDF2

PBKDF2 is also a key derivation function. It's designed to derive key material from some relatively low-entropy input, such as a password. It derives key material by applying a function such as HMAC to the input password along with some salt, and repeating this process many times. The more times the process is repeated, the more computationally expensive key derivation is: this makes it harder for an attacker to use brute-force to discover the key using a dictionary attack.

PBKDF2 is specified in RFC 2898.

Examples

Note: You can try the working examples on GitHub.

ECDH

In this example Alice and Bob each generate an ECDH key pair, then exchange public keys. They then use deriveKey() to derive a shared AES key, that they could use to encrypt messages. See the complete code on GitHub.

/*
Derive an AES key, given:
- our ECDH private key
- their ECDH public key
*/
function deriveSecretKey(privateKey, publicKey) {
  return window.crypto.subtle.deriveKey(
    {
      name: "ECDH",
      public: publicKey
    },
    privateKey,
    {
      name: "AES-GCM",
      length: 256
    },
    false,
    ["encrypt", "decrypt"]
  );
}

async function agreeSharedSecretKey() {
  // Generate 2 ECDH key pairs: one for Alice and one for Bob
  // In more normal usage, they would generate their key pairs
  // separately and exchange public keys securely
  let alicesKeyPair = await window.crypto.subtle.generateKey(
    {
      name: "ECDH",
      namedCurve: "P-384"
    },
    false,
    ["deriveKey"]
  );

  let bobsKeyPair = await window.crypto.subtle.generateKey(
    {
      name: "ECDH",
      namedCurve: "P-384"
    },
    false,
    ["deriveKey"]
  );

  // Alice then generates a secret key using her private key and Bob's public key.
  let alicesSecretKey = await deriveSecretKey(alicesKeyPair.privateKey, bobsKeyPair.publicKey);

  // Bob generates the same secret key using his private key and Alice's public key.
  let bobsSecretKey = await deriveSecretKey(bobsKeyPair.privateKey, alicesKeyPair.publicKey);

  // Alice can then use her copy of the secret key to encrypt a message to Bob.
  let encryptButton = document.querySelector(".ecdh .encrypt-button");
  encryptButton.addEventListener("click", () => {
    encrypt(alicesSecretKey);
  });

  // Bob can use his copy to decrypt the message.
  let decryptButton = document.querySelector(".ecdh .decrypt-button");
  decryptButton.addEventListener("click", () => {
    decrypt(bobsSecretKey);
  });
}

PBKDF2

In this example we ask the user for a password, then use it to derive an AES key using PBKDF2, then use the AES key to encrypt a message. See the complete code on GitHub.

/*
Get some key material to use as input to the deriveKey method.
The key material is a password supplied by the user.
*/
function getKeyMaterial() {
  let password = window.prompt("Enter your password");
  let enc = new TextEncoder();
  return window.crypto.subtle.importKey(
    "raw",
    enc.encode(password),
    "PBKDF2",
    false,
    ["deriveBits", "deriveKey"]
  );
}

async function encrypt(plaintext, salt, iv) {
  let keyMaterial = await getKeyMaterial();
  let key = await window.crypto.subtle.deriveKey(
    {
      "name": "PBKDF2",
      salt: salt,
      "iterations": 100000,
      "hash": "SHA-256"
    },
    keyMaterial,
    { "name": "AES-GCM", "length": 256},
    true,
    [ "encrypt", "decrypt" ]
  );

  return window.crypto.subtle.encrypt(
    {
      name: "AES-GCM",
      iv: iv
    },
    key,
    plaintext
  );
}

Specifications

SpecificationStatusComment
Web Cryptography API
The definition of 'SubtleCrypto.deriveKey()' in that specification.
RecommendationInitial definition.

Browser compatibility

BCD tables only load in the browser

See also

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

词条统计

浏览:52 次

字数:14312

最后编辑:7 年前

编辑次数:0 次

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文