安全上下文
此特征只可用于 安全上下文 (HTTPS),在某些或所有 支持浏览器 .

unwrapKey() 方法在 SubtleCrypto interface "unwraps" a key. This means that it takes as its input a key that has been exported and then encrypted (also called "wrapped"). It decrypts the key and then imports it, returning a CryptoKey object that can be used in the Web 加密 API .

就像 SubtleCrypto.importKey() , you specify the key's import format and other attributes of the key to import details such as whether it is extractable, and which operations it can be used for.

But because unwrapKey() also decrypts the key to be imported, you also need to pass in the key that must be used to decrypt it. This is sometimes called the "unwrapping key".

unwrapKey() is SubtleCrypto.wrapKey() : while unwrapKey is composed of decrypt + import, wrapKey is composed of encrypt + export.

句法

const result = crypto.subtle.unwrapKey(
    format,
    wrappedKey,
    unwrappingKey,
    unwrapAlgo,
    unwrappedKeyAlgo,
    extractable,
    keyUsages
);
					

参数

返回值

异常

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

InvalidAccessError
Raised when the unwrapping key is not a key for the requested unwrap algorithm or if the CryptoKey.usages value of that key doesn't contain unwrap .
NotSupported

Raised when trying to use an algorithm that is either unknown or isn't suitable for encryption or wrapping.

SyntaxError
Raised when keyUsages is empty but the unwrapped key is of type secret or private .
TypeError

Raised when trying to use an invalid format.

Supported algorithms

unwrapKey() method supports the same algorithms as the wrapKey() 方法。

范例

注意 : You can try the working examples on Github.

Unwrapping a "raw" key

In this example we unwrap an AES-GCM symmetric key. The key was exported in "raw" format and encrypted using the AES-KW algorithm, with a key derived from a password.

To unwrap, we ask the user for the password and use PBKDF2 and some salt to derive the AES-KW unwrapping key. The salt needs to be the same as the salt that was used to derive the original AES-KW key wrapping key.

Once we have the unwrapping key we pass it into unwrapKey() with the wrapped key and other parameters. See the complete code on GitHub.

/*
Salt that is to be used in derivation of the key-wrapping key,
alongside the password the user supplies.
This must match the salt value that was originally used to derive
the key.
*/
const saltBytes = [89,113,135,234,168,204,21,36,55,93,1,132,242,242,192,156];
/*
The wrapped key itself.
*/
const wrappedKeyBytes = [171,223,14,36,201,233,233,120,164,68,217,192,226,80,
    224,39,199,235,239,60,212,169,100,23,61,54,244,197,160,80,109,230,207,
    225,57,197,175,71,80,209];
/*
Convert an array of byte values to an ArrayBuffer.
*/
function bytesToArrayBuffer(bytes) {
  const bytesAsArrayBuffer = new ArrayBuffer(bytes.length);
  const bytesUint8 = new Uint8Array(bytesAsArrayBuffer);
  bytesUint8.set(bytes);
  return bytesAsArrayBuffer;
}
/*
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),
    {name: "PBKDF2"},
    false,
    ["deriveBits", "deriveKey"]
  );
}
/*
Derive an AES-KW key using PBKDF2.
*/
async function getUnwrappingKey() {
  // 1. get the key material (user-supplied password)
  const keyMaterial = await getKeyMaterial();
  // 2 initialize the salt parameter.
  // The salt must match the salt originally used to derive the key.
  // In this example it's supplied as a constant "saltBytes".
  const saltBuffer = bytesToArrayBuffer(saltBytes);
  // 3 derive the key from key material and salt
  return window.crypto.subtle.deriveKey(
    {
      "name": "PBKDF2",
      salt: saltBuffer,
      "iterations": 100000,
      "hash": "SHA-256"
    },
    keyMaterial,
    { "name": "AES-KW", "length": 256},
    true,
    [ "wrapKey", "unwrapKey" ]
  );
}
/*
Unwrap an AES secret key from an ArrayBuffer containing the raw bytes.
Takes an array containing the bytes, and returns a Promise
that will resolve to a CryptoKey representing the secret key.
*/
async function unwrapSecretKey(wrappedKey) {
  // 1. get the unwrapping key
  const unwrappingKey = await getUnwrappingKey();
  // 2. initialize the wrapped key
  const wrappedKeyBuffer = bytesToArrayBuffer(wrappedKey);
  // 3. unwrap the key
  return window.crypto.subtle.unwrapKey(
    "raw",                 // import format
    wrappedKeyBuffer,      // ArrayBuffer representing key to unwrap
    unwrappingKey,         // CryptoKey representing key encryption key
    "AES-KW",              // algorithm identifier for key encryption key
    "AES-GCM",             // algorithm identifier for key to unwrap
    true,                  // extractability of key to unwrap
    ["encrypt", "decrypt"] // key usages for key to unwrap
  );
}
					

