SubtleCrypto: importKey() method
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 insecure contexts (HTTPS), in some or allsupporting browsers.
Note: This feature is available inWeb Workers.
TheimportKey() method of theSubtleCrypto interface imports a key: that is, it takes as input a key in an external, portable format and gives you aCryptoKey object that you can use in theWeb Crypto API.
The function accepts several import formats: seeSupported formats for details.
In this article
Syntax
importKey(format, keyData, algorithm, extractable, keyUsages)Parameters
formatA string describing the data format of the key to import. It can be one of the following:
raw:Raw format.pkcs8:PKCS #8 format.spki:SubjectPublicKeyInfo format.jwk:JSON Web Key format.
keyDataAn
ArrayBuffer, aTypedArray,aDataView, or aJSONWebKeyobject containing the key inthe given format.algorithmAn object defining the type of key to import and providing extra algorithm-specific parameters.
- ForRSASSA-PKCS1-v1_5,RSA-PSS,orRSA-OAEP:pass an
RsaHashedImportParamsobject. - ForECDSA orECDH:pass an
EcKeyImportParamsobject. - ForHMAC:pass an
HmacImportParamsobject. - ForAES-CTR,AES-CBC,AES-GCM, andAES-KW:pass the string identifying the algorithm or an object of the form
{ name: ALGORITHM }, whereALGORITHMis the name of the algorithm. - ForPBKDF2: pass the string
PBKDF2or an object of the form{ name: "PBKDF2" }. - ForHKDF: pass the string
HKDFor an object of the form{ name: "HKDF" }. - ForEd25519: pass the string
Ed25519or an object of the form{ name: "Ed25519" }. - ForX25519: pass the string
X25519or an object of the form{ name: "X25519" }.
- ForRSASSA-PKCS1-v1_5,RSA-PSS,orRSA-OAEP:pass an
extractableA boolean value indicating whether it will be possible to export the key using
SubtleCrypto.exportKey()orSubtleCrypto.wrapKey().keyUsagesAn
Arrayindicating what can be done with the key. Possible array values are:encrypt: The key may be used toencrypt messages.decrypt: The key may be used todecrypt messages.sign: The key may be used tosign messages.verify: The key may be used toverify signatures.deriveKey: The key may be used inderiving a new key.deriveBits: The key may be used inderiving bits.wrapKey: The key may be used towrap a key.unwrapKey: The key may be used tounwrap a key.
Return value
APromise that fulfills with the imported key as aCryptoKey object.
Exceptions
The promise is rejected when one of the following exceptions is encountered:
SyntaxErrorDOMExceptionRaised when
keyUsagesis empty but the unwrapped key is of typesecretorprivate.TypeErrorRaised when trying to use an invalid format or if the
keyDatais not suited for that format.
Supported formats
This API supports four different key import/export formats: Raw, PKCS #8, SubjectPublicKeyInfo, and JSON Web Key.
Raw
You can use this format to import or export AES or HMAC secret keys, or Elliptic Curve public keys (ECDSA or ECDH).
In this format the key is supplied as anArrayBuffer containing the raw bytes for the key.
Note that when importing Elliptic Curve public keys, the data may containcompressed elliptic curve points.
PKCS #8
You can use this format to import or export RSA or Elliptic Curve private keys.
The PKCS #8 format is defined inRFC 5208, using theASN.1 notation:
PrivateKeyInfo ::= SEQUENCE { version Version, privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, privateKey PrivateKey, attributes [0] IMPLICIT Attributes OPTIONAL }TheimportKey() method expects to receive this object as anArrayBuffer containing theDER-encoded form of thePrivateKeyInfo.DER is a set of rules for encoding ASN.1 structures into a binary form.
You are most likely to encounter this object inPEM format.PEM format is a way to encode binary data in ASCII. It consists of a header and a footer, and in between, thebase64-encoded binary data.A PEM-encodedPrivateKeyInfo looks like this:
-----BEGIN PRIVATE KEY-----MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAU9BD0jxDfF5OV380z9VIEUN2W5kJDZ3hbuaDenCxLiAMsoquKTfFaou71eLdN0TShZANiAARMUhCee/cpxmjGc1roj0D0k6VlUqtA+JVCWigXcIAukOeTHCngZDKCrD4PkXDBvbciJdZKvO+lml2FIkoovZh/8yeTKmjUMb804g6OmjUc9vVojCRV0YdaSmYkkJMJbLg=-----END PRIVATE KEY-----
To get this into a format you can give toimportKey() you need to do two things:
- base64-decode the part between header and footer, using
Window.atob(). - convert the resulting string into an
ArrayBuffer.
See theExamples section for more concrete guidance.
SubjectPublicKeyInfo
You can use this format to import or export RSA or Elliptic Curve public keys.
SubjectPublicKey is defined inRFC 5280, Section 4.1 using theASN.1 notation:
SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING }Just likePKCS #8, theimportKey() method expects to receive this object as anArrayBuffer containing theDER-encoded form of theSubjectPublicKeyInfo.
Again, you are most likely to encounter this object inPEM format.A PEM-encodedSubjectPublicKeyInfo looks like this:
-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3j+HgSHUnc7F6XzvEbD0r3M5JNy+/kabiJVu8IU1ERAl3Osi38VgiMzjDBDOrFxVzNNzl+SXAHwXIV5BHiXLCQ6qhwYsDgH6OqgKIwiALra/wNH4UHxj1Or/iyAkjHRR/kGhUtjyVCjzvaQaDpJW2G+syd1ui0B6kJov2CRUWiPwpff8hBfVWv8q9Yc2yD5hCnykVL0iAiyn+SDAk/rv8dC5eIlzCI4efUCbyG4c9O88Qz7bS14DxSfaPTy8P/TWoihVVjLaDF743LgM/JLqCDPUBUA3HLsZUhKm3BbSkd7Q9Ngkjv3+yByo4/fL+fkYRa8j9Ypa2N0Iw53LFb3BgQIDAQAB-----END PUBLIC KEY-----
Just as withPKCS #8, to get this into a format you can give toimportKey() you need to do two things:
- base64-decode the part between header and footer, using
Window.atob(). - convert the resulting string into an
ArrayBuffer.
See theExamples section for more concrete guidance.
JSON Web Key
You can use JSON Web Key format to import or export RSA or Elliptic Curve public or private keys, as well as AES and HMAC secret keys.
JSON Web Key format is defined inRFC 7517.It describes a way to represent public, private, and secret keys as JSON objects.
A JSON Web Key looks something like this (this is an EC private key):
{ "crv": "P-384", "d": "wouCtU7Nw4E8_7n5C1-xBjB4xqSb_liZhYMsy8MGgxUny6Q8NCoH9xSiviwLFfK_", "ext": true, "key_ops": ["sign"], "kty": "EC", "x": "SzrRXmyI8VWFJg1dPUNbFcc9jZvjZEfH7ulKI1UkXAltd7RGWrcfFxqyGPcwu6AQ", "y": "hHUag3OvDzEr0uUQND4PXHQTXP5IDGdYhJhL-WLKjnGjQAw0rNGy5V29-aV-yseW"}Examples
Note:You cantry the working examples on GitHub.
Raw import
This example imports an AES key from anArrayBuffer containing the raw bytes to use.See the complete code on 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 Promisethat will resolve to a CryptoKey representing the secret key.*/function importSecretKey(rawKey) { return window.crypto.subtle.importKey("raw", rawKey, "AES-GCM", true, [ "encrypt", "decrypt", ]);}PKCS #8 import
This example imports an RSA private signing key from a PEM-encoded PKCS #8 object.See the complete code on GitHub.
/*Convert a string into an ArrayBufferfrom 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 Promisethat 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"], );}SubjectPublicKeyInfo import
This example imports an RSA public encryption key from a PEM-encodedSubjectPublicKeyInfo object.See the complete code on GitHub.
// from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-Stringfunction 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 import
This code imports an ECDSA private signing key, given a JSON Web Key object that represents it.See the complete code on 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 Promisethat 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"], );}Specifications
| Specification |
|---|
| Web Cryptography Level 2> # SubtleCrypto-method-importKey> |