Content Security Policy и Web Crypto

Web Crypto API (window.crypto.subtle) функционирует в рамках политики безопасности браузера, и одной из ключевых систем контроля является Content Security Policy (CSP). CSP определяет, какие источники данных, скриптов и операций разрешены в контексте страницы, и напрямую влияет на доступность криптографических возможностей.

Базовое взаимодействие CSP и Web Crypto API

Web Crypto API относится к встроенным браузерным возможностям и не загружает внешние скрипты для выполнения криптографических операций. Поэтому сама по себе она не блокируется стандартными директивами вроде script-src или worker-src в большинстве сценариев.

Однако CSP влияет на окружение, в котором Web Crypto API может использоваться, особенно в следующих аспектах:

  • использование Web Workers для криптографических операций
  • загрузка внешних библиотек, оборачивающих Web Crypto
  • доступ к небезопасным контекстам (HTTP вместо HTTPS)
  • взаимодействие с eval, new Function, динамическим кодом
  • использование WASM-модулей, которые часто применяются вместе с криптографией

Обязательность безопасного контекста

Web Crypto API доступен только в безопасных контекстах. Это означает, что страница должна быть загружена через:

  • HTTPS
  • localhost (в режиме разработки)
  • file:// (с ограничениями, зависящими от браузера)

CSP косвенно усиливает это требование через директиву:

Content-Security-Policy: upgrade-insecure-requests

Она автоматически переводит HTTP-запросы в HTTPS, что критично для криптографических операций, так как браузер может полностью отключить crypto.subtle в небезопасном окружении.

Директивы CSP, влияющие на криптографический код

Хотя Web Crypto API не требует специальных CSP-директив, его использование часто пересекается с ограничениями политики безопасности.

script-src

Наиболее важная директива при работе с криптографией в браузере.

Пример строгой политики:

Content-Security-Policy: script-src 'self'

В этом случае запрещается:

  • inline-скрипты
  • eval
  • динамическая генерация кода

Это напрямую влияет на криптографические библиотеки, если они используют динамическое создание функций.

object-src

Может блокировать старые плагины и встроенные объекты. Для Web Crypto API влияние косвенное, но важно для безопасности окружения:

Content-Security-Policy: object-src 'none'

worker-src

Криптографические операции часто выносятся в Web Workers для предотвращения блокировки UI.

Content-Security-Policy: worker-src 'self'

Если эта директива отсутствует или настроена строго, создание воркеров с криптографическими задачами может быть заблокировано.

connect-src

Используется при отправке зашифрованных данных на сервер.

Content-Security-Policy: connect-src 'self'

Если криптографический модуль выполняет fetch или XHR для передачи зашифрованных данных, эта директива становится критичной.

Web Crypto API и запрет inline-скриптов

Многие примеры работы с Web Crypto API используют inline-код:

<script>
crypto.subtle.digest("SHA-256", new TextEncoder().encode("data"))
  .then(hash => console.log(hash));
</script>

При CSP:

script-src 'self'

такой код будет заблокирован.

Правильная архитектура требует вынесения логики:

<script src="crypto.js"></script>

и в crypto.js:

async function hashData(data) {
  const encoded = new TextEncoder().encode(data);

  const hashBuffer = await crypto.subtle.digest('SHA-256', encoded);

  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

hashData('message').then(console.log);

CSP и Web Workers в криптографии

Использование Web Crypto API внутри воркеров — распространённая практика при обработке больших данных (например, хэширование файлов).

Создание воркера:

const worker = new Worker('crypto-worker.js');

CSP:

worker-src 'self'

В crypto-worker.js:

self.onmess age = async (e) => {
  const data = e.data;

  const hash = await crypto.subtle.digest(
    'SHA-256',
    new TextEncoder().encode(data)
  );

  self.postMessage(hash);
};

Если CSP не разрешает worker-src, криптографическая нагрузка может быть вынуждена выполняться в основном потоке, что ухудшает производительность и стабильность интерфейса.

Ограничения CSP при использовании внешних криптографических библиотек

Многие библиотеки используют Web Crypto API как fallback, но также включают JS-реализации алгоритмов.

Пример библиотек:

  • Forge
  • CryptoJS
  • libsodium.js

Если CSP запрещает загрузку внешних ресурсов:

script-src 'self'

то подключение CDN-версий библиотек становится невозможным:

<script src="https://cdn.example.com/crypto.js"></script>

Также может блокироваться WASM-версия криптографии при отсутствии:

Content-Security-Policy: script-src 'self' 'wasm-unsafe-eval'

WASM и криптография под CSP

WebAssembly часто используется для ускорения криптографических алгоритмов (например, Argon2, bcrypt, scrypt).

CSP ограничивает выполнение WASM через:

Content-Security-Policy: script-src 'self' 'wasm-unsafe-eval'

Без этой директивы загрузка и выполнение WASM-модулей может быть полностью заблокировано, даже если Web Crypto API доступен.

Интеграция строгого CSP и Web Crypto API

Безопасная конфигурация для приложений, активно использующих криптографию:

Content-Security-Policy:
  default-src 'self';
  script-src 'self';
  worker-src 'self';
  connect-src 'self';
  object-src 'none';
  base-uri 'none';

Такая политика:

  • исключает внешние источники кода
  • ограничивает сетевые соединения
  • защищает от внедрения скриптов
  • сохраняет доступ к Web Crypto API

Ошибки, связанные с CSP при использовании crypto.subtle

При нарушении политики безопасности типичные ошибки выглядят так:

  • Refused to execute inline script
  • Refused to create a worker
  • Blocked a frame with origin
  • Content Security Policy directive violated

При этом Web Crypto API может быть полностью исправен, но его использование невозможно из-за окружения.

Влияние nonce и hash-based CSP на криптографический код

При использовании nonce:

script-src 'self' 'nonce-random123'

скрипты криптографических операций должны быть явно помечены:

<script nonce="random123">
crypto.subtle.digest('SHA-256', new TextEncoder().encode('data'));
</script>

Hash-based CSP:

script-src 'self' 'sha256-abc...'

Используется редко в криптографических приложениях, так как любые изменения кода ломают политику и блокируют выполнение даже безопасных операций.

Практическая архитектура безопасного криптографического приложения

Типичная структура:

  • основной поток: UI и управление
  • worker: криптографические операции
  • Web Crypto API: генерация ключей, хэширование, подписи
  • строгий CSP: защита от внедрения кода

Пример распределения ответственности:

UI → отправка данных → Worker → crypto.subtle → результат → UI

CSP гарантирует, что в этот поток нельзя внедрить сторонний код, даже при наличии XSS уязвимости частичного уровня.

Итоговые ограничения взаимодействия

Web Crypto API не требует специальных разрешений CSP, но полностью зависит от:

  • разрешения выполнения JavaScript
  • наличия безопасного контекста HTTPS
  • возможности использовать Web Workers
  • отсутствия блокировки динамического кода

CSP не управляет криптографией напрямую, но определяет среду, в которой она становится возможной или недоступной.