Интеграция с браузерным хранилищем доверия

Браузерное хранилище доверия представляет собой совокупность корневых сертификатов (Root CA), предустановленных в системе или самом браузере. Эти сертификаты используются для проверки цепочек доверия при установлении защищённых соединений (TLS/SSL). Библиотека Jsrsasign не имеет прямого доступа к системному хранилищу доверия браузера, однако позволяет реализовать аналогичную модель проверки сертификатов на уровне JavaScript.

В условиях браузера ключевая задача — эмуляция процесса верификации цепочки сертификатов с использованием заранее известных доверенных корневых сертификатов.


Особенности работы Jsrsasign в браузере

Jsrsasign функционирует полностью в пользовательском пространстве JavaScript, без доступа к:

  • системному Keychain (macOS)
  • Windows Certificate Store
  • NSS (Firefox)

Это означает:

  • невозможность автоматически использовать доверенные корневые сертификаты браузера
  • необходимость вручного управления списком доверенных CA

При этом библиотека предоставляет инструменты для:

  • парсинга X.509 сертификатов
  • проверки подписей
  • построения и валидации цепочек сертификатов

Формирование пользовательского хранилища доверия

Вместо системного хранилища используется собственный список доверенных сертификатов.

Формат хранения

Чаще всего используются:

  • PEM (Base64 + заголовки)
  • DER (в бинарном виде, конвертируется в HEX)

Пример PEM-корневого сертификата:

-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIEbmh5...
-----END CERTIFICATE-----

Инициализация списка доверенных CA

const trustedCerts = [
  `-----BEGIN CERTIFICATE-----
  ...
  -----END CERTIFICATE-----`
];

Каждый сертификат может быть преобразован в объект:

const x509 = new X509();
x509.readCertPEM(trustedCerts[0]);

Построение цепочки сертификатов

Процесс включает:

  1. Получение сертификата сервера
  2. Добавление промежуточных сертификатов (если есть)
  3. Сопоставление с доверенным корневым сертификатом

Представление цепочки

const certChain = [
  serverCertPEM,
  intermediateCertPEM,
  rootCertPEM
];

Проверка подписи сертификата

Каждый сертификат подписан вышестоящим центром сертификации.

const child = new X509();
child.readCertPEM(serverCertPEM);

const parent = new X509();
parent.readCertPEM(intermediateCertPEM);

const isValid = child.verifySignature(parent.getPublicKey());

Проверка выполняется для каждого уровня цепочки.


Верификация цепочки доверия

Полная проверка включает:

  • корректность подписи каждого сертификата
  • соответствие Subject и Issuer
  • наличие доверенного корневого сертификата

Пример логики проверки

function verifyChain(chain, trustedRoots) {
  for (let i = 0; i < chain.length - 1; i++) {
    const cert = new X509();
    cert.readCertPEM(chain[i]);

    const issuer = new X509();
    issuer.readCertPEM(chain[i + 1]);

    if (!cert.verifySignature(issuer.getPublicKey())) {
      return false;
    }
  }

  const root = chain[chain.length - 1];

  return trustedRoots.includes(root);
}

Проверка срока действия сертификата

Каждый сертификат содержит поля:

  • Not Before
  • Not After
const x509 = new X509();
x509.readCertPEM(certPEM);

const now = new Date();
const notBefore = x509.getNotBefore();
const notAfter = x509.getNotAfter();

const validTime = now >= new Date(notBefore) && now <= new Date(notAfter);

Проверка имени хоста (Hostname Verification)

Сертификат должен соответствовать доменному имени.

Извлекаются:

  • CN (Common Name)
  • Subject Alternative Name (SAN)
const subject = x509.getSubjectString();

SAN:

const san = x509.getExtSubjectAltName();

Сравнение:

  • поддержка wildcard (*.example.com)
  • точное совпадение

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

Jsrsasign часто используется совместно с:

  • Fetch API
  • WebSocket
  • WebCrypto

Однако проверка TLS уже выполняется браузером. Jsrsasign применяется для:

  • пользовательской валидации сертификатов
  • проверки подписи данных
  • реализации zero-trust логики

Загрузка сертификатов в браузере

Сертификаты могут загружаться:

  • с сервера (fetch)
  • из локального файла
  • встроенными в код
fetch('/certs/root.pem')
  .then(res => res.text())
  .then(pem => {
    trustedCerts.push(pem);
  });

Кэширование доверенных сертификатов

Для повышения производительности используется:

  • localStorage
  • IndexedDB

Пример:

localStorage.setItem('trustedCerts', JSON.stringify(trustedCerts));

Загрузка:

const stored = JSON.parse(localStorage.getItem('trustedCerts'));

Обновление хранилища доверия

Проблема устаревших сертификатов решается:

  • периодической загрузкой актуального списка
  • проверкой CRL/OCSP (ограниченно)

Ограничения браузерной модели

  • отсутствие доступа к OCSP responder напрямую
  • невозможность проверить CRL без внешнего API
  • отсутствие аппаратной защиты ключей

Использование публичных списков CA

Можно импортировать:

  • Mozilla CA Bundle
  • собственные корпоративные CA

Формат — PEM список:

const mozillaBundle = `-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----`;

Валидация расширений сертификата

Jsrsasign позволяет анализировать расширения:

  • Key Usage
  • Extended Key Usage
  • Basic Constraints
const ext = x509.getExtBasicConstraints();

Проверяется:

  • является ли сертификат CA
  • допустимые цели использования

Защита от атак

Реализуются проверки:

  • цепочки доверия
  • совпадения домена
  • срока действия
  • самоподписанных сертификатов

Работа с самоподписанными сертификатами

Включение в список доверенных:

trustedCerts.push(selfSignedCertPEM);

Проверка:

cert.verifySignature(cert.getPublicKey());

Производительность

Проблемы:

  • обработка ASN.1 в JavaScript
  • большие цепочки сертификатов

Оптимизация:

  • кэширование разобранных объектов
  • минимизация повторных проверок

Практическая схема интеграции

  1. Инициализация списка доверенных CA
  2. Получение цепочки сертификатов
  3. Парсинг через X509
  4. Проверка подписи каждого звена
  5. Проверка корневого сертификата
  6. Валидация срока действия
  7. Проверка доменного имени

Типовой сценарий использования

  • Web-приложение с собственной системой доверия
  • Проверка подписи документов
  • Валидация сертификатов вне TLS

Расширение через WebCrypto

Jsrsasign может использовать WebCrypto для:

  • ускорения операций
  • повышения безопасности

Однако интеграция требует ручной реализации.


Управление доверием в SPA

В одностраничных приложениях:

  • список CA хранится в памяти
  • обновляется через API
  • используется для всех операций проверки

Безопасность хранения

Риски:

  • подмена localStorage
  • XSS атаки

Решения:

  • подпись списка CA
  • проверка целостности
  • ограничение источников загрузки

Модульная структура

Рекомендуется разделять:

  • модуль загрузки сертификатов
  • модуль проверки цепочки
  • модуль управления хранилищем

Поддержка различных форматов

Jsrsasign работает с:

  • PEM
  • HEX
  • Base64

Конвертация:

const hex = pemtohex(pem);

Расширяемость

Система может быть дополнена:

  • поддержкой OCSP через API
  • интеграцией с backend
  • динамическими списками доверия

Роль Jsrsasign в модели безопасности

Библиотека не заменяет встроенную TLS-проверку браузера, а дополняет её:

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