我一直在尝试实现一个SSL连接服务器和客户端使用证书,但我一直击中钉子,似乎无法进行身份验证,经过大量的帖子和线程仔细阅读,我希望你能帮我找到问题的根源。
我总是捕获在AuthenticateAsServer()
行抛出的异常:
- 系统。安全。身份验证。身份验证异常:'身份验证失败,请参见内部异常。' Win32 Exception:提供给软件包的凭据无法识别。*
现在,我只是尝试调用服务器通过chrome与此url,我没有尝试第一次与我的客户端代码,但我的authenticateAsClient()
方不是问题的来源,因为即使与谷歌chrome我不能认证:
https://192.168.1.113:32581
使用端口32581
进行测试,computer.IpPort=32581
服务器IP为192.168.1.103
、computer.IpAddress="192.168.1.103"
以下是我执行的所有步骤:
已使用PowerShell新建自签名证书创建证书
新-自签名证书-受试者DESKTOP-12345
下面是我的服务器端代码:getServerCert()
工作并返回正确的证书。ValidateServerCertificate()
从现在起返回真。
private readonly Computer computer;
private TcpClient TCP_Client;
private NetworkStream TCP_Stream;
private SslStream SSL_Stream;
private X509Certificate2 clientCertificate;
private ConcurrentQueue<string> TCP_pendingCommands = new ConcurrentQueue<string>();
private void TCP_Listen()
{
try
{
ServerCertificate = getServerCert();
if (ServerCertificate == null)
{
throw new Exception("Client certificate is not set.");
}
// Listen
TCP_Listener = new TcpListener(IPAddress.Any, computer.IpPort);
TCP_Listener.Start();
while (true)
{
Console.WriteLine("Waiting for a client to connect...");
Thread.Sleep(2000);
TCP_Client = TCP_Listener.AcceptTcpClient();
ProcessClient();
}
}
catch (Exception e)
{
Disconnect();
Console.WriteLine(e.Message);
Thread.Sleep(1000);
}
}
private void ProcessClient()
{
try
{
IPEndPoint remoteIpEndPoint = TCP_Client.Client.RemoteEndPoint as IPEndPoint;
computer.IpAddress = remoteIpEndPoint.Address.ToString();
TCP_Stream = TCP_Client.GetStream();
TCP_Stream.ReadTimeout = Timeout.Infinite;
SSL_Stream = new SslStream(TCP_Stream, false, ValidateServerCertificate);
SSL_Stream.AuthenticateAsServer(ServerCertificate, false, SslProtocols.Tls12, false);
if (!SSL_Stream.IsAuthenticated)
throw new Exception("Failed to connect.");
new Thread(() => TCP_Write(TCP_Client))
{
IsBackground = true,
Name = "SSL server TCP Write thread"
}.Start();
new Thread(() => TCP_Read(TCP_Client))
{
IsBackground = true,
Name = "SSL server TCP Read thread"
}.Start();
TCP_pendingCommands = new ConcurrentQueue<string>();
}
catch (Exception e)
{
Disconnect();
Console.WriteLine(e.Message);
Thread.Sleep(1000);
}
}
private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
// lets just return true here
return true;
}
private X509Certificate getServerCert()
{
X509Store store = new X509Store(StoreName.My,
StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509Certificate2 foundCertificate = null;
foreach (X509Certificate2 currentCertificate
in store.Certificates)
{
if (currentCertificate.IssuerName.Name
!= null && currentCertificate.IssuerName.
Name.Equals("CN=DESKTOP-12345"))
{
foundCertificate = currentCertificate;
break;
}
}
return foundCertificate;
}
这里是我的客户端,如果需要甚至认为我没有使用它successfully尚未:
private void Connect()
{
try
{
TCP_Client = new TcpClient(computer.IpAddress, computer.IpPort)
{
NoDelay = true
};
TCP_Stream = TCP_Client.GetStream();
TCP_Stream.ReadTimeout = Timeout.Infinite;
SSL_Stream = new SslStream(TCP_Stream, false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
SSL_Stream.AuthenticateAsClient("DESKTOP-12345");
byte[] buffer = new byte[4096];
int bytesRead = SSL_Stream.Read(buffer, 0, buffer.Length);
if (!SSL_Stream.IsAuthenticated)
throw new Exception("Failed to connect.");
RaisePropertyChanged(nameof(Power));
computer.RaiseComputerPropertyChanged(nameof(Power));
computer.SetComputerConnected(true);
TCP_pendingCommands = new ConcurrentQueue<string>();
}
catch (Exception e)
{
Disconnect();
Debug.Writeline(e.Message);
Thread.Sleep(1000);
}
}
public 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 true;
}
**EDIT:**我也在这些步骤中使用了openssl,但遇到了相同的异常:
生成证书和密钥:
请求-x509 -sha 256-节点-天数365 -新密钥rsa:2048 -密钥输出私有密钥-密钥输出证书. crt
使用此代码部分代替ServerCertificate = getServerCert();
:
string certFilePath = "C:\\Path\\To\\certificate.crt";
string privateKeyPath = "C:\\Path\\To\\private.key";
ServerCertificate = X509Certificate2.CreateFromPemFile(certFilePath, privateKeyPath);
1条答案
按热度按时间uxhixvfz1#
the credentials supplied to the package were not recognized
通常表示“Windows S/Channel无法访问私钥”,前两个子原因是“没有私钥”或“私钥是临时的”。CreateFromPemFile
生成临时私钥,因此这种方法肯定是这种情况。PKCS 12/PFX加载器使用与PEM加载器不同的密钥加载机制,并且PFX加载器与SslStream一起工作。