Подтвердить что ты не робот

С# Как я могу проверить цепочку сертификатов Root-CA-Cert (x509)?

Скажем, у меня есть три сертификата (в формате Base64)

Root
 |
 --- CA
     |
     --- Cert (client/signing/whatever)

Как я могу проверить сертификаты и путь/цепочку сертификатов на С#? (Все эти три сертификата не могут быть в моем магазине cert компьютера)

Изменить. У BouncyCastle есть функция для проверки. Но я стараюсь не использовать стороннюю библиотеку.

    byte[] b1 = Convert.FromBase64String(x509Str1);
    byte[] b2 = Convert.FromBase64String(x509Str2);
    X509Certificate cer1 = 
        new X509CertificateParser().ReadCertificate(b1);
    X509Certificate cer2 =
        new X509CertificateParser().ReadCertificate(b2);
    cer1.Verify(cer2.GetPublicKey());

Если cer1 не подписан cert2 (CA или root), будет исключение. Это именно то, что я хочу.

4b9b3361

Ответ 1

Для этого был разработан класс X509Chain, вы даже можете настроить, как он выполняет процесс построения цепочки.

static bool VerifyCertificate(byte[] primaryCertificate, IEnumerable<byte[]> additionalCertificates)
{
    var chain = new X509Chain();
    foreach (var cert in additionalCertificates.Select(x => new X509Certificate2(x)))
    {
        chain.ChainPolicy.ExtraStore.Add(cert);
    }

    // You can alter how the chain is built/validated.
    chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
    chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreWrongUsage;

    // Do the validation.
    var primaryCert = new X509Certificate2(primaryCertificate);
    return chain.Build(primaryCert);
}

X509Chain будет содержать дополнительную информацию о сбое проверки после Build() == false, если вам это нужно.

Изменить: Это будет гарантировать, что ваш центр сертификации действителен. Если вы хотите убедиться, что цепь идентична, вы можете проверить отпечатки вручную. Вы можете использовать следующий метод для обеспечения правильности цепи сертификации, он ожидает, что цепочка будет в порядке: ..., INTERMEDIATE2, INTERMEDIATE1 (Signer of INTERMEDIATE2), CA (Signer of INTERMEDIATE1)

static bool VerifyCertificate(byte[] primaryCertificate, IEnumerable<byte[]> additionalCertificates)
{
    var chain = new X509Chain();
    foreach (var cert in additionalCertificates.Select(x => new X509Certificate2(x)))
    {
        chain.ChainPolicy.ExtraStore.Add(cert);
    }

    // You can alter how the chain is built/validated.
    chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
    chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreWrongUsage;

    // Do the preliminary validation.
    var primaryCert = new X509Certificate2(primaryCertificate);
    if (!chain.Build(primaryCert))
        return false;

    // Make sure we have the same number of elements.
    if (chain.ChainElements.Count != chain.ChainPolicy.ExtraStore.Count + 1)
        return false;

    // Make sure all the thumbprints of the CAs match up.
    // The first one should be 'primaryCert', leading up to the root CA.
    for (var i = 1; i < chain.ChainElements.Count; i++)
    {
        if (chain.ChainElements[i].Certificate.Thumbprint != chain.ChainPolicy.ExtraStore[i - 1].Thumbprint)
            return false;
    }

    return true;
}

Я не могу проверить это, потому что у меня нет полной цепочки CA со мной, поэтому лучше всего отлаживать и выполнять код.