SubtleCrypto:importKey() 方法
基线 广泛可用
此功能已经很成熟,并在许多设备和浏览器版本上运行。它从 2015 年 7 月.
报告反馈
安全上下文:此功能仅在安全上下文(HTTPS)中可用,在某些或所有支持的浏览器中可用。
importKey()
方法是 SubtleCrypto
接口的一种方法,用于导入密钥:即,它以外部可移植格式的密钥作为输入,并提供一个 CryptoKey
对象,你可以在 Web 密码 API 中使用该对象。
语法
importKey(format, keyData, algorithm, extractable, keyUsages)
js
参数
-
format
- 一个字符串,描述要导入的密钥的数据格式。它可以是以下之一
raw
:原始 格式。pkcs8
:PKCS #8 格式。spki
:SubjectPublicKeyInfo 格式。
jwk
:JSON Web 密钥 格式。-
keyData
一个
ArrayBuffer
、一个 TypedArray、一个DataView
或一个JSONWebKey
对象,其中包含以给定格式表示的密钥。-
algorithm
- 一个对象,定义要导入的密钥类型并提供额外的特定于算法的参数。
- 对于 RSASSA-PKCS1-v1_5、RSA-PSS 或 RSA-OAEP:传递一个
RsaHashedImportParams
对象。 - 对于 ECDSA 或 ECDH:传递一个
EcKeyImportParams
对象。 - 对于 HMAC:传递一个
HmacImportParams
对象。 - 对于 AES-CTR、AES-CBC、AES-GCM 和 AES-KW:传递标识算法的字符串或形式为
{ name: ALGORITHM }
的对象,其中ALGORITHM
是算法的名称。 - 对于 PBKDF2:传递字符串
PBKDF2
或形式为{ name: "PBKDF2" }
的对象。 - 对于 HKDF:传递字符串
HKDF
或形式为{ name: "HKDF" }
的对象。 - 对于 Ed25519:传递字符串
Ed25519
或形式为{ name: "Ed25519" }
的对象。
对于 X25519:传递字符串
X25519
或形式为{ name: "X25519" }
的对象。-
extractable
一个布尔值,指示是否可以使用
SubtleCrypto.exportKey()
或SubtleCrypto.wrapKey()
导出密钥。-
keyUsages
unwrapKey
:该密钥可用于 解包密钥。
返回值
一个 Promise
,该承诺以导入的密钥作为 CryptoKey
对象来完成。
异常
- 当遇到以下异常之一时,承诺将被拒绝
当
keyUsages
为空但解包的密钥类型为secret
或private
时引发。-
TypeError
支持的格式
当尝试使用无效格式或 keyData
不适合该格式时引发。
此 API 支持四种不同的密钥导入/导出格式:原始格式、PKCS #8 格式、SubjectPublicKeyInfo 格式和 JSON Web 密钥格式。
原始格式
你可以使用此格式导入或导出 AES 或 HMAC 秘密密钥,或椭圆曲线公钥。
在此格式中,密钥以 ArrayBuffer
的形式提供,该缓冲区包含密钥的原始字节。
PKCS #8 格式
你可以使用此格式导入或导出 RSA 或椭圆曲线私钥。
PrivateKeyInfo ::= SEQUENCE { version Version, privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, privateKey PrivateKey, attributes [0] IMPLICIT Attributes OPTIONAL }
PKCS #8 格式在 RFC 5208 中定义,使用 ASN.1 符号
importKey()
方法期望接收此对象作为 ArrayBuffer
,其中包含 PrivateKeyInfo
的 DER 编码 形式。DER 是一组用于将 ASN.1 结构编码为二进制形式的规则。
-----BEGIN PRIVATE KEY----- MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAU9BD0jxDfF5OV380z 9VIEUN2W5kJDZ3hbuaDenCxLiAMsoquKTfFaou71eLdN0TShZANiAARMUhCee/cp xmjGc1roj0D0k6VlUqtA+JVCWigXcIAukOeTHCngZDKCrD4PkXDBvbciJdZKvO+l ml2FIkoovZh/8yeTKmjUMb804g6OmjUc9vVojCRV0YdaSmYkkJMJbLg= -----END PRIVATE KEY-----
你最有可能在 PEM 格式 中遇到此对象。PEM 格式是将二进制数据编码为 ASCII 的一种方法。它包含一个标题和一个页脚,标题和页脚之间是 Base64 编码 的二进制数据。一个 PEM 编码的 PrivateKeyInfo
看起来像这样
- 要将其转换为可以传递给
importKey()
的格式,你需要执行以下两个步骤 - 使用
Window.atob()
解码标题和页脚之间的部分。
将生成的字符串转换为 ArrayBuffer
。
有关更具体的指导,请参阅示例 部分。
SubjectPublicKeyInfo 格式
你可以使用此格式导入或导出 RSA 或椭圆曲线公钥。
SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING }
SubjectPublicKey
在 RFC 5280 第 4.1 节 中定义,使用 ASN.1 符号
与 PKCS #8 一样,importKey()
方法期望接收此对象作为 ArrayBuffer
,其中包含 SubjectPublicKeyInfo
的 DER 编码 形式。
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3j+HgSHUnc7F6XzvEbD0 r3M5JNy+/kabiJVu8IU1ERAl3Osi38VgiMzjDBDOrFxVzNNzl+SXAHwXIV5BHiXL CQ6qhwYsDgH6OqgKIwiALra/wNH4UHxj1Or/iyAkjHRR/kGhUtjyVCjzvaQaDpJW 2G+syd1ui0B6kJov2CRUWiPwpff8hBfVWv8q9Yc2yD5hCnykVL0iAiyn+SDAk/rv 8dC5eIlzCI4efUCbyG4c9O88Qz7bS14DxSfaPTy8P/TWoihVVjLaDF743LgM/JLq CDPUBUA3HLsZUhKm3BbSkd7Q9Ngkjv3+yByo4/fL+fkYRa8j9Ypa2N0Iw53LFb3B gQIDAQAB -----END PUBLIC KEY-----
同样,你最有可能在 PEM 格式 中遇到此对象。一个 PEM 编码的 SubjectPublicKeyInfo
看起来像这样
- 要将其转换为可以传递给
importKey()
的格式,你需要执行以下两个步骤 - 使用
Window.atob()
解码标题和页脚之间的部分。
将生成的字符串转换为 ArrayBuffer
。
与 PKCS #8 一样,要将其转换为可以传递给 importKey()
的格式,你需要执行以下两个步骤
JSON Web 密钥
你可以使用 JSON Web 密钥格式导入或导出 RSA 或椭圆曲线公钥或私钥,以及 AES 和 HMAC 秘密密钥。
JSON Web 密钥格式在 RFC 7517 中定义。它描述了一种将公钥、私钥和秘密密钥表示为 JSON 对象的方法。
{
"crv": "P-384",
"d": "wouCtU7Nw4E8_7n5C1-xBjB4xqSb_liZhYMsy8MGgxUny6Q8NCoH9xSiviwLFfK_",
"ext": true,
"key_ops": ["sign"],
"kty": "EC",
"x": "SzrRXmyI8VWFJg1dPUNbFcc9jZvjZEfH7ulKI1UkXAltd7RGWrcfFxqyGPcwu6AQ",
"y": "hHUag3OvDzEr0uUQND4PXHQTXP5IDGdYhJhL-WLKjnGjQAw0rNGy5V29-aV-yseW"
};
示例
json
注意:你可以在 GitHub 上尝试运行示例。
原始导入
const rawKey = window.crypto.getRandomValues(new Uint8Array(16));
/*
Import an AES secret key from an ArrayBuffer containing the raw bytes.
Takes an ArrayBuffer string containing the bytes, and returns a Promise
that will resolve to a CryptoKey representing the secret key.
*/
function importSecretKey(rawKey) {
return window.crypto.subtle.importKey("raw", rawKey, "AES-GCM", true, [
"encrypt",
"decrypt",
]);
}
此示例从包含要使用的原始字节的 ArrayBuffer
中导入 AES 密钥。在 GitHub 上查看完整代码。
PKCS #8 导入
/*
Convert a string into an ArrayBuffer
from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
*/
function str2ab(str) {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
const pemEncodedKey = `-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDD0tPV/du2vftjvXj1t/gXTK39sNBVrOAEb/jKzXae+Xa0H+3LhZaQIQNMfACiBSgIfZUvEGb+7TqXWQpoLoFR/R7MvGWcSk98JyrVtveD8ZmZYyItSY7m2hcasqAFiKyOouV5vzyRe87/lEyzzBpF3bQQ4IDaQu+K9Hj5fKuU6rrOeOhsdnJc+VdDQLScHxvMoLZ9Vtt+oK9J4/tOLwr4CG8khDlBURcBY6gPcLo3dPU09SW+6ctX2cX4mkXx6O/0mmdTmacr/vu50KdRMleFeZYOWPAEhhMfywybTuzBiPVIZVP8WFCSKNMbfi1S9A9PdBqnebwwHhX3/hsEBt2BAgMBAAECggEABEI1P6nf6Zs7mJlyBDv+Pfl5rjL2cOqLy6TovvZVblMkCPpJyFuNIPDK2tK2i897ZaXfhPDBIKmllM2Hq6jZQKB110OAnTPDg0JxzMiIHPs32S1d/KilHjGff4Hjd4NXp1l1Dp8BUPOllorR2TYm2x6dcCGFw9lhTr8O03Qp4hjn84VjGIWADYCk83mgS4nRsnHkdiqYnWx1AjKlY51yEK6RcrDMi0Th2RXrrINoC35sVv+APt2rkoMGi52RwTEseA1KZGFrxjq61ReJif6p2VXEcvHeX6CWLx014LGk43z6Q28P6HgeEVEfIjyqCUea5Du/mYb/QsRSCosXLxBqwQKBgQD1+fdC9ZiMrVI+km7Nx2CKBn8rJrDmUh5SbXn2MYJdrUd8bYNnZkCgKMgxVXsvJrbmVOrby2txOiqudZkk5mD3E5O/QZWPWQLgRu8ueYNpobAX9NRgNfZ7rZD+81vh5MfZiXfuZOuzv29iZhU0oqyZ9y75eHkLdrerNkwYOe5aUQKBgQDLzapDi1NxkBgsj9iiO4KUa7jvD4JjRqFy4Zhj/jbQvlvM0F/uFp7sxVcHGx4r11C+6iCbhX4u+Zuu0HGjT4d+hNXmgGyxR8fIUVxOlOtDkVJa5sOBZK73/9/MBeKusdmJPRhalZQfMUJRWIoEVDMhfg3tW/rBj5RYAtP2dTVUMQKBgDs8yr52dRmT+BWXoFWwaWB0NhYHSFz/c8v4D4Ip5DJ5M5kUqquxJWksySGQa40sbqnD05fBQovPLU48hfgr/zghn9hUjBcsoZOvoZR4sRw0UztBvA+7jzOz1hKAOyWIulR6Vca0yUrNlJ6G5R56+sRNkiOETupi2dLCzcqb0PoxAoGAZyNHvTLvIZN4iGSrjz5qkM4LIwBIThFadxbv1fq6pt0O/BGf2o+cEdq0diYlGK64cEVwBwSBnSg4vzlBqRIAUejLjwEDAJyA4EE8Y5A9l04dzV7nJb5cRak6CrgXxay/mBJRFtaHxVlaZGxYPGSYE6UFS0+3EOmmevvDZQBf4qECgYEA0ZF6Vavz28+8wLO6SP3w8NmpHk7K9tGEvUfQ30SgDx4G7qPIgfPrbB4OP/E0qCfsIImi3sCPpjvUMQdVVZyPOIMuB+rV3ZOxkrzxEUOrpOpR48FZbL7RN90yRQsAsrp9e4iv8QwB3VxLe7X0TDqqnRyqrc/osGzuS2ZcHOKmCU8=
-----END PRIVATE KEY-----`;
/*
Import a PEM encoded RSA private key, to use for RSA-PSS signing.
Takes a string containing the PEM encoded key, and returns a Promise
that will resolve to a CryptoKey representing the private key.
*/
function importPrivateKey(pem) {
// fetch the part of the PEM string between header and footer
const pemHeader = "-----BEGIN PRIVATE KEY-----";
const pemFooter = "-----END PRIVATE KEY-----";
const pemContents = pem.substring(
pemHeader.length,
pem.length - pemFooter.length - 1,
);
// base64 decode the string to get the binary data
const binaryDerString = window.atob(pemContents);
// convert from a binary string to an ArrayBuffer
const binaryDer = str2ab(binaryDerString);
return window.crypto.subtle.importKey(
"pkcs8",
binaryDer,
{
name: "RSA-PSS",
hash: "SHA-256",
},
true,
["sign"],
);
}
此示例从 PEM 编码的 PKCS #8 对象中导入 RSA 私钥签名密钥。在 GitHub 上查看完整代码。
本示例从 PEM 编码的 SubjectPublicKeyInfo 对象导入 RSA 公钥加密密钥。 在 GitHub 上查看完整代码。
// from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
function str2ab(str) {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
const pemEncodedKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy3Xo3U13dc+xojwQYWoJLCbOQ5fOVY8LlnqcJm1W1BFtxIhOAJWohiHuIRMctv7dzx47TLlmARSKvTRjd0dF92jx/xY20Lz+DXp8YL5yUWAFgA3XkO3LSJgEOex10NB8jfkmgSb7QIudTVvbbUDfd5fwIBmCtaCwWx7NyeWWDb7A9cFxj7EjRdrDaK3ux/ToMLHFXVLqSL341TkCf4ZQoz96RFPUGPPLOfvN0x66CM1PQCkdhzjE6U5XGE964ZkkYUPPsy6Dcie4obhW4vDjgUmLzv0z7UD010RLIneUgDE2FqBfY/C+uWigNPBPkkQ+Bv/UigS6dHqTCVeD5wgyBQIDAQAB
-----END PUBLIC KEY-----`;
function importRsaKey(pem) {
// fetch the part of the PEM string between header and footer
const pemHeader = "-----BEGIN PUBLIC KEY-----";
const pemFooter = "-----END PUBLIC KEY-----";
const pemContents = pem.substring(
pemHeader.length,
pem.length - pemFooter.length - 1,
);
// base64 decode the string to get the binary data
const binaryDerString = window.atob(pemContents);
// convert from a binary string to an ArrayBuffer
const binaryDer = str2ab(binaryDerString);
return window.crypto.subtle.importKey(
"spki",
binaryDer,
{
name: "RSA-OAEP",
hash: "SHA-256",
},
true,
["encrypt"],
);
}
JSON Web Key 导入
此代码导入 ECDSA 私有签名密钥,给定表示它的 JSON Web Key 对象。 在 GitHub 上查看完整代码。
const jwkEcKey = {
crv: "P-384",
d: "wouCtU7Nw4E8_7n5C1-xBjB4xqSb_liZhYMsy8MGgxUny6Q8NCoH9xSiviwLFfK_",
ext: true,
key_ops: ["sign"],
kty: "EC",
x: "SzrRXmyI8VWFJg1dPUNbFcc9jZvjZEfH7ulKI1UkXAltd7RGWrcfFxqyGPcwu6AQ",
y: "hHUag3OvDzEr0uUQND4PXHQTXP5IDGdYhJhL-WLKjnGjQAw0rNGy5V29-aV-yseW",
};
/*
Import a JSON Web Key format EC private key, to use for ECDSA signing.
Takes an object representing the JSON Web Key, and returns a Promise
that will resolve to a CryptoKey representing the private key.
*/
function importPrivateKey(jwk) {
return window.crypto.subtle.importKey(
"jwk",
jwk,
{
name: "ECDSA",
namedCurve: "P-384",
},
true,
["sign"],
);
}
规范
规范 |
---|
Web Cryptography API # SubtleCrypto-方法-importKey |
浏览器兼容性
BCD 表格仅在浏览器中加载