[英].Net SslStream with Client Certificate
我沒有運氣讓客戶端證書與我的 SslStream 項目一起使用。 無論我做什么,我都無法讓它實際使用客戶端證書,盡管事實上所有證書都是有效且受信任的,並且我已經為我自己生成的證書導入了 CA 證書,但它只是沒有工作。 我一定遺漏了一些東西,但我已經經歷了幾十次,查看了文檔、示例和數小時的谷歌搜索,但我就是無法讓它工作。 我究竟做錯了什么?
客戶端:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace SslClient
{
class SslClientProgram
{
static void Main(string[] args)
{
TcpClient client = new TcpClient("localhost", 443);
SslStream stream = new SslStream(client.GetStream(), false, VerifyServerCertificate, null);
Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
string location = assembly.Location;
int pos = location.LastIndexOf('\\');
location = location.Substring(0, pos);
X509Certificate2 certificate = new X509Certificate2(location + "\\my.client.certificate.pfx", "password");
stream.AuthenticateAsClient("my.host.name", new X509Certificate2Collection(certificate), System.Security.Authentication.SslProtocols.Tls, false);
StreamReader reader = new StreamReader(stream);
StreamWriter writer = new StreamWriter(stream);
while (true)
{
string line = System.Console.ReadLine();
writer.WriteLine(line);
writer.Flush();
if (line == "close") break;
line = reader.ReadLine();
System.Console.WriteLine("Received: {0}", line);
}
stream.Close();
}
private static bool VerifyServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
}
}
服務器:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace SslServer
{
class SslServerProgram
{
static void Main(string[] args)
{
TcpListener server = new TcpListener(System.Net.IPAddress.Loopback, 443);
server.Start();
TcpClient client = server.AcceptTcpClient();
SslStream stream = new SslStream(client.GetStream(), false, VerifyClientCertificate, null);
Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
string location = assembly.Location;
int pos = location.LastIndexOf('\\');
location = location.Substring(0, pos);
X509Certificate2 certificate = new X509Certificate2(location + "\\my.server.certificate.pfx", "password");
stream.AuthenticateAsServer(certificate, false, System.Security.Authentication.SslProtocols.Tls, false);
if (stream.RemoteCertificate != null)
{
System.Console.WriteLine(stream.RemoteCertificate.Subject);
}
else
{
System.Console.WriteLine("No client certificate.");
}
StreamReader reader = new StreamReader(stream);
StreamWriter writer = new StreamWriter(stream);
bool clientClose = false;
while (!System.Console.KeyAvailable)
{
System.Console.WriteLine("Waiting for data...");
string line = reader.ReadLine();
System.Console.WriteLine("Received: {0}", line);
if (line == "close")
{
clientClose = true;
break;
}
writer.WriteLine(line);
writer.Flush();
}
if (!clientClose) System.Console.ReadKey();
stream.Close();
server.Stop();
}
private static bool VerifyClientCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
}
}
無論我嘗試什么,服務器總是說“沒有客戶端證書”。
事實證明, AuthenticateAsServer
是這里的關鍵——更具體地說,是第二個參數。
如果clientCertificateRequired
為false
,它將完全忽略客戶端證書,即使客戶端指定了一個,但如果為true
,它將允許它們,但如果沒有指定客戶端證書,則不會拋出異常。
愚蠢的我 - 我認為clientCertificateRequired
設置為 true 意味着它實際上是必需的,因為 .Net 文檔將其描述為:
“一個布爾值,指定客戶端是否必須提供認證證書。”* (強調我的)
我的期望是,如果它是true
,並且我沒有發送客戶端證書,那么它就會失敗。 這是 Microsoft 文檔不完全准確的一個明顯案例。
更新: clientCertificateRequired
參數的最新文檔包括“注意這只是一個請求——如果沒有提供證書,服務器仍然接受連接請求”。
我有同樣的問題和我的解決方案:我設置了 clientCertificateRequired true
,並使用下面的代碼手動檢查 clientCertificate
state.SslStream = new SslStream(state.NetworkStream, true , new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
private bool ValidateServerCertificate(object sender, X509Certificate certificate , X509Chain chain, SslPolicyErrors sslPolicyErrors) { if (certificate == null) return false; var clientCertificate = certificate as X509Certificate2; if (!serverCertificate.Thumbprint.Equals(clientCertificate.Thumbprint)) return false; ///For self-signed certificate, return true. return true; //if (sslPolicyErrors == SslPolicyErrors.None) // return true; //Log(string.Format("Certificate validation error:{0}", sslPolicyErrors)); //return false; }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.