SubtleCrypto: phương thức importKey()
Baseline
Widely available
*
This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.
* Some parts of this feature may have varying levels of support.
Secure context: This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.
Note: This feature is available in Web Workers.
Phương thức importKey() của giao diện SubtleCrypto nhập một khóa: nghĩa là, nó nhận làm đầu vào một khóa ở định dạng bên ngoài, có thể di chuyển và cung cấp cho bạn một đối tượng CryptoKey mà bạn có thể sử dụng trong Web Crypto API.
Hàm này chấp nhận nhiều định dạng nhập: xem Các định dạng được hỗ trợ để biết chi tiết.
Cú pháp
importKey(format, keyData, algorithm, extractable, keyUsages)
Tham số
format-
Một chuỗi mô tả định dạng dữ liệu của khóa cần nhập. Nó có thể là một trong các giá trị sau:
raw: Định dạng Raw.pkcs8: Định dạng PKCS #8.spki: Định dạng SubjectPublicKeyInfo.jwk: Định dạng JSON Web Key.
keyData-
Một
ArrayBuffer, một TypedArray, mộtDataView, hoặc một đối tượngJSONWebKeychứa khóa ở định dạng đã cho. algorithm-
Một đối tượng xác định loại khóa cần nhập và cung cấp các tham số bổ sung cụ thể cho thuật toán.
- Đối với RSASSA-PKCS1-v1_5, RSA-PSS,
hoặc RSA-OAEP:
truyền một đối tượng
RsaHashedImportParams. - Đối với ECDSA hoặc ECDH:
truyền một đối tượng
EcKeyImportParams. - Đối với HMAC:
truyền một đối tượng
HmacImportParams. - Đối với AES-CTR, AES-CBC,
AES-GCM, và AES-KW:
truyền chuỗi xác định thuật toán hoặc một đối tượng có dạng
{ name: ALGORITHM }, trong đóALGORITHMlà tên của thuật toán. - Đối với PBKDF2: truyền chuỗi
PBKDF2hoặc một đối tượng có dạng{ name: "PBKDF2" }. - Đối với HKDF: truyền chuỗi
HKDFhoặc một đối tượng có dạng{ name: "HKDF" }. - Đối với Ed25519: truyền chuỗi
Ed25519hoặc một đối tượng có dạng{ name: "Ed25519" }. - Đối với X25519: truyền chuỗi
X25519hoặc một đối tượng có dạng{ name: "X25519" }.
- Đối với RSASSA-PKCS1-v1_5, RSA-PSS,
hoặc RSA-OAEP:
truyền một đối tượng
extractable-
Một giá trị boolean cho biết liệu có thể xuất khóa bằng
SubtleCrypto.exportKey()hoặcSubtleCrypto.wrapKey()hay không. keyUsages-
Một
Arraycho biết những gì có thể thực hiện với khóa. Các giá trị có thể của mảng là:encrypt: Khóa có thể được sử dụng để mã hóa thông báo.decrypt: Khóa có thể được sử dụng để giải mã thông báo.sign: Khóa có thể được sử dụng để ký thông báo.verify: Khóa có thể được sử dụng để xác minh chữ ký.deriveKey: Khóa có thể được sử dụng trong phái sinh khóa mới.deriveBits: Khóa có thể được sử dụng trong phái sinh bit.wrapKey: Khóa có thể được sử dụng để bọc khóa.unwrapKey: Khóa có thể được sử dụng để mở bọc khóa.
Giá trị trả về
Một Promise được fulfill với khóa đã nhập dưới dạng đối tượng CryptoKey.
Ngoại lệ
Promise bị reject khi gặp một trong các ngoại lệ sau:
SyntaxErrorDOMException-
Ném lên khi
keyUsagestrống nhưng khóa đã mở bọc có loạisecrethoặcprivate. TypeError-
Ném lên khi cố sử dụng một định dạng không hợp lệ hoặc nếu
keyDatakhông phù hợp với định dạng đó.
Các định dạng được hỗ trợ
API này hỗ trợ bốn định dạng nhập/xuất khóa khác nhau: Raw, PKCS #8, SubjectPublicKeyInfo và JSON Web Key.
Raw
Bạn có thể sử dụng định dạng này để nhập hoặc xuất các khóa bí mật AES hoặc HMAC, hoặc các khóa công khai Elliptic Curve (ECDSA hoặc ECDH).
Trong định dạng này, khóa được cung cấp dưới dạng một ArrayBuffer chứa các byte thô cho khóa.
Lưu ý khi nhập các khóa công khai Elliptic Curve, dữ liệu có thể chứa các điểm đường cong elliptic nén.
PKCS #8
Bạn có thể sử dụng định dạng này để nhập hoặc xuất các khóa riêng tư RSA hoặc Elliptic Curve.
Định dạng PKCS #8 được định nghĩa trong RFC 5208, sử dụng ký hiệu ASN.1:
PrivateKeyInfo ::= SEQUENCE {
version Version,
privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
privateKey PrivateKey,
attributes [0] IMPLICIT Attributes OPTIONAL }
Phương thức importKey() mong đợi nhận đối tượng này dưới dạng một ArrayBuffer chứa dạng mã hóa DER của PrivateKeyInfo.
DER là một tập hợp các quy tắc để mã hóa các cấu trúc ASN.1 thành dạng nhị phân.
Bạn có khả năng bắt gặp đối tượng này ở định dạng PEM nhiều nhất.
Định dạng PEM là một cách mã hóa dữ liệu nhị phân thành ASCII. Nó bao gồm một header và một footer, và ở giữa là dữ liệu nhị phân mã hóa base64.
Một PrivateKeyInfo được mã hóa PEM trông như thế này:
-----BEGIN PRIVATE KEY----- MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAU9BD0jxDfF5OV380z 9VIEUN2W5kJDZ3hbuaDenCxLiAMsoquKTfFaou71eLdN0TShZANiAARMUhCee/cp xmjGc1roj0D0k6VlUqtA+JVCWigXcIAukOeTHCngZDKCrD4PkXDBvbciJdZKvO+l ml2FIkoovZh/8yeTKmjUMb804g6OmjUc9vVojCRV0YdaSmYkkJMJbLg= -----END PRIVATE KEY-----
Để đưa nó vào định dạng bạn có thể truyền cho importKey(), bạn cần thực hiện hai việc:
- Giải mã base64 phần giữa header và footer, sử dụng
Window.atob(). - Chuyển đổi chuỗi kết quả thành một
ArrayBuffer.
Xem mục Ví dụ để biết hướng dẫn cụ thể hơn.
SubjectPublicKeyInfo
Bạn có thể sử dụng định dạng này để nhập hoặc xuất các khóa công khai RSA hoặc Elliptic Curve.
SubjectPublicKey được định nghĩa trong RFC 5280, Section 4.1 sử dụng ký hiệu ASN.1:
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
subjectPublicKey BIT STRING }
Giống như PKCS #8, phương thức importKey() mong đợi nhận đối tượng này dưới dạng một ArrayBuffer chứa dạng mã hóa DER của SubjectPublicKeyInfo.
Một lần nữa, bạn có khả năng bắt gặp đối tượng này ở định dạng PEM nhiều nhất.
Một SubjectPublicKeyInfo được mã hóa PEM trông như thế này:
-----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-----
Giống như với PKCS #8, để đưa nó vào định dạng bạn có thể truyền cho importKey(), bạn cần thực hiện hai việc:
- Giải mã base64 phần giữa header và footer, sử dụng
Window.atob(). - Chuyển đổi chuỗi kết quả thành một
ArrayBuffer.
Xem mục Ví dụ để biết hướng dẫn cụ thể hơn.
JSON Web Key
Bạn có thể sử dụng định dạng JSON Web Key để nhập hoặc xuất các khóa công khai hoặc riêng tư RSA hoặc Elliptic Curve, cũng như các khóa bí mật AES và HMAC.
Định dạng JSON Web Key được định nghĩa trong RFC 7517. Nó mô tả một cách biểu diễn các khóa công khai, riêng tư và bí mật dưới dạng các đối tượng JSON.
Một JSON Web Key trông giống như thế này (đây là một khóa riêng tư EC):
{
"crv": "P-384",
"d": "wouCtU7Nw4E8_7n5C1-xBjB4xqSb_liZhYMsy8MGgxUny6Q8NCoH9xSiviwLFfK_",
"ext": true,
"key_ops": ["sign"],
"kty": "EC",
"x": "SzrRXmyI8VWFJg1dPUNbFcc9jZvjZEfH7ulKI1UkXAltd7RGWrcfFxqyGPcwu6AQ",
"y": "hHUag3OvDzEr0uUQND4PXHQTXP5IDGdYhJhL-WLKjnGjQAw0rNGy5V29-aV-yseW"
}
Ví dụ
Note: Bạn có thể thử các ví dụ hoạt động trên GitHub.
Nhập Raw
Ví dụ này nhập một khóa AES từ một ArrayBuffer chứa các byte thô sẽ sử dụng.
Xem mã đầy đủ trên GitHub.
const rawKey = window.crypto.getRandomValues(new Uint8Array(16));
/*
Nhập một khóa bí mật AES từ một ArrayBuffer chứa các byte thô.
Nhận một chuỗi ArrayBuffer chứa các byte, và trả về một Promise
sẽ giải quyết thành một CryptoKey đại diện cho khóa bí mật.
*/
function importSecretKey(rawKey) {
return window.crypto.subtle.importKey("raw", rawKey, "AES-GCM", true, [
"encrypt",
"decrypt",
]);
}
Nhập PKCS #8
Ví dụ này nhập một khóa riêng tư ký RSA từ một đối tượng PKCS #8 được mã hóa PEM. Xem mã đầy đủ trên GitHub.
/*
Chuyển đổi một chuỗi thành một ArrayBuffer
từ 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/vu50KdRMleZeZYOWPAEhhMfywybTuzBiPVIZVP8WFCSKNMbfi1S9A9PdBqnebwwHhX3/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-----`;
/*
Nhập một khóa riêng tư RSA được mã hóa PEM, để sử dụng cho việc ký RSA-PSS.
Nhận một chuỗi chứa khóa được mã hóa PEM, và trả về một Promise
sẽ giải quyết thành một CryptoKey đại diện cho khóa riêng tư.
*/
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"],
);
}
Nhập SubjectPublicKeyInfo
Ví dụ này nhập một khóa công khai mã hóa RSA từ một đối tượng SubjectPublicKeyInfo được mã hóa PEM. Xem mã đầy đủ trên GitHub.
// từ 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"],
);
}
Nhập JSON Web Key
Đoạn mã này nhập một khóa riêng tư ký ECDSA, với một đối tượng JSON Web Key đại diện cho nó. Xem mã đầy đủ trên 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",
};
/*
Nhập một khóa riêng tư EC ở định dạng JSON Web Key, để sử dụng cho việc ký ECDSA.
Nhận một đối tượng đại diện cho JSON Web Key, và trả về một Promise
sẽ giải quyết thành một CryptoKey đại diện cho khóa riêng tư.
*/
function importPrivateKey(jwk) {
return window.crypto.subtle.importKey(
"jwk",
jwk,
{
name: "ECDSA",
namedCurve: "P-384",
},
true,
["sign"],
);
}
Đặc tả kỹ thuật
| Thông số kỹ thuật |
|---|
| Web Cryptography Level 2> # SubtleCrypto-method-importKey> |