SslStream 和身份验证
SslStream and Authentication
看了很久的MSDN信息文章,还是没看懂。
基于不需要客户端身份验证的假设:
1.When我调用SslStream.AuthenticateAsServer(...)
这个方法是在服务器端调用还是在客户端调用?
2.When 建立 SslStream 是只有服务器负责建立 SslStream
还是服务器和客户端都负责?
3.If 只是服务端的责任,是不是意味着客户端可以直接使用正则send()
和receive()
不自己创建SslStream的操作?
4.Does客户端需要获取证书文件才能对服务器进行身份验证?
非常感谢,关于这个话题我真的找不到太多信息,我已经搜索了很长时间...
EDIT:MSDN 在本页底部有一个完整的工作示例:https://msdn.microsoft.com/en-us/library/system.net.security.sslstream?f=255&MSPPError=-2147217396 - 所以您应该真正开始在那里进行试验,因为该示例包含所有内容.
原回答:
我必须在这个回答前加上 "client authentication not required" 大多数 SSL 实现的情况。客户端身份验证很少见:您很可能会在 VPN 应用程序、银行业和其他安全应用程序中看到它。因此,当您尝试使用 SslStream() 时,在没有客户端身份验证的情况下启动是明智的。
当您浏览 HTTPS 网站时,您不会使用客户端证书对浏览器进行身份验证,而只是想确认您要连接的服务器名称是否与证书中的 CNAME 匹配,并且服务器证书由您的机器信任的 CA 签名 - 还有更多内容,但本质上就是它归结为。
所以,说了这么多,让我来回答你的问题:
1) SslStream.AuthenticateAsServer(...)
仅在服务器端使用服务器 509 证书完成。在客户端,您必须使用服务器名称调用 SslStream.AuthenticateAsClient(serverName)
作为您证书的 CNAME(通用名称)(示例:"domain.com")
2) SslStream
必须同时为客户端和服务器创建。您只需在其周围 "wrapping" 一个 TcpClient
NetworkStream
即可创建它(例如,但还有其他方法)
服务器示例:
// assuming an 509 certificate has been loaded before in an init method of some sort
X509Certificate serverCertificate = X509Certificate2.CreateFromCertFile("c:\mycert.cer"); // for illustration only, don't do it like this in production
...
// assuming a TcpClient tcpClient was accepted somewhere above this code
slStream sslStream = new SslStream(tcpClient.GetStream(), false);
sslStream.AuthenticateAsServer(
serverCertificate,
false,
SslProtocols.Tls,
true);
3) 否。通信在两端都是加密的。所以双方都必须使用SslStream
。在客户端使用 receive()
和 send()
会产生二进制加密数据。
4) 否。客户端将回调方法传递给 SslStream
创建以验证服务器收到的证书。
示例:
// assuming a TcpClient tcpClient was connected to the server somewhere above this code
SslStream sslStream = new SslStream(
tcpClient.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
sslStream.AuthenticateAsClient(serverName); // serverName: "domain.com" for example
然后在您的代码中的其他地方:
public static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None) {
return true;
}
Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
// refuse connection
return false;
}
看了很久的MSDN信息文章,还是没看懂。
基于不需要客户端身份验证的假设:
1.When我调用SslStream.AuthenticateAsServer(...)
这个方法是在服务器端调用还是在客户端调用?
2.When 建立 SslStream 是只有服务器负责建立 SslStream
还是服务器和客户端都负责?
3.If 只是服务端的责任,是不是意味着客户端可以直接使用正则send()
和receive()
不自己创建SslStream的操作?
4.Does客户端需要获取证书文件才能对服务器进行身份验证?
非常感谢,关于这个话题我真的找不到太多信息,我已经搜索了很长时间...
EDIT:MSDN 在本页底部有一个完整的工作示例:https://msdn.microsoft.com/en-us/library/system.net.security.sslstream?f=255&MSPPError=-2147217396 - 所以您应该真正开始在那里进行试验,因为该示例包含所有内容.
原回答:
我必须在这个回答前加上 "client authentication not required" 大多数 SSL 实现的情况。客户端身份验证很少见:您很可能会在 VPN 应用程序、银行业和其他安全应用程序中看到它。因此,当您尝试使用 SslStream() 时,在没有客户端身份验证的情况下启动是明智的。
当您浏览 HTTPS 网站时,您不会使用客户端证书对浏览器进行身份验证,而只是想确认您要连接的服务器名称是否与证书中的 CNAME 匹配,并且服务器证书由您的机器信任的 CA 签名 - 还有更多内容,但本质上就是它归结为。
所以,说了这么多,让我来回答你的问题:
1) SslStream.AuthenticateAsServer(...)
仅在服务器端使用服务器 509 证书完成。在客户端,您必须使用服务器名称调用 SslStream.AuthenticateAsClient(serverName)
作为您证书的 CNAME(通用名称)(示例:"domain.com")
2) SslStream
必须同时为客户端和服务器创建。您只需在其周围 "wrapping" 一个 TcpClient
NetworkStream
即可创建它(例如,但还有其他方法)
服务器示例:
// assuming an 509 certificate has been loaded before in an init method of some sort
X509Certificate serverCertificate = X509Certificate2.CreateFromCertFile("c:\mycert.cer"); // for illustration only, don't do it like this in production
...
// assuming a TcpClient tcpClient was accepted somewhere above this code
slStream sslStream = new SslStream(tcpClient.GetStream(), false);
sslStream.AuthenticateAsServer(
serverCertificate,
false,
SslProtocols.Tls,
true);
3) 否。通信在两端都是加密的。所以双方都必须使用SslStream
。在客户端使用 receive()
和 send()
会产生二进制加密数据。
4) 否。客户端将回调方法传递给 SslStream
创建以验证服务器收到的证书。
示例:
// assuming a TcpClient tcpClient was connected to the server somewhere above this code
SslStream sslStream = new SslStream(
tcpClient.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
sslStream.AuthenticateAsClient(serverName); // serverName: "domain.com" for example
然后在您的代码中的其他地方:
public static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None) {
return true;
}
Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
// refuse connection
return false;
}