Unwrapping a "pkcs8" key

In this example we unwrap an RSA-PSS private signing key. The key was exported in "pkcs8" format and encrypted using the AES-GCM algorithm, with a key derived from a password.

To unwrap, we ask the user for the password and use PBKDF2 and some salt to derive the AES-GCM unwrapping key. The salt needs to be the same as the salt that was used to derive the original AES-GCM key wrapping key.

Once we have the unwrapping key we pass it into unwrapKey() with the wrapped key and other parameters. Note that when using AES-GCM we have to pass the iv value into unwrapKey() , and this must be the same as the iv that was used in the corresponding wrapKey() 操作。 See the complete code on GitHub.

/*
Salt that is to be used in derivation of the key-wrapping key,
alongside the password the user supplies.
This must match the salt value that was originally used to derive
the key.
*/
const saltBytes = [180,253,62,216,47,35,90,55,218,233,103,10,172,143,161,177];
/*
IV that is to be used in decrypting the key to unwrap.
This must the the same IV that was originally used to encrypt
the key.
*/
const ivBytes = [212,187,26,247,172,51,37,151,27,177,249,142];
/*
The wrapped key itself.
*/
const wrappedKeyBytes = [6,155,182,208,7,141,44,18,3,151,58,126,68,100,252,
  225,241,11,25,201,153,171,102,174,150,29,62,195,110,138,106,109,14,6,108,
  148,104,221,22,93,102,221,146,25,65,112,4,140,79,194,164,163,156,250,108,
  11,14,220,78,194,161,17,14,57,121,70,13,28,220,210,78,32,46,217,36,165,220,
  170,244,152,214,150,83,2,138,128,11,251,227,213,72,100,158,10,162,40,195,
  60,248,77,37,156,34,10,213,171,67,147,73,231,31,63,80,176,103,206,187,164,
  214,250,49,223,185,5,48,241,17,1,253,59,185,181,209,255,42,223,175,90,159,
  174,169,205,156,120,195,1,135,165,226,46,119,27,97,183,23,197,227,85,138,
  235,79,158,167,59,62,194,34,210,214,240,215,101,233,63,138,53,87,253,189,
  27,66,150,76,242,76,102,174,179,163,184,205,11,161,224,19,110,34,175,192,
  101,117,169,86,66,56,241,128,13,156,165,125,139,110,138,50,108,129,251,137,
  26,186,110,117,113,207,179,59,213,18,175,14,203,192,2,97,131,125,167,227,
  182,87,72,123,54,156,60,195,88,224,96,46,126,245,251,247,147,110,147,173,
  82,106,93,210,55,71,127,133,41,37,181,17,106,16,158,220,136,43,75,133,96,
  240,151,116,40,44,254,2,32,74,226,193,172,48,211,71,109,163,143,30,92,28,
  30,183,25,16,176,207,77,93,139,242,114,91,218,126,123,234,18,9,245,53,46,
  172,215,62,92,249,191,17,27,0,58,151,33,23,169,93,177,253,152,147,198,196,
  226,42,202,166,99,250,127,40,221,196,121,195,198,235,30,159,159,95,182,107,
  175,137,177,49,72,63,131,162,198,186,22,255,230,237,195,56,147,177,101,52,
  227,125,32,180,242,47,92,212,6,148,218,107,125,137,123,15,51,107,159,228,
  238,212,60,54,184,48,110,248,252,208,46,23,149,78,169,201,68,242,193,251,
  156,227,42,90,109,102,172,61,207,124,96,98,79,37,218,16,212,139,162,0,183,
  235,171,75,18,84,160,120,173,156,187,99,24,58,88,213,148,24,193,111,75,169,
  10,158,207,148,84,249,156,248,19,221,2,175,1,8,74,221,212,244,123,34,223,
  175,54,166,101,51,175,141,80,87,9,146,72,223,46,251,199,192,2,22,125,16,15,
  99,26,159,165,133,172,169,26,236,44,86,182,162,81,143,249,15,207,12,232,15,
  205,199,78,133,199,19,232,183,33,183,72,117,72,27,43,254,13,17,252,1,143,
  137,154,10,4,77,85,24,85,143,200,81,76,171,43,124,42,191,150,70,10,90,178,
  198,40,233,233,225,146,231,209,254,2,90,216,5,97,105,204,82,88,81,99,92,
  159,116,192,223,148,252,12,24,197,211,187,212,98,252,201,154,184,65,54,47,
  13,106,151,168,208,112,212,74,204,36,233,98,104,58,103,1,194,13,26,109,101,
  60,42,3,215,20,25,99,176,63,28,112,102,121,190,96,198,228,196,78,38,82,37,
  248,42,150,115,6,10,22,101,42,237,175,69,232,212,231,40,193,70,211,245,106,
  231,175,150,88,105,170,139,238,196,64,218,250,47,165,22,36,196,161,30,79,
  175,14,133,88,129,182,56,140,147,168,134,91,68,172,110,195,134,156,68,78,
  249,215,68,250,11,23,70,59,156,99,75,249,159,84,16,206,93,16,130,34,66,210,
  82,252,53,251,84,59,226,212,154,15,20,163,58,228,109,53,214,151,237,10,169,
  107,180,123,174,159,182,8,240,115,115,220,131,128,79,80,61,133,58,24,98,
  193,225,56,36,159,254,199,49,44,160,28,81,140,163,24,143,114,31,237,235,
  250,83,72,215,44,232,182,45,39,182,193,248,65,174,186,52,219,30,198,48,1,
  134,151,81,114,38,124,7,213,205,138,28,22,216,76,46,224,241,88,156,7,62,
  23,104,34,54,25,156,93,212,133,182,61,93,255,195,68,244,234,53,132,151,140,
  72,146,127,113,227,34,243,218,222,47,218,113,18,173,203,158,133,90,156,214,
  77,20,113,1,231,164,52,55,69,132,24,68,131,212,7,153,34,179,113,156,81,
  127,83,57,29,195,90,64,211,115,202,188,5,42,188,142,203,109,231,53,206,72,
  220,90,23,12,1,178,122,60,221,68,6,14,154,108,203,171,142,159,249,13,55,52,
  110,214,33,147,164,181,50,79,164,200,83,251,40,105,223,50,0,115,240,146,23,
  122,80,204,169,38,198,154,31,29,23,236,39,35,131,147,242,163,138,158,236,
  117,7,108,33,132,98,50,111,46,146,251,82,34,85,5,130,237,67,40,170,235,124,
  92,66,71,239,12,97,136,251,1,206,13,51,232,92,46,35,95,5,123,24,183,99,243,
  124,75,155,89,66,54,72,17,255,99,137,199,232,204,9,248,78,35,218,136,117,
  239,102,240,187,40,89,244,140,109,229,120,116,54,207,171,11,248,190,199,81,
  53,109,8,188,51,93,165,34,255,165,191,198,130,220,41,192,166,194,69,104,
  124,158,122,236,176,24,60,87,240,42,158,143,37,143,208,155,249,230,21,4,
  230,56,194,62,235,132,14,50,180,216,134,28,25,159,64,199,161,236,60,233,
  160,172,68,169,2,5,252,190,20,54,115,248,63,93,107,156,8,96,85,32,189,118,
  66,114,126,64,203,97,235,13,18,102,192,51,59,5,122,171,96,129,40,32,154,4,
  191,234,75,184,112,201,244,110,50,216,44,88,139,175,58,112,7,52,25,64,112,
  40,148,187,39,234,96,151,16,158,114,113,109,164,47,108,94,148,35,232,221,
  33,110,126,170,25,234,45,165,180,210,193,120,247,155,127];
