x509Chain.build терпит неудачу, certutil -verify проходит - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть root сертификат и лист. Лист имеет расширение OID URL CRL, которое указывает на действительное местоположение в сети. При этом:

certutil -verify .\leaf.cer

завершается неудачно с

ОШИБКА: возвращено подтверждение состояния отзыва сертификата листа Функция отзыва не смогла проверить отзыв, поскольку сервер отзыва был отключен. 0x80092013 (-2146885613 CRYPT_E_REVOCATION_OFFLINE)

Если я сделаю это:

certutil -verify .\leaf.cer .\root.cer

Затем проверка проходит, и я вижу, что CRL извлекается из сети в Fiddler.

В моем C# коде я делаю это:

X509Chain childCertChain = new X509Chain();
childCertChain.ChainPolicy.ExtraStore.Add(rootCert);
childCertChain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
childCertChain.ChainPolicy.UrlRetrievalTimeout = TimeSpan.FromSeconds(10);
if (!childCertChain.Build(childCert))
        {
            // The root cert is not in the windows certificate store, that is fine
            if (childCertChain.ChainStatus.Length != 1 || childCertChain.ChainStatus.First().Status != X509ChainStatusFlags.UntrustedRoot)
            {
                throw new Exception("Certificate validation error.");
            }
        }

Это ударит по моему исключению, и хотя chainElements будет правильно заполнен 2 сертификатами, ChainStatus покажет:

OfflineRevocation, RevocationStatusUnknown

Я также не увижу никаких веб-запросов в Fiddler. Я могу программно загрузить CRL по URL, так что это не моя среда отладки AFAIK. Любые идеи, как получить x509Chain.Build для успеха?

1 Ответ

0 голосов
/ 08 апреля 2020

Я прочитал ваш код из P C и выяснил, что случилось: ваш root сертификат не является доверенным в вашей системе. Windows CryptoAPI выбрасывает CERT_E_UNTRUSTEDROOT, когда root сертификат не является доверенным. Наряду с этим CryptoAPI завершает проверку отзыва и выдает две ошибки добавления: CRYPT_E_NO_REVOCATION_CHECK и CERT_E_UNTRUSTEDROOT, поскольку проверка отзыва была пропущена. В дополнение к ненадежным root, CryptoAPI пропускает другие проверки (например, ограничения), но не сообщает о них. Все правильно и как и ожидалось.

Вы пытаетесь разрешить ненадежных root, но делаете это неправильно, потому что таким образом вы пропускаете другие проверки (как упомянуто в предыдущем параграфе) и ваши логики c уязвимы .

Вы можете исключить ненадежное исключение root в настройках цепочки и заставить CryptoAPI продолжить проверку и вернуть успех, если не найдено других ошибок, но я настоятельно рекомендую этого не делать, потому что тогда вы открыты для любого вида MITM.

У вас есть два варианта:

  1. сделать сертификат root доверенным для компьютера (локальная система). Это может быть невозможно.
  2. вызовите функцию CertCreateCertificateChainEngine напрямую и поместите свой сертификат root в hRestrictedTrust член структуры CERT_CHAIN_ENGINE_CONFIG.

Если вы находитесь на Windows, 2-й подход является наиболее безопасным и надежным. На данный момент. NET X509Chain не реализует эту функцию. Требуется дополнительное кодирование, но альтернатив не так много.

...