Mensaje de error
InvalidAccessError: Failed to execute 'exportKey' on 'SubtleCrypto': key is not extractable
También se muestra como
- InvalidAccessError: The CryptoKey is nonextractable
- InvalidAccessError: A parameter or an operation is not supported by the underlying object
Arriba está el texto de Chromium; Safari/WebKit: «The CryptoKey is nonextractable»; Firefox: «A parameter or an operation is not supported by the underlying object». En todos los casos es una DOMException `InvalidAccessError`.
WebCrypto SubtleCrypto.exportKey / wrapKey — DOMException InvalidAccessError (Chromium / Firefox / WebKit)
Qué significa
La clave se creó con `extractable: false`, así que su material nunca se puede volver a leer: ni con `exportKey` ni con `wrapKey`. Ese es el propósito del indicador: la clave privada se queda dentro de la implementación criptográfica del navegador, y los scripts (incluidos los inyectados) pueden usarla, pero no robarla. Las claves públicas de un par generado siempre se pueden exportar; este error afecta a las claves privadas y a las claves secretas.
Por qué ocurre
La clave se generó como no extraíble a propósito
frecuenteLas bibliotecas y los diseños al estilo de las llaves de acceso crean así claves vinculadas al dispositivo. Una funcionalidad posterior que quiera mostrar la clave privada, hacer una copia de seguridad de ella o sincronizarla choca con esa decisión.
Una clave restaurada desde IndexedDB conserva su indicador
ocasionalLos objetos CryptoKey guardados en IndexedDB vuelven exactamente como se crearon; no es posible hacerlos exportables más adelante.
El valor predeterminado de una biblioteca
ocasionalAlgunas bibliotecas JOSE y de cifrado de extremo a extremo (E2E) generan claves con `extractable: false` de forma predeterminada; sus funciones auxiliares de exportación fallan entonces con las claves privadas.
Cómo solucionarlo
- 1.
Conservar la clave privada como objeto y exportar la clave pública
Guarda las claves no extraíbles como objetos `CryptoKey` en IndexedDB y comparte solo la clave pública (SPKI o JWK). Así se mantiene la protección que aporta el indicador.
js const pair = await crypto.subtle.generateKey({ name: "ECDSA", namedCurve: "P-256" }, false, ["sign", "verify"]); // Persist the non-extractable private key as a CryptoKey object (structured clone), never as bytes: await idbPut("signing-key", pair.privateKey); // Share only the public key: const jwk = await crypto.subtle.exportKey("jwk", pair.publicKey); - 2.
Crear claves extraíbles solo cuando la exportación sea un requisito
Si la clave privada realmente tiene que salir del navegador, genérala como extraíble y expórtala solo envuelta con otra clave.
js // Only if the private key must leave the browser (e.g. a user-initiated, encrypted backup): const pair = await crypto.subtle.generateKey({ name: "ECDSA", namedCurve: "P-256" }, true, ["sign", "verify"]); const wrapped = await crypto.subtle.wrapKey("pkcs8", pair.privateKey, backupKey, { name: "AES-GCM", iv });