/*
The unwrapped signing key.
*/
let signingKey;
const signButton = document.querySelector(".pkcs8 .sign-button");
/*
Convert an array of byte values to an ArrayBuffer.
*/
function bytesToArrayBuffer(bytes) {
  const bytesAsArrayBuffer = new ArrayBuffer(bytes.length);
  const bytesUint8 = new Uint8Array(bytesAsArrayBuffer);
  bytesUint8.set(bytes);
  return bytesAsArrayBuffer;
}
/*
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),
    {name: "PBKDF2"},
    false,
    ["deriveBits", "deriveKey"]
  );
}
/*
Derive an AES-GCM key using PBKDF2.
*/
async function getUnwrappingKey() {
  // 1. get the key material (user-supplied password)
  const keyMaterial = await getKeyMaterial();
  // 2 initialize the salt parameter.
  // The salt must match the salt originally used to derive the key.
  // In this example it's supplied as a constant "saltBytes".
  const saltBuffer = bytesToArrayBuffer(saltBytes);
  // 3 derive the key from key material and salt
  return window.crypto.subtle.deriveKey(
    {
      "name": "PBKDF2",
      salt: saltBuffer,
      "iterations": 100000,
      "hash": "SHA-256"
    },
    keyMaterial,
    { "name": "AES-GCM", "length": 256},
    true,
    [ "wrapKey", "unwrapKey" ]
  );
}
/*
Unwrap an RSA-PSS private signing key from an ArrayBuffer containing
the raw bytes.
Takes an array containing the bytes, and returns a Promise
that will resolve to a CryptoKey representing the private key.
*/
async function unwrapPrivateKey(wrappedKey) {
  // 1. get the unwrapping key
  const unwrappingKey = await getUnwrappingKey();
  // 2. initialize the wrapped key
  const wrappedKeyBuffer = bytesToArrayBuffer(wrappedKey);
  // 3. initialize the iv
  const ivBuffer = bytesToArrayBuffer(ivBytes);
  // 4. unwrap the key
  return window.crypto.subtle.unwrapKey(
    "pkcs8",               // import format
    wrappedKeyBuffer,      // ArrayBuffer representing key to unwrap
    unwrappingKey,         // CryptoKey representing key encryption key
    {                      // algorithm params for key encryption key
      name: "AES-GCM",
      iv: ivBuffer
    },
    {                      // algorithm params for key to unwrap
      name: "RSA-PSS",
      hash: "SHA-256"
    },
    true,                  // extractability of key to unwrap
    ["sign"]               // key usages for key to unwrap
  );
}
					

