本文へスキップ
ecdsa.com
WebCryptoWebCrypto

エラーメッセージ

TypeError: Cannot read properties of undefined (reading 'digest')

別の表記

  • TypeError: Cannot read properties of undefined (reading 'importKey')
  • TypeError: can't access property "digest", crypto.subtle is undefined
  • TypeError: undefined is not an object (evaluating 'crypto.subtle.digest')

文言は、エンジンが出す汎用的な TypeError です。Chromium/V8 は「Cannot read properties of undefined (reading 'digest')」、Firefox は「can't access property "digest", crypto.subtle is undefined」、Safari/WebKit は「undefined is not an object (evaluating 'crypto.subtle.digest')」です。メソッド名は最初の呼び出しに応じて変わります(`importKey`、`sign`、`generateKey`…)。

WebCrypto — window.crypto.subtle is undefined outside a secure context (Chromium / Firefox / WebKit)

このエラーの意味

このページには `crypto.subtle` が存在しないため、それに対する最初の呼び出しで、「undefined」に関する汎用的な TypeError が発生します。ブラウザーが `SubtleCrypto` を公開するのは安全なコンテキスト(secure context)だけです。つまり、HTTPS で配信されるページ、`http://localhost` / `127.0.0.1` から配信されるページ、`file:` URL のページです。同じコードが手元のマシンの localhost では動作し、別のホスト名や IP アドレスから暗号化されていない HTTP でページを開いた途端に動かなくなります。`crypto.getRandomValues` は動作し続けるため、一部の機能だけが失敗しているように見えます。

発生する理由

修正方法

  1. 1.

    検出し、わかりやすいメッセージでエラーにする

    WebCrypto を使う前に `window.isSecureContext` を確認してください。JavaScript の暗号ポリフィルに黙ってフォールバックしてはいけません。そもそも TLS がなければ、ページの完全性は保証されません。

    js
    if (!window.isSecureContext || !globalThis.crypto?.subtle) {
      throw new Error("WebCrypto needs HTTPS (or http://localhost). Current origin: " + location.origin);
    }
    const digest = await crypto.subtle.digest("SHA-256", data);
  2. 2.

    ページを HTTPS で配信する

    ほかのデバイスから開く開発サーバーも含め、すべての環境で TLS を使ってください。mkcert などのツールで、ローカルで信頼される証明書を作成できます。

    bash
    # Local HTTPS for a dev server reachable from other devices
    mkcert -install
    mkcert dev.example.test 192.168.1.20 localhost
    # Vite: server.https = { key: fs.readFileSync("dev.example.test+2-key.pem"), cert: fs.readFileSync("dev.example.test+2.pem") }

関連するエラー

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