SubtleCrypto: importKey() ã¡ã½ãã
Baseline
åºãå©ç¨å¯è½
*
ãã®æ©è½ã¯åºãå®è£ ããã¦ãããå¤ãã®ãã¼ã¸ã§ã³ã®ç«¯æ«ããã©ã¦ã¶ã¼ã§åä½ãã¾ãã2020å¹´1æä»¥éããã¹ã¦ã®ãã©ã¦ã¶ã¼ã§å©ç¨å¯è½ã§ãã
* ãã®æ©è½ã®ä¸é¨ã¯ã対å¿ã¬ãã«ãç°ãªãå ´åãããã¾ãã
å®å ¨ãªã³ã³ããã¹ãç¨: ãã®æ©è½ã¯ä¸é¨ã¾ãã¯ãã¹ã¦ã®å¯¾å¿ãã¦ãããã©ã¦ã¶ã¼ã«ããã¦ãå®å ¨ãªã³ã³ããã¹ã (HTTPS) ã§ã®ã¿å©ç¨ã§ãã¾ãã
importKey() 㯠SubtleCrypto ã¤ã³ã¿ã¼ãã§ã¤ã¹ã®ã¡ã½ããã§ãéµãã¤ã³ãã¼ããã¾ããã¤ã¾ããå¤é¨ã®ãã¼ã¿ãã«å½¢å¼ã®éµãå
¥åã¨ãã¦åããã¦ã§ãæå· API ã§ä½¿ç¨ã§ãã CryptoKey ãªãã¸ã§ã¯ããè¿ãã¾ãã
ãã®é¢æ°ã¯ããã¤ãã®ã¤ã³ãã¼ãå½¢å¼ãåãå ¥ãã¾ãã詳細ã¯å¯¾å¿ãã¦ããå½¢å¼ãåç §ãã¦ãã ããã
æ§æ
importKey(format, keyData, algorithm, extractable, keyUsages)
弿°
format-
ã¤ã³ãã¼ãããéµã®ãã¼ã¿å½¢å¼ãè¨è¿°ããæååã以ä¸ã®ããããã«ãªãã¾ãã
raw: Raw å½¢å¼ã§ããpkcs8: PKCS #8 å½¢å¼ã§ããspki: SubjectPublicKeyInfo å½¢å¼ã§ããjwk: JSON Web Key å½¢å¼ã§ãã
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ãæ¸¡ãã¦ãã ããã - HKDF ã®å ´å: æåå
HKDFãæ¸¡ãã¦ãã ããã
- RSASSA-PKCS1-v1_5, RSA-PSS, RSA-OAEP ã®å ´å:
extractable-
è«çå¤ã§ã
SubtleCrypto.exportKey()ã¾ãã¯SubtleCrypto.wrapKey()ã使ç¨ãã¦éµãã¨ã¯ã¹ãã¼ããããã¨ãå¯è½ãã©ããã示ãã¾ãã keyUsages-
ãã®éµã§ä½ãã§ãããã示ã
Arrayã§ããéµã®ä½¿ç¨ã¯ 使ç¨å¯è½ãªå¤ã¯ä»¥ä¸ã®éãã§ããencrypt: ãã®éµã¯ã¡ãã»ã¼ã¸ã®æå·åã§ä½¿ç¨ãããã¨ãã§ãã¾ããdecrypt: ãã®éµã¯ã¡ãã»ã¼ã¸ã®å¾©å·ã§ä½¿ç¨ãããã¨ãã§ãã¾ããsign: ãã®éµã¯ã¡ãã»ã¼ã¸ã®ç½²åã§ä½¿ç¨ãããã¨ãã§ãã¾ããverify: ãã®éµã¯ç½²åã®æ¤è¨¼ã§ä½¿ç¨ãããã¨ãã§ãã¾ããderiveKey: ãã®éµã¯æ°ããéµã®å°åºã§ä½¿ç¨ãããã¨ãã§ãã¾ããderiveBits: ãã®éµã¯ãããã®å°åºã§ä½¿ç¨ãããã¨ãã§ãã¾ããwrapKey: ãã®éµã¯éµãã©ããããã®ã«ä½¿ç¨ãããã¨ãã§ãã¾ããunwrapKey: ãã®éµã¯éµã®ã©ãããè§£é¤ããã®ã«ä½¿ç¨ãããã¨ãã§ãã¾ãã
è¿å¤
ã¤ã³ãã¼ããããéµã CryptoKey ãªãã¸ã§ã¯ãã¨ãã¦å±¥è¡ããã Promise ã§ãã
ä¾å¤
以ä¸ã®ä¾å¤ãçºçããå ´åããããã¹ã¯æå¦ããã¾ãã
SyntaxErrorDOMException-
keyUsagesã空ã§ãã©ããããã¦ããªãéµã®ç¨®é¡ãsecretã¾ãã¯privateã§ããå ´åã«çºçãã¾ãã TypeError-
ç¡å¹ãªå½¢å¼ã使ç¨ãããã¨ããå ´åã
keyDataããã®å½¢å¼ã«é©ãã¦ããªãå ´åã«çºçãã¾ãã
対å¿ãã¦ããå½¢å¼
ãã® API ã¯ã4 ã¤ã®ç°ãªãéµå½¢å¼ãRawãPKCS #8ãSubjectPublicKeyInfoãJSON ã¦ã§ãéµã®ã¤ã³ãã¼ã/ã¨ã¯ã¹ãã¼ãã«å¯¾å¿ãã¦ãã¾ãã
Raw
ãã®å½¢å¼ã使ç¨ãã¦ãAES ã HMAC ç§å¯éµãæ¥åæ²ç·å ¬ééµãã¤ã³ãã¼ãã¾ãã¯ã¨ã¯ã¹ãã¼ãã§ãã¾ãã
ãã®å½¢å¼ã§ã¯ãéµã¯éµã®çã®ãã¤ããæ ¼ç´ãã ArrayBuffer ã¨ãã¦æä¾ããã¾ãã
PKCS #8
ãã®å½¢å¼ã使ç¨ãã¦ãRSA ã¾ãã¯æ¥åæ²ç·ç§å¯éµãã¤ã³ãã¼ãã¾ãã¯ã¨ã¯ã¹ãã¼ãã§ãã¾ãã
PKCS #8 ã®å½¢å¼ã¯ãRFC 5208ã§ ASN.1 è¨æ³ãç¨ãã¦å®ç¾©ããã¦ãã¾ãã
PrivateKeyInfo ::= SEQUENCE {
version Version,
privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
privateKey PrivateKey,
attributes [0] IMPLICIT Attributes OPTIONAL }
importKey() ã¡ã½ããã¯ããã®ãªãã¸ã§ã¯ãã ArrayBuffer ã« PrivateKeyInfo ã® DER ã¨ã³ã³ã¼ãããããã®ãå
¥ã£ããã®ã¨ãã¦åãåããã¨ãæå¾
ãã¾ãã DER 㯠ASN.1 æ§é ä½ããã¤ããªã¼å½¢å¼ã«ã¨ã³ã³ã¼ãããããã®ä¸é£ã®ã«ã¼ã«ã§ãã
ãã®ãªãã¸ã§ã¯ã㯠PEM å½¢å¼ã§è¡¨ç¤ºããããã¨ãã»ã¨ãã©ã§ãã PEM å½¢å¼ã¯ãã¤ããªã¼ãã¼ã¿ã ASCII ã§ã¨ã³ã³ã¼ãããæ¹æ³ã§ãããããã¼ã¨ããã¿ã¼ã§æ§æããããã®éã« base64 ã¨ã³ã³ã¼ãã®ãã¤ããªã¼ãã¼ã¿ãããã¾ãã PEM ã¨ã³ã³ã¼ãããã PrivateKeyInfo ã¯æ¬¡ã®ããã«ãªãã¾ãã
-----BEGIN PRIVATE KEY----- MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAU9BD0jxDfF5OV380z 9VIEUN2W5kJDZ3hbuaDenCxLiAMsoquKTfFaou71eLdN0TShZANiAARMUhCee/cp xmjGc1roj0D0k6VlUqtA+JVCWigXcIAukOeTHCngZDKCrD4PkXDBvbciJdZKvO+l ml2FIkoovZh/8yeTKmjUMb804g6OmjUc9vVojCRV0YdaSmYkkJMJbLg= -----END PRIVATE KEY-----
ããã importKey() ã«æ¸¡ããå½¢å¼ã«åå¾ããã«ã¯ã 2 ã¤ã®ãã¨ãè¡ãå¿
è¦ãããã¾ãã
window.atob()ã使ç¨ãã¦ããããã¼ã¨ããã¿ã¼ã®éã®é¨åã base64 ãã³ã¼ããã¾ãã- çµæã®æååã
ArrayBufferã«å¤æãã¾ãã
ä¾ã®ç¯ãåç §ãã¦ãã ããã
SubjectPublicKeyInfo
ãã®å½¢å¼ã使ç¨ãã¦ã RSA ã¾ãã¯æ¥åæ²ç·å ¬ééµãã¤ã³ãã¼ãã¾ãã¯ã¨ã¯ã¹ãã¼ãã§ãã¾ãã
SubjectPublicKey 㯠RFC 5280, Section 4.1 ã«ããã¦ã ASN.1 notation ã使ç¨ãã¦å®ç¾©ããã¦ãã¾ãã
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
subjectPublicKey BIT STRING }
PKCS #8 ã¨åæ§ã«ã importKey() ã¡ã½ããã¯ãã®ãªãã¸ã§ã¯ãã SubjectPublicKeyInfo ã® DER ã¨ã³ã³ã¼ãå½¢å¼ã®ãã¼ã¿ãæ ¼ç´ãã ArrayBuffer ã¨ãã¦åãåããã¨ãæå¾
ãã¾ãã
ç¹°ãè¿ãã¾ããããã®ãªãã¸ã§ã¯ã㯠PEM å½¢å¼ã§è¡¨ç¤ºããããã¨ãã»ã¨ãã©ã§ãã
PEM ã¨ã³ã³ã¼ãããã SubjectPublicKeyInfo ã¯æ¬¡ã®ããã«ãªãã¾ãï¼
-----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-----
PKCS #8 ã¨åæ§ã«ãããã importKey() ã«æ¸¡ããå½¢å¼ã§åå¾ããã«ã¯ã 2 ã¤ã®ãã¨ãè¡ãå¿
è¦ãããã¾ãã
window.atob()ã使ç¨ãã¦ããããã¼ã¨ããã¿ã¼ã®éã®é¨åã base64 ãã³ã¼ããã¾ãã- çµæã®æååã
ArrayBufferã«å¤æãã¾ãã
ä¾ç¯ãåç §ãã¦ãã ããã
JSON ã¦ã§ãéµ
JSON ã¦ã§ãéµå½¢å¼ã使ç¨ãã¦ãRSA ã¾ãã¯æ¥åæ²ç·å ¬ééµãç§å¯éµãAES ã HMAC ç§å¯éµãã¤ã³ãã¼ãã¾ãã¯ã¨ã¯ã¹ãã¼ãã§ãã¾ãã
JSON ã¦ã§ãéµå½¢å¼ã¯ãRFC 7517ã§å®ç¾©ããã¦ãã¾ãã å ¬ééµãç§å¯éµãç§å¯éµã JSON ãªãã¸ã§ã¯ãã¨ãã¦è¡¨ãæ¹æ³ãè¨è¿°ããã¦ãã¾ãã
JSON ã¦ã§ãéµã¯æ¬¡ã®ãããªãã®ã§ãï¼ãã㯠EC ç§å¯éµã§ãï¼ã
{
"crv": "P-384",
"d": "wouCtU7Nw4E8_7n5C1-xBjB4xqSb_liZhYMsy8MGgxUny6Q8NCoH9xSiviwLFfK_",
"ext": true,
"key_ops": ["sign"],
"kty": "EC",
"x": "SzrRXmyI8VWFJg1dPUNbFcc9jZvjZEfH7ulKI1UkXAltd7RGWrcfFxqyGPcwu6AQ",
"y": "hHUag3OvDzEr0uUQND4PXHQTXP5IDGdYhJhL-WLKjnGjQAw0rNGy5V29-aV-yseW"
};
ä¾
ã¡ã¢: You can try the working examples on GitHub.
Raw ã¤ã³ãã¼ã
ãã®ä¾ã§ã¯ã使ç¨ããçã®ãã¤ããæ ¼ç´ãã ArrayBuffer ãã AES éµãã¤ã³ãã¼ããã¾ããå®å
¨ãªã³ã¼ã㯠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",
]);
}
PKCS #8 ã¤ã³ãã¼ã
ãã®ä¾ã§ã¯ãPEM ã¨ã³ã³ã¼ãããã PKCS #8 ãªãã¸ã§ã¯ããã RSA ç§å¯éµãã¤ã³ãã¼ããã¾ãã å®å ¨ãªã³ã¼ã㯠GitHub ã§ç¢ºèªãã¦ãã ããã
/*
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,
);
// 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 ã¤ã³ãã¼ã
ãã®ä¾ã§ã¯ã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 ã¦ã§ãéµã¤ã³ãã¼ã
ãã®ã³ã¼ãã¯ã ECDSA ç§å¯ç½²åéµãæå®ããã JSON ã¦ã§ãéµãªãã¸ã§ã¯ãã«ã¤ã³ãã¼ããã¾ããå®å ¨ãªã³ã¼ã㯠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 Level 2 > # SubtleCrypto-method-importKey > |