规范

规范 状态 注释
Web Cryptography API
The definition of 'SubtleCrypto.unwrapKey()' in that specification.
推荐 初始定义。

浏览器兼容性

The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request. 更新 GitHub 上的兼容性数据
桌面 移动
Chrome Edge Firefox Internet Explorer Opera Safari Android webview Chrome for Android Firefox for Android Opera for Android Safari on iOS Samsung Internet
unwrapKey Chrome 37 Edge 部分支持 12
部分支持 12
Not supported: AES-CTR.
Firefox 34
34
不支持 32 — 34 Disabled
Disabled ). To change preferences in Firefox, visit
IE 部分支持 11
部分支持 11
返回 KeyOperation 而不是 Promise
Opera 24 Safari 7 WebView Android ? Chrome Android 37 Firefox Android 34
34
不支持 32 — 34 Disabled
Disabled ). To change preferences in Firefox, visit
Opera Android 24 Safari iOS 7 Samsung Internet Android 6.0

图例

完整支持

完整支持

部分支持

部分支持

兼容性未知 ?

兼容性未知

见实现注意事项。

用户必须明确启用此特征。

用户必须明确启用此特征。

另请参阅

元数据

  • 最后修改:
  1. Web 加密 API
  2. SubtleCrypto
  3. 方法
    1. decrypt()
    2. deriveBits()
    3. deriveKey()
    4. digest()
    5. encrypt()
    6. exportKey()
    7. generateKey()
    8. importKey()
    9. sign()
    10. unwrapKey()
    11. verify()
    12. wrapKey()
  4. Related pages for Web Crypto API
    1. Crypto
    2. CryptoKey
    3. CryptoKeyPair
    4. RandomSource
    5. Window.crypto

版权所有  © 2014-2026 乐数软件    

工业和信息化部: 粤ICP备14079481号-1