エラーメッセージ
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` は動作し続けるため、一部の機能だけが失敗しているように見えます。
発生する理由
ページが暗号化されていない HTTP で配信されている
よくあるステージング用のホスト、イントラネットのツール、プレビュー環境のうち、TLS を使っていないものは安全なコンテキストではありません。そこでは仕様により、WebCrypto の機能がすべて使えなくなります。
LAN のアドレスで開いた開発サーバー
よくある`http://localhost:5173` は安全ですが、`http://192.168.1.20:5173`(スマートフォンでのテスト)は安全ではありません。開発中に動いていたコードが、そのデバイスでは失敗します。
安全でないフレームまたは WebView
ときどき`http:` の親フレームに埋め込まれた安全なページや、独自の安全でないスキームでローカルコンテンツを読み込む WebView も、安全なコンテキストではありません。
修正方法
- 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.
ページを 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") }
関連するエラー
DataError: Data provided to an operation does not meet requirementsWebCrypto crypto.subtle.importKeyTypeError: Failed to execute 'importKey' on 'SubtleCrypto': The provided value…WebCrypto SubtleCrypto.importKeySecurityError: The relying party ID is not a registrable domain suffix of, nor…WebAuthn navigator.credentials.create() / get()