c# - 如何为 TcpClient 实现证书固定

标签 c# ssl certificate-pinning

我正在尝试在将暴露给公共(public)互联网的服务器上设置 TCP 流(非 HTTP),但只有“选择的”客户端应该能够连接到。据我了解,这通常由证书固定处理,但我不熟悉如何完成的所有细节。

  • 为服务器生成 SSL 证书。这很容易。
  • 设置服务器。当客户端连接时,让它调用类似以下内容:

  • private SslStream GetSslStream(TcpClient client, string certificateFile)
    {
        var c = X509Certificate.CreateFromCertFile(certificateFile);
        var cert = new X509Certificate2(c);
        if (!cert.Verify()) {
            throw new Exception("Certificate failed verification");
        }
        var stream = new SslStream(client.GetStream(), false, VerifyClientCert);
        stream.AuthenticateAsServer(cert, true, true);
        return stream;
    }
    
  • 客户端证书从何而来?它是服务器 SSL 证书的副本吗?它是必须以某种方式从服务器的证书派生的单独证书吗?它是一个完全不同的证书吗?
  • VerifyClientCert 中的内容确保它是正确的证书的方法?只需 Verify()并检查 Thumbprint与预期值相反,还是需要发生更多事情?
  • 每个客户都应该获得相同客户证书的副本吗?
  • 最佳答案

    证书固定是一个不同的概念。服务器使用 SSL 证书时,通常是由某个证书颁发机构颁发的。该机构的证书又可以由另一个证书机构颁发,形成一个链。当客户端验证服务器证书时,它会检查该证书颁发机构是否被此特定客户端“信任”。 “受信任”反过来意味着上述链中的某些证书​​受此客户端信任。例如,Windows 和 Linux 操作系统都带有一组默认受信任的证书权限。如果服务器证书在其链中具有其中一些权限 - 那么它也是受信任的。
    证书固定意味着您作为客户端对服务器证书施加的限制比上述限制更多。例如,你可能会说对于这个域\端点,我只信任这个特定的证书(带有这个特定的摘要),我根本不关心信任链。或者对于这个端点,我只信任这个特定的证书颁发机构。这是证书固定。您可以将它用于您的服务器,但它有它的缺点,我不会在这里描述。
    现在回到你的问题。您所描述的称为客户端证书身份验证。在 SSL 握手中,不仅服务器可以提供证书供客户端验证。服务器也可能要求客户端发送他自己的证书,以验证该客户端。这个证书当然与服务器的证书完全不同。
    每个客户都必须有不同证书。通常使用以下两个选项之一:

  • 您(服务器所有者)创建自己的证书颁发机构(例如使用几个简单的 openssl 命令),然后您从该颁发机构为每个客户端颁发单独的证书。然后,您将这些证书(每个客户端一个),包括私钥,发送给它们各自的客户端。之后,您可以丢弃(删除)这些证书,因为您将不再需要它们。验证客户端证书时 - 只需检查它是否由您的证书颁发机构颁发。
  • 或者为每个客户端颁发单独的证书,并且您存储这些证书的指纹(摘要\哈希),每个客户端一个。然后在验证期间确保指纹具有给定客户端的预期值。好处是您可以要求客户端生成此类证书并向您(服务器所有者)发送指纹。然后,您永远不会拥有该证书的私钥(与您自己的证书颁发机构的方法不同,您自己生成证书并在某一时刻拥有其私钥)。
  • 关于c# - 如何为 TcpClient 实现证书固定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69598046/

    相关文章:

    c# - LINQ 到 SQL : Change timestamp forcefully of a table

    c# - .Net SFTP 连接中的错误 key 格式无效

    apache - 将 SSL 添加到我的网站

    ssl - STM32Cube_FW_F7 客户端 mbedTLS SSL 握手失败并显示 FATAL_ALERT

    c# - 在后面的 C# 代码中显示 "Yes/No"警告框

    apache - ssl_error_rx_record_too_long 和 Apache SSL

    ssl - SSL固定(嵌入主机)和普通证书(由服务器提供)有什么区别

    android - 如何使用 Resttemplate 在 android 中使用 ssl pinning 验证 hsotnameverifyer

    ios - 如何使用 alamofire 管理器在 ios app swift4 中添加 ssl 证书固定?

    c# - OverflowException 仅在 VB.net 中,而不在 C# 中