C# 区分根CA和中间CA证书

C# 区分根CA和中间CA证书,c#,ssl,.net-core,x509certificate2,C#,Ssl,.net Core,X509certificate2,我已设法确定X509Certificate2集合中的证书是否为证书颁发机构证书,但如何安全地确定它是根证书还是中间证书?以下各项是否足够安全 var collection = new X509Certificate2Collection(); collection.Import("test.pfx", "password", X509KeyStorageFlags.PersistKeySet); foreach (X509Certificate2 cert in collection) {

我已设法确定X509Certificate2集合中的证书是否为证书颁发机构证书,但如何安全地确定它是根证书还是中间证书?以下各项是否足够安全

var collection = new X509Certificate2Collection();
collection.Import("test.pfx", "password", X509KeyStorageFlags.PersistKeySet);

foreach (X509Certificate2 cert in collection)
{
    var basicConstraintExt = cert.Extensions["2.5.29.19"] as X509BasicConstraintsExtension;
    if (basicConstraintExt != null)
    {
        Log.Debug($"    Subject is: '{cert.Subject}'");
        Log.Debug($"    Issuer is: '{cert.Issuer}'");
        if (basicConstraintExt.CertificateAuthority)
        {
            Log.Debug("I am a CA Cert.");
            if (cert.Subject == cert.Issuer)
            {
                Log.Debug("My Subject matches Issuer.");
            }
            else
            {
                Log.Debug("My Subject does not match Issuer.");
            }
            Log.Debug(cert.Verify() ? "I verify" : "I do not verify");
        }
        else
        {
            Log.Debug("I am not a CA Cert.");
        }
    }
}
结果:

 Displaying Cert #1 in collection
 ********************************

 Subject is: 'CN=Intermediate-CA, DC=test, DC=lan'
 Issuer is: 'CN=Root-CA, DC=test, DC=lan'
 - I am a CA Cert.
 - My Subject does not match Issuer.
 - I do not verify


 Displaying Cert #2 in collection
 ********************************

 Subject is: 'CN=Root-CA, DC=test, DC=lan'
 Issuer is: 'CN=Root-CA, DC=test, DC=lan'
 - I am a CA Cert.
 - My Subject matches Issuer.
 - I do not verify

不确定这是否有助于红隼,但我会尝试下面的代码

我们将使用类来构造和验证链

var collection = new X509Certificate2Collection();
collection.Import("test.pfx", "password");

var chain = new X509Chain();
chain.ChainPolicy.ExtraStore.AddRange(collection);
// untrusted root error raise false-positive errors, for example RevocationOffline
// so skip possible untrusted root chain error.
chain.VerificationFlags |= X509VerificationFlags.AllowUnknownCertificateAuthority;
// revocation checking is client's responsibility. Skip it.
chain.RevocationMode = X509VerificationFlags.NoCheck;
// build the chain.
Boolean isValid = chain.Build(collection[0]);
// explore chain.ChainElements collection. First item should be your leaf
// certificate and last item should be root certificate

所有这些内容都位于
System.Security.Cryptography.X509Certificates
命名空间中。在这段代码中,我假设PFX中的第一个证书是leaf证书(在99%的情况下是这样的,除非有人试图忽略标准)。通过探索
chain.ChainElements
集合,您可以找到链中每个证书的问题。

您还可以检查签名。RootCA是自签名的。因此,如果您使用同一证书中的公钥验证证书的签名,它应该告诉您它是自签名的。如果主题DN和发行者DN匹配并且是CA,那么您已经找到了您的RootCA。太好了!谢谢我是否必须使用BouncyCastle之类的工具才能获得签名-/您可以使用
X509Certificate2.Verify()
验证签名。你不需要用BC来做这个。它还进行信任检查。此外,我要注意,提供的代码在本地化(非英语)系统上无效且容易出错。感谢v.much@Crypt32,我将改为按Oid.value搜索,因此它不限于英语。如何使用Verify()确定它是否是自签名的?我试图通过MS文档了解这一点,但我不清楚。
var collection = new X509Certificate2Collection();
collection.Import("test.pfx", "password");

var chain = new X509Chain();
chain.ChainPolicy.ExtraStore.AddRange(collection);
// untrusted root error raise false-positive errors, for example RevocationOffline
// so skip possible untrusted root chain error.
chain.VerificationFlags |= X509VerificationFlags.AllowUnknownCertificateAuthority;
// revocation checking is client's responsibility. Skip it.
chain.RevocationMode = X509VerificationFlags.NoCheck;
// build the chain.
Boolean isValid = chain.Build(collection[0]);
// explore chain.ChainElements collection. First item should be your leaf
// certificate and last item should be root certificate