X509 证书预期用途和 SSL

X509 Certificate Intended purpose and SSL

我正在考虑允许用户 select 一个证书,该证书将用于我们的一项服务的 SSL,最初用户需要 select 商店名称和列表的证书将显示在下拉列表中,我在阅读此 article 后删除了证书应该只来自 MY 存储位置 Local Computer。查看几篇文章后,我创建了以下代码

using (var store = new X509Store(StoreName.My,StoreLocation.LocalMachine))
        {
            store.Open(OpenFlags.ReadOnly);

            var certificates = store.Certificates;
            foreach (var c in certificates)
            {
                bool isSslCompatible = false;
                bool ekuExists = false;//when this value does not exist, certificate can be used for all purposes [ https://tools.ietf.org/html/rfc3280#section-4.2.1.13 ] 
                if (c.HasPrivateKey)//only chose those that have a private key
                {

                    foreach (X509Extension extension in c.Extensions)
                    {
                        if (extension.Oid.Value == "2.5.29.37")//[ Friedlname = Enhanced Key Usage, names are localised, firendly name cannot be used
                        {
                            ekuExists = true;
                            X509EnhancedKeyUsageExtension ext = (X509EnhancedKeyUsageExtension) extension;
                            OidCollection oids = ext.EnhancedKeyUsages;
                            foreach (Oid oid in oids)
                            {
                                if (/*oid.FriendlyName == "Server Authentication" || -- cannot be used as friendly names are localised*/
                                    oid.Value == "1.3.6.1.5.5.7.3.1")
                                {
                                    isSslCompatible = true;
                                }
                            }
                        }
                    }
                    if (isSslCompatible || !ekuExists)//add only if value is ssl compatible
                    {
                        SSLCertficate certificate = new SSLCertficate();

                        certificate.CertificateHash = c.GetCertHash();
                        certificate.CertificateHashString = c.GetCertHashString();
                        certificate.CertificateThumbPrint = c.Thumbprint;
                        certificate.FriendlyName = c.FriendlyName;
                        certificate.SubjectName = c.Subject;
                        certificate.HasPrivateKey = c.HasPrivateKey;

                        sslCertificates.Add(certificate);
                    }
                }
            }

上面代码的这个问题是它没有看到证书并且具有所有预期目的,我不确定如何获得这些,

,

检查属性 window,我得到以下信息, ,上面的代码似乎没有检测到这个证书,在 IIS 下检查,我能够将这个特定的证书用于 Https,我的代码是否缺少一些东西来检测有效的 SSL 证书?

MMC UI 有点误导。它的意思是“启用证书已经声明的所有用途”。

在您的过滤代码中,您要求存在 EKU 扩展并具有 TLS 服务器身份验证目的。

IETF RFC 3280 section 4.2.1.13

If the extension is present, then the certificate MUST only be used for one of the purposes indicated. If multiple purposes are indicated the application need not recognize all purposes indicated, as long as the intended purpose is present. Certificate using applications MAY require that a particular purpose be indicated in order for the certificate to be acceptable to that application.

这通常被理解为“如果没有扩展名,则证书被认为对所有目的都有效”。 TLS RFC 似乎没有具体引用 id-kp-serverAuth EKU,这意味着它是一个“严格约定”的应用程序约定来检查它。

有不同的规范覆盖了“对所有目的有效”的隐式评估,例如 IETF RFC 3161(可信时间戳)第 2.3 节:

The corresponding certificate MUST contain only one instance of the extended key usage field extension as defined in [RFC2459] Section 4.2.1.13 with KeyPurposeID having value:

id-kp-时间戳。此扩展必须是关键的。

但是,再一次,TLS 从未真正谈论它。

所以你需要更复杂一些。 Web 浏览器使用的逻辑是 if (!hasEkuExtension || hasServerAuthEku),而你的 if (hasServerAuthEku).

此外,您应该(几乎)总是通过 Value 而不是 FriendlyName 来比较 Oid 对象。 FriendlyName 已本地化,因此您的代码只会 运行 在英文系统上可靠。 Oid.Value 值是证书中的实际内容(文本化形式)。 (唯一的例外是当 Value 为 null 时,因为这意味着 API 试图表示一个没有定义 OID 的值(由于 Curve25519,这实际上只发生在 ECCurve 上))。