安全上下文
此特征只可用于
安全上下文
(HTTPS),在某些或所有
支持浏览器
.
deriveKey()
方法在
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.
const result = crypto.subtle.deriveKey(
algorithm,
baseKey,
derivedKeyAlgorithm,
extractable,
keyUsages
);
algorithm
is an object defining the
derivation algorithm
to use.
EcdhKeyDeriveParams
对象。
HkdfParams
对象。
Pbkdf2Params
对象。
baseKey
是
CryptoKey
representing the input to the derivation algorithm. If
algorithm
is ECDH, then this will be the ECDH private key. Otherwise it will be the initial key material for the derivation function: for example, for PBKDF2 it might be a password, imported as a
CryptoKey
使用
SubtleCrypto.importKey()
.
derivedKeyAlgorithm
is an object defining the algorithm the derived key will be used for.
HmacKeyGenParams
对象。
AesKeyGenParams
对象。
extractable
是
布尔
indicating whether it will be possible to export the key using
SubtleCrypto.exportKey()
or
SubtleCrypto.wrapKey()
.
keyUsages
是
数组
indicating what can be done with the derived key. Note that the key usages must be allowed by the algorithm set in
derivedKeyAlgorithm
. Possible values of the array are:
encrypt
: The key may be used to
encrypt
messages.
decrypt
: The key may be used to
decrypt
messages.
sign
: The key may be used to
sign
messages.
verify
: The key may be used to
verify
signatures.
deriveKey
: The key may be used in
deriving a new key
.
"deriveBits"
: The key may be used in
deriving bits
.
"wrapKey"
: The key may be used to
wrap a key
.
"unwrapKey"
: The key may be used to
unwrap a key
.
The promise is rejected when one of the following exceptions are encountered:
InvalidAccessError
CryptoKey.usages
value of that key doesn't contain
deriveKey
.
NotSupported
SyntaxError
keyUsages
is empty but the unwrapped key is of type
secret
or
private
.
The three algorithms supported by
deriveKey()
have quite different characteristics and are appropriate in different situations.
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 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 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 .
注意 : You can try the working examples on GitHub.
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);
});
}
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
);
}
| 规范 | 状态 | 注释 |
|---|---|---|
|
Web Cryptography API
The definition of 'SubtleCrypto.deriveKey()' in that specification. |
推荐 | 初始定义。 |
| 桌面 | 移动 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
deriveKey
|
Chrome 37 |
Edge
部分支持
12
|
Firefox
34
|
IE No | Opera 24 | Safari 7 | WebView Android 37 | Chrome Android 37 |
Firefox Android
34
|
Opera Android 24 | Safari iOS 7 | Samsung Internet Android 6.0 |
完整支持
部分支持
不支持
见实现注意事项。
用户必须明确启用此特征。
SubtleCrypto