Я изо всех сил пытаюсь найти надежный способ проверить из моего приложения C # (.Net 4.0), если X509Certificate (или X509Certificate2) установлен флаг «Расширенная проверка» (EV). Кто-нибудь знает лучший метод?
Как проверить, включена ли расширенная проверка сертификата X509?
Ответы (2)
Вы можете проверить, содержит ли X509Certificate
один из этих OId. Кроме того, вы можете проверить источник Chromium для списка реализованных OId. Исходный код можно найти здесь. Если вы хотите придерживаться Firefox, вы можете получить реализацию здесь а>.
Теперь я обновил свой источник и протестировал его. Я написал небольшой метод для проверки X509Certificate2
по списку OId из Википедии/Chromium. В этом методе я использую список Википедии, вместо него может быть лучше взять список Chromium.
Как сохраняется OID?
Каждый CA
имеет один или несколько идентификаторов ObjectId OId
. Они не сохраняются как расширения, как вы можете догадаться, они сохраняются как запись в расширениях политики. Чтобы получить точное расширение, рекомендуется использовать Oid самого Policy Extension
, а не понятное имя. OId расширений политики — 2.5.29.32
.
Извлечение информации
Чтобы получить внутреннее содержимое расширений политики, мы можем использовать System.Security.Cryptography.AsnEncodedData
для преобразования его в удобочитаемый string
. Сама строка содержит политики, которые нам нужно сопоставить с нашим string[]
, чтобы убедиться, что он содержит один из OId EV Certificate
.
Источник
/// <summary>
/// Checks if a X509Certificate2 contains Oids for EV
/// </summary>
/// <param name="certificate"></param>
/// <returns></returns>
private static bool IsCertificateEV(X509Certificate2 certificate)
{
// List of valid EV Oids
// You can find correct values here:
// http://code.google.com/searchframe#OAMlx_jo-ck/src/net/base/ev_root_ca_metadata.cc&exact_package=chromium
// or in Wikipedia
string[] extendedValidationOids =
{
"1.3.6.1.4.1.34697.2.1",
"1.3.6.1.4.1.34697.2.2",
"1.3.6.1.4.1.34697.2.1",
"1.3.6.1.4.1.34697.2.3",
"1.3.6.1.4.1.34697.2.4",
"1.2.40.0.17.1.22",
"2.16.578.1.26.1.3.3",
"1.3.6.1.4.1.17326.10.14.2.1.2",
"1.3.6.1.4.1.17326.10.8.12.1.2",
"1.3.6.1.4.1.6449.1.2.1.5.1",
"2.16.840.1.114412.2.1",
"2.16.528.1.1001.1.1.1.12.6.1.1.1",
"2.16.840.1.114028.10.1.2",
"1.3.6.1.4.1.14370.1.6",
"1.3.6.1.4.1.4146.1.1",
"2.16.840.1.114413.1.7.23.3",
"1.3.6.1.4.1.14777.6.1.1",
"1.3.6.1.4.1.14777.6.1.2",
"1.3.6.1.4.1.22234.2.5.2.3.1",
"1.3.6.1.4.1.782.1.2.1.8.1",
"1.3.6.1.4.1.8024.0.2.100.1.2",
"1.2.392.200091.100.721.1",
"2.16.840.1.114414.1.7.23.3",
"1.3.6.1.4.1.23223.2",
"1.3.6.1.4.1.23223.1.1.1",
"1.3.6.1.5.5.7.1.1",
"2.16.756.1.89.1.2.1.1",
"2.16.840.1.113733.1.7.48.1",
"2.16.840.1.114404.1.1.2.4.1",
"2.16.840.1.113733.1.7.23.6",
"1.3.6.1.4.1.6334.1.100.1",
};
// Logic:
// Locate Certificate Policy Extension
// Convert to AsnEncodedData (String)
// Check if any of the EV Oids exist
return (
from X509Extension ext in certificate.Extensions
where ext.Oid.Value == "2.5.29.32"
select new AsnEncodedData(ext.Oid, ext.RawData).Format(true))
.Any(asnConvertedData => extendedValidationOids.Where(asnConvertedData.Contains).Any()
);
}
Если вам нужен источник для начала:
static void Main(string[] args)
{
// Create Delegate for analysis of X509Certificate
ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertificate;
// Make sample request to EV-Website to get Certificate
var wc = new WebClient();
wc.DownloadString("https://startssl.com"); // EV
wc.DownloadString("https://petrasch.biz"); // Not EV
Console.ReadLine();
}
public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
var cert = (X509Certificate2) certificate;
Console.WriteLine("Certificate: " + cert.GetNameInfo(X509NameType.SimpleName, true) + " -> " + IsCertificateEV(cert));
return true;
}
Если кто-то знает лучший способ достичь этой цели, сообщите нам об этом.
CertificatePolicy
. В настоящее время я тестирую CAPI, чтобы получить список этих политик, но я не могу получить доступ к этому списку. Это было бы решением.
- person Dennis Alexander; 06.02.2013
Я думал, что опубликую более полный ответ, хотя этот вопрос довольно старый. Я не буду отказываться от существующего ответа, чтобы этот был завершен.
Сертификат EV имеет несколько проверок, которые необходимо пройти, чтобы браузер считал, что сертификат является EV.
- Что сертификат имеет идентификатор политики, известный как политика EV.
- Отпечаток корня сертификата соответствует закрепленному идентификатору политики.
- Сертификат должен пройти онлайн-проверку отзыва.
- Если значение notBefore (дата выдачи) сертификата после 01.01.2015, сертификат должен поддерживать прозрачность сертификата.
- Сертификат должен быть выдан доверенным корнем.
- Что все цепочки действительны, если существует несколько путей доверия.
Разберем каждый из них.
Идентификатор политики
Сертификат имеет расширение, называемое идентификаторами политики. Доступ к расширениям можно получить из свойства X509Certificate2.Extensions
. Расширение идентификатора политики имеет идентификатор объекта ("OID") 2.5.29.32
. Таким образом, мы можем получить необработанное расширение, используя что-то вроде этого:
var extension = certificate.Extensions["2.5.29.32"]
Если это возвращает значение null, что означает, что политики вообще нет, вы можете сразу предположить, что это не сертификат EV.
Скорее хоть у сертификата есть какая-то политика. В этом случае вам необходимо расшифровать данные. Атрибут даст вам это в необработанном ASN.1, нам нужно разобраться в этом.
К сожалению, сегодня в .NET нет ничего, что могло бы сделать это из коробки. Однако CryptDecodeObjectEx
может сделайте это, если вы используете вызов платформы. Подробности о том, как это сделать, я опущу, но есть много информации, чтобы показать, как вызывать эту функцию. Вы захотите вызвать его с параметром lpszStructType, установленным на значение (IntPtr)16
. Это вернет вам CERT_POLICIES_INFO
, которая содержит счетчик и указатель на массив из CERT_POLICY_INFO
структур. В этой структуре есть поле под названием pszPolicyIdentifier
. Нас интересует именно этот OID политики.
У каждого центра сертификации есть один или несколько OID, которые они используют для создания сертификата как EV. Каждый ЦС документирует их на своей странице политик. Тем не менее, лучшее место для получения актуального списка — это, вероятно, Исходный код Chromium.
Если у сертификата есть политика, соответствующая одному из этих OID, то мы можем перейти к следующей проверке.
Корневой отпечаток пальца
Если вы посмотрите на источник Chromium по приведенной выше ссылке, вы увидите, что в дополнение к идентификаторам политики он также хранит отпечаток корня SHA256.
Это связано с тем, что в дополнение к сертификату, имеющему правильный OID, он должен быть выдан центром сертификации, чьи отпечатки пальцев совпадают. В исходниках Chromium мы видим что-то вроде этого:
{{0x06, 0x3e, 0x4a, 0xfa, 0xc4, 0x91, 0xdf, 0xd3, 0x32, 0xf3, 0x08,
0x9b, 0x85, 0x42, 0xe9, 0x46, 0x17, 0xd8, 0x93, 0xd7, 0xfe, 0x94,
0x4e, 0x10, 0xa7, 0x93, 0x7e, 0xe2, 0x9d, 0x96, 0x93, 0xc0}},
{
// AC Camerfirma uses the last two arcs to track how the private key
// is managed - the effective verification policy is the same.
"1.3.6.1.4.1.17326.10.14.2.1.2", "1.3.6.1.4.1.17326.10.14.2.2.2",
}
Таким образом, сертификат должен иметь идентификаторы политики «1.3.6.1.4.1.17326.10.14.2.1.2» или «1.3.6.1.4.1.17326.10.14.2.2.2», но корень должен иметь отпечаток SHA1 двоичного файла, показанного выше. .
Это предотвращает использование мошенническим ЦС идентификатора политики, которым он не владеет.
Проверка отзыва
Если браузер не может проверить, отозван ли сертификат, он не будет считаться сертификатом EV. Должна быть выполнена онлайн проверка отзыва, хотя клиент может кэшировать результат.
Вы можете выполнить проверку отзыва при использовании X509Chain.Build
, установив соответствующие флаги в цепочке перед вызовом Build
.
Прозрачность сертификата
Проверить это немного сложнее, но у Google есть соответствующая документация на веб-сайте Certificate Transparency< /а>. Если сертификат был выдан после 01.01.2015, требуется прозрачность сертификата. Некоторые сертификаты также занесены Chrome в белый список, как указано в Страница проекта Chromium.
Доверенный корень
Это довольно просто, но сертификат должен принадлежать доверенному корню. Если сертификат самоподписанный, он не может быть EV. Это можно еще раз проверить при вызове X509Chain.Build()
.
Несколько путей доверия
У сертификата может быть несколько путей доверия, например, если сертификат был выпущен корнем с перекрестной подписью. При наличии нескольких путей доверия все пути должны быть действительными. Аналогичным образом проверка отзыва должна выполняться для всех путей. Если какой-либо из путей показывает сертификат как отозванный, то сертификат недействителен.
К сожалению, насколько я знаю, .NET и даже Win32 не имеют хороших средств проверки всех цепочек сертификатов или даже получения более одной цепочки.
Сочетая все это, если все они пройдены, сертификат можно считать сертификатом EV.