当我在IE(工具/ Internet选项/内容/证书)中手动导入证书时,我的C#.NET SSL连接有效,但如何通过代码加载证书? 这是我的代码:
TcpClient client = new TcpClient(ConfigManager.SSLSwitchIP, Convert.ToInt32(ConfigManager.SSLSwitchPort));
SslStream sslStream = new SslStream(
client.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
sslStream.AuthenticateAsClient("Test");
如果我在Internet Explorer中手动导入我的证书文件,上面的代码工作正常。但是,如果我从IE中删除我的证书并使用以下代码,我将获得身份验证例外:
sslStream.AuthenticateAsClient("Test", GetX509CertificateCollection(), SslProtocols.Default, false);
这是'GetX509CertificateCollection'方法:
public static X509CertificateCollection GetX509CertificateCollection()
{
X509Certificate2 certificate1 = new X509Certificate2("c:\\ssl.txt");
X509CertificateCollection collection1 = new X509CertificateCollection();
collection1.Add(certificate1);
return collection1;
}
如何动态加载证书?
答案 0 :(得分:4)
基于owlstead的回答,这里是我如何在验证回调中使用单个CA证书和自定义链来避免微软的存储。
默认情况下我不想出如何使用此链(chain2
),这样就不需要回调了。也就是说,将它安装在ssl套接字上,连接将“正常工作”。而且我不想出如何安装它以便传递给回调。也就是说,我必须为每次调用回调构建链。我认为这些是.Net中的架构缺陷,但我可能会遗漏一些明显的东西。
该功能的名称无关紧要。下面,VerifyServerCertificate
与RemoteCertificateValidationCallback
的回调相同。您也可以将其用于ServerCertificateValidationCallback
中的ServicePointManager
。
static bool VerifyServerCertificate(object sender, X509Certificate certificate,
X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
try
{
String CA_FILE = "ca-cert.der";
X509Certificate2 ca = new X509Certificate2(CA_FILE);
X509Chain chain2 = new X509Chain();
chain2.ChainPolicy.ExtraStore.Add(ca);
// Check all properties
chain2.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
// This setup does not have revocation information
chain2.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
// Build the chain
chain2.Build(new X509Certificate2(certificate));
// Are there any failures from building the chain?
if (chain2.ChainStatus.Length == 0)
return true;
// If there is a status, verify the status is NoError
bool result = chain2.ChainStatus[0].Status == X509ChainStatusFlags.NoError;
Debug.Assert(result == true);
return result;
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return false;
}
答案 1 :(得分:3)
Google快速向我指出了Microsoft SslStream
类的一段文字。
身份验证由安全支持提供商(SSPI)处理 渠道提供商。客户有机会控制 通过指定a来验证服务器的证书 创建一个
RemoteCertificateValidationCallback
委托 SslStream。服务器还可以通过提供a来控制验证RemoteCertificateValidationCallback
代表。引用的方法 代表包括远程方的证书和任何错误 验证证书时遇到SSPI。注意,如果 server指定委托,调用委托的方法 无论服务器是否请求客户端身份验证。如果 服务器没有请求客户端身份验证,服务器的 委托方法接收空证书和空数组 证书错误。
因此,只需实现委托并自行进行验证。
答案 2 :(得分:2)
在尝试通过SSLStream对象作为客户端进行身份验证之前,我写了另一种方法将我的证书添加到受信任的根证书颁发机构(root):
public static void InstallCertificate()
{
X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
string fileName = "sslcert.pem";
X509Certificate2 certificate1;
try
{
certificate1 = new X509Certificate2(fileName);
}
catch (Exception ex)
{
throw new Exception("Error loading SSL certificate file." + Environment.NewLine + fileName);
}
store.Add(certificate1);
store.Close();
}
然后:
InstallCertificate();
sslStream.AuthenticateAsClient("Test");
没有任何警告或错误,它工作正常。但基本问题仍未解决:
如何在不在Windows中安装证书的情况下使用证书作为客户端进行身份验证?