C# SSLStream示例-如何获得有效的证书?
我正在使用msdn中的SSLStream示例。客户端代码“似乎”工作正常,因为我可以连接到谷歌,它至少通过了身份验证,但服务器没有 从msdn页面的评论中,我使用上的过程生成了我自己的私钥,但它就是不起作用。我得到了一个异常C# SSLStream示例-如何获得有效的证书?,c#,ssl,certificate,C#,Ssl,Certificate,我正在使用msdn中的SSLStream示例。客户端代码“似乎”工作正常,因为我可以连接到谷歌,它至少通过了身份验证,但服务器没有 从msdn页面的评论中,我使用上的过程生成了我自己的私钥,但它就是不起作用。我得到了一个异常System.NotSupportedException:服务器模式SSL必须使用一个带有相关私钥的证书。因此我非常确定我所做的一切都是错误的 所以我的问题很简单:如何从msdn中获取/生成适用于我自己的小示例程序的密钥?它可以是自签名的,但我对SSL太陌生了,甚至不知道我到
System.NotSupportedException:服务器模式SSL必须使用一个带有相关私钥的证书。
因此我非常确定我所做的一切都是错误的
所以我的问题很简单:如何从msdn中获取/生成适用于我自己的小示例程序的密钥?它可以是自签名的,但我对SSL太陌生了,甚至不知道我到底需要什么。除了为本地服务器指定自己的证书之外,我只想按照给定的方式运行示例。如果我也想在第二台机器上进行通信,那么知道我必须在第二台机器上安装什么就好了(所以这不是100%本地主机的例子)
我个人认为这是示例文档中的一个缺陷。它应该说“要运行此操作,您需要执行A、B、C等操作”,但它没有这样做。使用以下命令生成您的证书:
makecert -r -pe -n "CN=localhost" -m 12 -sky CertSubject -ss my serverCert.cer
然后从客户端像这样连接到服务器(假设我们使用的是您提到的MSDN示例):
在ValidateServerCertificate()调用中会出现验证错误-但这是意料之中的-您使用的是自签名证书。只要在那里返回真的
更新:
我不同意Tung的建议,即将自签名证书添加到客户端的受信任根证书颁发机构中。我认为,如果您计划分发/支持您的软件,以后可能会出现问题。例如,客户可能会重新安装windows,或者将其个人资料移动到另一台PC,或者其他任何东西,而理解您的软件为何突然停止工作将是一件痛苦的事情(同样,我说的是长期的——一年或两年后,当您完全忘记这个小“把戏”)
相反,我建议将您的证书(通过比较主题和指纹)硬编码到客户的逻辑中,如下所示:
X509Certificate2 certificate = (X509Certificate2)cert;
if (certificate.Subject.StartsWith("CN=FAKE_SERVER_WHATEVER") &&
!string.IsNullOrEmpty(certificate.Thumbprint) &&
certificate.Thumbprint.ToLower() == "11c4446c572a9918ced3618728b91b3a07982787")
{
return true;
}
return false;
SslTcpServer.exe TempCert.cer
SslTcpClient.exe <ip to your server> FakeServerName
Certificate purposes:
SSL client : No
SSL client CA : Yes
SSL server : No
SSL server CA : Yes
Netscape SSL server : No
Netscape SSL server CA : Yes
S/MIME signing : No
S/MIME signing CA : Yes
S/MIME encryption : No
S/MIME encryption CA : Yes
CRL signing : Yes
CRL signing CA : Yes
Any Purpose : Yes
Any Purpose CA : Yes
OCSP helper : Yes
OCSP helper CA : Yes
Time Stamp signing : No
Time Stamp signing CA : Yes
-----BEGIN CERTIFICATE-----
MIIGLjCCBBagAwIBAgIJANCzs7UBFJMpMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV
...
im1yDnB5nPwkPwZ9eRmlzIc6OaLZcfbFfSeSw8/ipKZcEJ1u+EFrB0JhuSbeLXtQ
N/8=
-----END CERTIFICATE-----
即使使用自签名证书,也可以使示例正常工作。我已从makecert教程中提取了您正在使用的命令,并做了一些小的修改:
makecert -sv RootCATest.pvk -r -n "CN=FakeServerName" RootCATest.cer
makecert -ic RootCATest.cer -iv RootCATest.pvk -n "CN=FakeServerName" -sv TempCert.pvk -pe -sky exchange TempCert.cer
cert2spc TempCert.cer TempCert.spc
pvkimprt -pfx TempCert.spc TempCert.pvk
makecert
和cert2psc
可以在您的Microsoft SDKs\Window\v7.0A\Bin
文件夹中找到。
可以下载pvkImport.exe
安装程序。这本书以前可以从微软网站下载,但后来他们把它取了下来。或者,@Dweeberly为我们指出了微软提供的新替代品
对于下一步,请确保在出现pvkimprt对话框时选择导出私钥:
pvkimprt -pfx TempCert.spc TempCert.pvk
当您选择包含私钥时,pvkimprt
将提示您输入密码。稍后将生成的.pfx文件导入服务器计算机的个人存储时,需要提供此密码
接下来,将RootCATest.cer导入计算机
商店的受信任根证书颁发机构(在服务器和客户端上)。请注意,证书颁发给FakeServerName。这必须与SslTcpClient所需的服务器名称相匹配:sslStream.authenticatesClient(serverName)
,其中serverName
是传递给SslTcpClient.exe的第二个参数的值
当您的客户端连接时,服务器会提供一个证书,告诉客户端“我是FakeServerName”。如果客户端计算机信任颁发证书的CA,则客户端将接受此声明,这是通过将RootCATest.cer导入客户端的受信任根证书颁发机构来实现的
最后,您需要将服务器将要使用的私钥导入服务器机器的个人存储此步骤非常重要,因为它解决了服务器模式SSL必须使用带有相关私钥的证书的问题。。这是通过导入先前生成的.pfx
文件实现的。确保将文件类型筛选器更改为“所有文件”,以便可以查看生成的.pfx文件:
MSDN提供的示例代码使用端口443(标准ssl端口)。由于我创建了控制台应用程序,我将示例类使用的端口更改为8080:
SslTcpServer:
TcpListener listener = new TcpListener(IPAddress.Any, 8080);
SslTcpClient:
TcpClient client = new TcpClient(machineName, 8080);
以下是输出:
您将按如下方式启动服务器:
X509Certificate2 certificate = (X509Certificate2)cert;
if (certificate.Subject.StartsWith("CN=FAKE_SERVER_WHATEVER") &&
!string.IsNullOrEmpty(certificate.Thumbprint) &&
certificate.Thumbprint.ToLower() == "11c4446c572a9918ced3618728b91b3a07982787")
{
return true;
}
return false;
SslTcpServer.exe TempCert.cer
SslTcpClient.exe <ip to your server> FakeServerName
Certificate purposes:
SSL client : No
SSL client CA : Yes
SSL server : No
SSL server CA : Yes
Netscape SSL server : No
Netscape SSL server CA : Yes
S/MIME signing : No
S/MIME signing CA : Yes
S/MIME encryption : No
S/MIME encryption CA : Yes
CRL signing : Yes
CRL signing CA : Yes
Any Purpose : Yes
Any Purpose CA : Yes
OCSP helper : Yes
OCSP helper CA : Yes
Time Stamp signing : No
Time Stamp signing CA : Yes
-----BEGIN CERTIFICATE-----
MIIGLjCCBBagAwIBAgIJANCzs7UBFJMpMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV
...
im1yDnB5nPwkPwZ9eRmlzIc6OaLZcfbFfSeSw8/ipKZcEJ1u+EFrB0JhuSbeLXtQ
N/8=
-----END CERTIFICATE-----
从客户端,您可以按以下方式连接:
X509Certificate2 certificate = (X509Certificate2)cert;
if (certificate.Subject.StartsWith("CN=FAKE_SERVER_WHATEVER") &&
!string.IsNullOrEmpty(certificate.Thumbprint) &&
certificate.Thumbprint.ToLower() == "11c4446c572a9918ced3618728b91b3a07982787")
{
return true;
}
return false;
SslTcpServer.exe TempCert.cer
SslTcpClient.exe <ip to your server> FakeServerName
Certificate purposes:
SSL client : No
SSL client CA : Yes
SSL server : No
SSL server CA : Yes
Netscape SSL server : No
Netscape SSL server CA : Yes
S/MIME signing : No
S/MIME signing CA : Yes
S/MIME encryption : No
S/MIME encryption CA : Yes
CRL signing : Yes
CRL signing CA : Yes
Any Purpose : Yes
Any Purpose CA : Yes
OCSP helper : Yes
OCSP helper CA : Yes
Time Stamp signing : No
Time Stamp signing CA : Yes
-----BEGIN CERTIFICATE-----
MIIGLjCCBBagAwIBAgIJANCzs7UBFJMpMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV
...
im1yDnB5nPwkPwZ9eRmlzIc6OaLZcfbFfSeSw8/ipKZcEJ1u+EFrB0JhuSbeLXtQ
N/8=
-----END CERTIFICATE-----
SslTcpClient.exe FakeServerName
由于Microsoft下载的pvkimprt
已损坏,我是OpenSSL的粉丝,在此,我留下两个OpenSSL解决方案
变体#1-自签名证书
首先,您需要下载此配置@董说你可以使用完美的自签名证书。将下载的配置文件复制到运行OpenSSL命令的同一文件夹中
让我们生成证书颁发机构的私钥和证书:
*使用-nodes参数可以省略密码短语,但出于安全考虑,我个人不建议这样做
如果需要检查CA证书的信息,请执行以下命令:
让我们创建证书请求,公共名称必须与计算机名称一起设置:
*-节点的注释与参数相同
如果要检查证书请求信息,请执行以下命令:
使用生成的CA证书签署证书请求:
让我们使用PFX格式制作自签名证书:
现在您应该导入.pfx证书
Certificate purposes:
SSL client : No
SSL client CA : Yes
SSL server : No
SSL server CA : Yes
Netscape SSL server : No
Netscape SSL server CA : Yes
S/MIME signing : No
S/MIME signing CA : Yes
S/MIME encryption : No
S/MIME encryption CA : Yes
CRL signing : Yes
CRL signing CA : Yes
Any Purpose : Yes
Any Purpose CA : Yes
OCSP helper : Yes
OCSP helper CA : Yes
Time Stamp signing : No
Time Stamp signing CA : Yes
-----BEGIN CERTIFICATE-----
MIIGLjCCBBagAwIBAgIJANCzs7UBFJMpMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV
...
im1yDnB5nPwkPwZ9eRmlzIc6OaLZcfbFfSeSw8/ipKZcEJ1u+EFrB0JhuSbeLXtQ
N/8=
-----END CERTIFICATE-----
openssl req -config openssl.cnf -newkey rsa:2048 -sha256 -keyout ssl-serverkey.pem -out ssl-servercert.csr -outform PEM
openssl req -text -noout -verify -in ssl-servercert.csr
verify OK
Certificate Request:
Data:
Version: 0 (0x0)
Subject: C=US, ST=..., L=..., O=..., OU=..., CN=SERVERNAME
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:aa:92:bd:87:75:18:6c:c0:23:3f:0b:5a:46:1a:
...
fe:13
Exponent: 65537 (0x10001)
Attributes:
Requested Extensions:
X509v3 Subject Key Identifier:
7E:7D:79:F4:CD:71:0E:90:3A:9A:F8:3F:83:7D:89:90:4D:D4:F0:12
X509v3 Basic Constraints:
CA:FALSE
X509v3 Key Usage:
Digital Signature, Key Encipherment, Data Encipherment
Signature Algorithm: sha256WithRSAEncryption
34:e1:b4:db:b2:87:cc:11:3e:85:3c:ed:ac:8d:d9:43:ae:b0:
...
56:84:29:f9
mkdir certificates
echo '01' > serial.txt
openssl ca -config openssl.cnf -days 730 -policy signing_policy -extensions v3_req -out ssl-servercert.pem -infiles ssl-servercert.csr
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'US'
stateOrProvinceName :ASN.1 12:'...'
localityName :ASN.1 12:'...'
organizationName :ASN.1 12:'...'
organizationalUnitName:ASN.1 12:'...'
commonName :ASN.1 12:'SERVERNAME'
Certificate is to be certified until Jul 4 23:26:59 2018 GMT (730 days)
Sign the certificate? [y/n]:
1 out of 1 certificate requests certified, commit? [y/n]
openssl pkcs12 -export -out ssl-certificate.pfx -inkey ssl-serverkey.pem -in ssl-servercert.pem -name "SSL Signed Certificate"