我需要在使用TCP / IP套接字进行通信的各种进程之间提供安全通信。我想要身份验证和加密。我不想重新发明轮子,而是真的想使用SSL和SslStream类以及自签名证书。我想要做的是根据本地应用程序中的已知副本验证远程进程的证书。 (不需要是证书颁发机构,因为我打算手动复制证书。)
为此,我希望应用程序能够在第一次运行时自动生成新的证书。除了makecert.exe之外,看起来this link显示了一种自动生成自签名证书的方法,所以这是一个开始。
我查看了SslStream的AuthenticateAsServer和AuthenticateAsClient方法。您可以提供回电验证,因此看起来可能。但是现在我已经了解了它的细节,我真的认为不可能这样做。
我是朝着正确的方向前进的吗?还有更好的选择吗?有没有人之前做过这样的事情(基本上是点对点SSL而不是客户端服务器)?
答案 0 :(得分:28)
第1步:生成自签名证书:
我使用此代码生成.pfx证书文件:
byte[] c = Certificate.CreateSelfSignCertificatePfx(
"CN=yourhostname.com", //host name
DateTime.Parse("2000-01-01"), //not valid before
DateTime.Parse("2010-01-01"), //not valid after
"mypassword"); //password to encrypt key file
using (BinaryWriter binWriter = new BinaryWriter(
File.Open(@"testcert.pfx", FileMode.Create)))
{
binWriter.Write(c);
}
第2步:加载证书
X509Certificate cert = new X509Certificate2(
@"testcert.pfx",
"mypassword");
第3步:将它们放在一起
我将Server Program.cs文件中的这一行替换为步骤2中的行:
X509Certificate cert = getServerCert();
在Client Program.cs文件中,确保设置serverName = yourhostname.com(并且它与证书中的名称相匹配)
第4步:客户端身份验证
以下是我的客户端验证的方式(它与服务器略有不同):
TcpClient client = new TcpClient();
client.Connect(hostName, port);
SslStream sslStream = new SslStream(client.GetStream(), false,
new RemoteCertificateValidationCallback(CertificateValidationCallback),
new LocalCertificateSelectionCallback(CertificateSelectionCallback));
bool authenticationPassed = true;
try
{
string serverName = System.Environment.MachineName;
X509Certificate cert = GetServerCert(SERVER_CERT_FILENAME, SERVER_CERT_PASSWORD);
X509CertificateCollection certs = new X509CertificateCollection();
certs.Add(cert);
sslStream.AuthenticateAsClient(
serverName,
certs,
SslProtocols.Default,
false); // check cert revokation
}
catch (AuthenticationException)
{
authenticationPassed = false;
}
if (authenticationPassed)
{
//do stuff
}
CertificateValidationCallback与服务器案例中的相同,但请注意AuthenticateAsClient如何获取证书集合,而不仅仅是一个证书。所以,你必须添加一个LocalCertificateSelectionCallback,就像这样(在这种情况下,我只有一个客户端证书,所以我只返回集合中的第一个):
static X509Certificate CertificateSelectionCallback(object sender,
string targetHost,
X509CertificateCollection localCertificates,
X509Certificate remoteCertificate,
string[] acceptableIssuers)
{
return localCertificates[0];
}
答案 1 :(得分:2)
你也可以看一下这个例子 示例异步SslStream客户端/服务器实现 http://blogs.msdn.com/joncole/archive/2007/06/13/sample-asynchronous-sslstream-client-server-implementation.aspx
如果证书生成不正确,您可能会收到异常服务器模式SSL必须使用带有相关私钥的证书。
基本证书示例
makecert -sr LocalMachine -ss My -n CN = Test -sky exchange -sk 123456
或
作为外部文件
makecert -sr LocalMachine -ss My -n CN = Test -sky exchange -sk 123456 c:\ Test.cer
证书创建工具(Makecert.exe)
http://msdn.microsoft.com/en-us/library/bfsktky3%28VS.80%29.aspx
答案 2 :(得分:1)
你提出的建议对我来说听起来不错,只是听起来你要等到调用回调才能生成证书。我不认为那会飞; AFAIK,您必须在调用AuthenticateAsX
时提供有效的证书。
然而,这些类是可以覆盖的;所以理论上,您可以创建一个派生类,首先检查是否需要生成证书,如果需要生成证书,然后调用父AuthenticateAsX
方法。