Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 要求SslStream仅接受由特定公钥签名的证书_C#_.net_Security_Ssl_Sslstream - Fatal编程技术网

C# 要求SslStream仅接受由特定公钥签名的证书

C# 要求SslStream仅接受由特定公钥签名的证书,c#,.net,security,ssl,sslstream,C#,.net,Security,Ssl,Sslstream,我有一个工作的实现,但要确保它是安全的。目标是使用SSLStream,并且只接受来自服务器的由特定RSA密钥签名的SSL证书 这是我的连接代码: var client = new TcpClient("server_address", port_number); var sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCa

我有一个工作的实现,但要确保它是安全的。目标是使用SSLStream,并且只接受来自服务器的由特定RSA密钥签名的SSL证书

这是我的连接代码:

        var client = new TcpClient("server_address", port_number);
        var sslStream = new SslStream(client.GetStream(), false,
            new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
        sslStream.AuthenticateAsClient("SpeechGrid");
下面是我对ValidateServerCertificate的实现:

    private static bool ValidateServerCertificate(object sender, X509Certificate certificate,
            X509Chain chain, SslPolicyErrors sslPolicyErrors) {

        // Only accept our specific key pair
        foreach (var cert in chain.ChainElements) {
            if (cert.Certificate.GetPublicKeyString() == k_prodPublicKey) {
                return true;
            }
        }

        return false;
    }
由于X509Chain对象的丰富性,我希望确保不需要检查X509ChainStatusFlags.NotSignatureValid等内容

        foreach (var status in chain.ChainStatus) {
            switch (status.Status) {
                case X509ChainStatusFlags.Cyclic:
                case X509ChainStatusFlags.NotSignatureValid:
                case X509ChainStatusFlags.PartialChain:
                    return false;
            }
        }
例如,攻击者是否有可能“声明”由我的公钥签名,发送无效签名,而此攻击会有效,因为.NET假定我正在检查所有这些标志

谢谢

更新:好的,到目前为止,我已决定将以下检查置于原始foreach之上。注意,这有点特定于应用程序;例如,如果我想让证书过期,我会检查NotTimeValid等

        foreach (var status in chain.ChainStatus) {
            switch (status.Status) {
                case X509ChainStatusFlags.Cyclic:
                case X509ChainStatusFlags.NotSignatureValid:
                case X509ChainStatusFlags.PartialChain:
                    return false;
            }
        }

您可以检查sslPolicyErrors参数是否存在其他错误,例如过期错误,或者证书是否不受信任。如果一切正常,则应返回SslPolicyErrors.None。从公钥派生私钥在计算上是不可行的,因此您不需要担心其他人创建相同的密钥对并对其签名

我会将您在问题更新中添加的检查逻辑颠倒过来。而不是寻找可能的错误并接受其他一切:

foreach (thing that I can think of that might be wrong)
 return false;

if (public key matches regardless of other policy errors)
 return true;
…相反,我会寻找可能错误但可以接受的地方,并拒绝任何其他政策错误:

if (policy errors)
{
 foreach (error that is acceptable: remote name mismatch, untrusted root, etc.)
   policy errors -= that particular error
}

if (any policy errors left)
 return false;
else if (public key matches)
 return true;
else
 return false;
第一部分是这样的(我没有测试或编译):


公钥用于一般公共密钥。。。不过,只有您(拥有私钥的人)可以解密加密的消息。如果要确保数据确实来自第三方,请从他们那里获取公钥(他们将使用密钥加密数据)。在我的示例中,它将SslPolicyErrors显示为“System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch | System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors”。在连锁状态下,它说不可信。请注意,我的证书不是由CA签署的。因此,我应该检查以确保不可信是唯一的链状态吗?RemoteCertificateNameMismatch表示您的客户端连接到的主机名与证书上的主机名不匹配。如果您正在连接到“www.myapp.com”,则证书上的名称也应与之匹配。由于证书未作为受信任的根CA安装在客户端计算机的证书存储中,因此出现不可信错误。您可以在存储中安装该CA,也可以忽略该错误,因为您需要对公钥进行另一次显式检查。