为了账号安全,请及时绑定邮箱和手机立即绑定

使用 SslStream 时验证自签名证书链

使用 SslStream 时验证自签名证书链

C#
慕尼黑8549860 2023-09-16 17:50:45
我有一个链.pem-----BEGIN CERTIFICATE-----// My server cert signed by intemediate CA-----END CERTIFICATE----------BEGIN CERTIFICATE-----// My intermediate cert signed by root CA-----END CERTIFICATE----------BEGIN CERTIFICATE-----// My self signed root cert-----END CERTIFICATE-----以及server.key.pem-----BEGIN RSA PRIVATE KEY-----// Private key for server cert-----END RSA PRIVATE KEY-----从那里,我生成一个 pfx 文件 - 其中包含服务器证书及其私钥以及链的其余部分。openssl pkcs12 -export -out certificate.pfx -inkey server.key.pem -in chain.pem我将导出密码留空接下来我用 SslStream 托管一个 TcpListenernamespace fun_with_ssl{    internal class Program    {        public static int Main(string[] args)        {            var serverCertificate = new X509Certificate2("certificate.pfx");            var listener = new TcpListener(IPAddress.Any, 1443);            listener.Start();            while (true)            {                using (var client = listener.AcceptTcpClient())                using (var sslStream = new SslStream(client.GetStream(), false))                {                    sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls12, false);                    //send/receive from the sslStream                }            }        }    }}但是当我尝试从 openssl 检查链时,它失败了openssl s_client -connect 127.0.0.1:1443 -CAfile ca.cert.pemCONNECTED(00000005)depth=0 CN = SERVERverify error:num=20:unable to get local issuer certificateverify return:1depth=0 CN = SERVERverify error:num=21:unable to verify the first certificateverify return:1---Certificate chain 0 s:CN = SERVER   i:CN = Intermediate---Server certificate-----BEGIN CERTIFICATE-----// My Server certificate-----END CERTIFICATE-----subject=CN = SERVER我似乎没有提供中间证书或根证书,以便它可以验证链。我在这里缺少什么?在我的场景中,客户端将拥有根证书公钥。
查看完整描述

1 回答

?
吃鸡游戏

TA贡献1829条经验 获得超7个赞

即使 PFX 包含整个链,使用单证书构造函数也会使其仅加载具有私钥的证书,其余的都会被丢弃。

即使使用 load-the-PFX-as-a-collection 方法,SslStream 也仅使用集合来查找可接受的服务器证书(具有私钥和正确的 EKU 值),然后忽略其余部分。

仅当 X509Chain 通过系统环境上下文找到中间证书时才会发送中间证书。如果您的证书不是公共信任的,那么您的方案的最佳答案是将中间证书(以及可选的根证书)添加到 CurrentUser\CA ( )X509StoreName.CertificateAuthority证书存储中。“CA”存储不提供信任,它只是系统见过的所有中间发行者 CA 的一个抓包,系统在构建新链时将其用作缓存。


您可以在启动时以编程方式执行此操作


X509Certificate2 serverCertificate = null;


using (X509Store store = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser))

{

    store.Open(OpenFlags.ReadWrite);


    X509Certificate2Collection coll = new X509Certificate2Collection();

    coll.Import("certificate.pfx");


    foreach (X509Certificate2 cert in coll)

    {

        if (cert.HasPrivateKey)

        {

            // Maybe apply more complex logic if you really expect multiple private-key certs.

            if (serverCertificate == null)

            {

                serverCertificate = cert;

            }

            else

            {

                cert.Dispose();

            }

        }

        else

        {

            // This handles duplicates (as long as no custom properties have been applied using MMC)

            store.Add(cert);

            cert.Dispose();

        }

    }

}


// tcpListener, et al.

其他选项:将整个集合输入 X509Chain.ChainPolicy.ExtraStore,在 serverCert 上调用 X509Chain.Build,仅在第一个证书之后添加证书(也可以不添加最后一个证书)...仅取决于预计需要多少额外内容位于 PFX 中。


查看完整回答
反对 回复 2023-09-16
  • 1 回答
  • 0 关注
  • 92 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信