本文へスキップ
ecdsa.com
WebCrypto SubtleCrypto.exportKey / wrapKeyWebCrypto

エラーメッセージ

InvalidAccessError: Failed to execute 'exportKey' on 'SubtleCrypto': key is not extractable

別の表記

  • InvalidAccessError: The CryptoKey is nonextractable
  • InvalidAccessError: A parameter or an operation is not supported by the underlying object

上記は Chromium のテキストです。Safari/WebKit は「The CryptoKey is nonextractable」、Firefox は「A parameter or an operation is not supported by the underlying object」です。いずれも `InvalidAccessError` の DOMException です。

WebCrypto SubtleCrypto.exportKey / wrapKey — DOMException InvalidAccessError (Chromium / Firefox / WebKit)

このエラーの意味

この鍵は `extractable: false` で作成されているため、その鍵データを読み出すことは `exportKey` でも `wrapKey` でも決してできません。それがこのフラグの目的です。秘密鍵はブラウザーの暗号実装の内部にとどまり、スクリプト(注入されたスクリプトを含む)は鍵を使えても盗むことはできません。生成した鍵ペアの公開鍵は常にエクスポートできます。このエラーが関係するのは秘密鍵と共通鍵です。

発生する理由

修正方法

  1. 1.

    秘密鍵はオブジェクトのまま保持し、公開鍵をエクスポートする

    エクスポート不可の鍵は `CryptoKey` オブジェクトとして IndexedDB に保存し、公開鍵(SPKI または JWK)だけを共有してください。これで、このフラグによる保護が維持されます。

    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. 2.

    エクスポートが必須の場合に限り、エクスポート可能な鍵を作成する

    秘密鍵をどうしてもブラウザーの外に出さなければならない場合は、エクスポート可能として生成し、別の鍵でラップした状態でのみエクスポートしてください。

    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 });

関連するエラー

署名エラーデータベースをすべて見る