C# SSLStream 示例 - 如何获得有效的证书?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9982865/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SSLStream example - how do I get certificates that work?
提问by Kevin Anderson
I'm using the SSLStream example from msdn here. The client code "seems" to work fine, as I can connect to google and it at least gets past authentication, but the server doesn't.
我正在使用 msdn here 中的 SSLStream 示例。客户端代码“似乎”工作正常,因为我可以连接到 google 并且它至少通过了身份验证,但服务器却没有。
From the comments from the msdn page, I used the procedure on this pageto generate my own private key, but it just doesn't work. I get an exception of System.NotSupportedException: The server mode SSL must use a certificate with the associated private key.So I'm pretty sure whatever I'm doing is wrong.
从 msdn 页面的评论中,我使用此页面上的过程生成了我自己的私钥,但它不起作用。我得到了一个例外System.NotSupportedException: The server mode SSL must use a certificate with the associated private key.所以我很确定我所做的一切都是错误的。
So my question is simple: how do I get/generate keys that will work for my own little example program from msdn? It can be self-signed, whatever, but I'm too new to SSL to even know what exactly I need. All I want to do is to run the example as-given, except for specifying my own certificates for my local server. And it'd be great to know what I'd have to install on my 2nd machine if I just want to communicate between the two of them too (so it's not a 100% localhost example).
所以我的问题很简单:如何从 msdn 获取/生成适用于我自己的小示例程序的密钥?它可以是自签名的,无论如何,但我对 SSL 太陌生,甚至不知道我到底需要什么。我想要做的就是按照给定的方式运行示例,除了为本地服务器指定我自己的证书。如果我也只想在两台机器之间进行通信,那么知道我必须在我的第二台机器上安装什么会很棒(所以这不是 100% 本地主机示例)。
Personally I see this as a flaw in the example document. It should say "to run this, you need to do A, B, C, etc," but it doesn't.
我个人认为这是示例文档中的一个缺陷。它应该说“要运行这个,你需要做 A、B、C 等”,但它没有。
采纳答案by Tung
You can get the example to work even with self-signed certificates. I've extracted the commands from the makecert tutorial that you're using with minor modifications:
即使使用自签名证书,您也可以使用该示例。我从 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
makecertand cert2psccan be found in your Microsoft SDKs\Window\v7.0A\Binfolder.
The pvkImport.exeinstaller can be downloaded here (Provided by @Jospeph and VirusTotal verified). This used to be downloadable from the Microsoft Site, but they have since taken it down. Alternatively, @Dweeberly pointed us to a new Microsoft-provided replacement, pvk2pfx.
makecert并且cert2psc可以在您的Microsoft SDKs\Window\v7.0A\Bin文件夹中找到。该pvkImport.exe安装程序可以下载这里(由@Jospeph和VirusTotal提供的验证)。这曾经可以从 Microsoft 站点下载,但他们已将其删除。或者,@Dweeberly 向我们指出了 Microsoft 提供的新替代品pvk2pfx。
For this next step make sure that you select to EXPORT the private key when the dialog from pvkimprt comes up:
对于下一步,请确保在 pvkimprt 的对话框出现时选择导出私钥:
pvkimprt -pfx TempCert.spc TempCert.pvk


pvkimprtwill prompt you for a password when you elect to include the private key. You will need to provide this password later when you import the generated .pfx file into the personal store of your server machine
pvkimprt当您选择包含私钥时,将提示您输入密码。稍后将生成的 .pfx 文件导入服务器计算机的个人存储时,您将需要提供此密码


Next, import RootCATest.cer into your Computerstore's Trusted Root Certification Authorities (on both the server and client). Notice that the certificate is issued to FakeServerName. This must match the server name that the SslTcpClient expects: sslStream.AuthenticateAsClient(serverName), where serverNameis the value of the second argument passed to SslTcpClient.exe.
接下来,将 RootCATest.cer 导入您Computer商店的受信任的根证书颁发机构(在服务器和客户端上)。请注意,证书颁发给FakeServerName。这必须与 SslTcpClient 期望的服务器名称匹配:sslStream.AuthenticateAsClient(serverName),其中serverName是传递给 SslTcpClient.exe 的第二个参数的值。
When your client connects, the server presents a certificate that tells the client "I'm FakeServerName". The client will accept this claim if the client machine trusts the CA that issued the certificate, which is achieved by importing RootCATest.cer into the client's Trusted Root Certification Authorities.
当您的客户端连接时,服务器会提供一个证书,告诉客户端“我是 FakeServerName”。如果客户端机器信任颁发证书的 CA,则客户端将接受此声明,这是通过将 RootCATest.cer 导入客户端的受信任根证书颁发机构来实现的。
Finally, you need to import the private key that the server is going to use into the server machine's Personal store. This step is importantbecause it addresses The server mode SSL must use a certificate with the associated private key.. This is achieved by importing the .pfxfile that you generated earlier. Make sure that you change the file type filter to "all files" so that you can see the .pfx file that you generated:
最后,您需要将服务器将要使用的私钥导入到服务器计算机的个人存储中。 这一步很重要,因为它解决了The server mode SSL must use a certificate with the associated private key.. 这是通过导入.pfx您之前生成的文件来实现的。确保将文件类型过滤器更改为“所有文件”,以便您可以看到您生成的 .pfx 文件:


The sample code provided by MSDN uses port 443 (which is the standard ssl port). Since I created console applications, I changed the port used by the sample classes to 8080:
MSDN 提供的示例代码使用端口 443(这是标准的 ssl 端口)。由于我创建了控制台应用程序,我将示例类使用的端口更改为 8080:
SslTcpServer:
SslTcp服务器:
TcpListener listener = new TcpListener(IPAddress.Any, 8080);
SslTcpClient:
SslTcp客户端:
TcpClient client = new TcpClient(machineName, 8080);
Here's the output:
这是输出:


you would launch your server like this:
你会像这样启动你的服务器:
SslTcpServer.exe TempCert.cer
from the client, you would connect like this:
从客户端,你会像这样连接:
SslTcpClient.exe <ip to your server> FakeServerName
回答by avs099
generate your certificate using this command:
使用以下命令生成您的证书:
makecert -r -pe -n "CN=localhost" -m 12 -sky CertSubject -ss my serverCert.cer
and then from client connect to the server like this (assuming we are using MSDN example you mentioned):
然后像这样从客户端连接到服务器(假设我们使用的是您提到的 MSDN 示例):
SslTcpClient.RunClient ("localhost", "CertSubject");
you will get validation errors in ValidateServerCertificate() call - but that's expected - you are using self-signed certificate. Just return true there.
您将在 ValidateServerCertificate() 调用中收到验证错误 - 但这是意料之中的 - 您正在使用自签名证书。只是在那里返回 true 。
UPDATE:
更新:
I disagree with Tung's suggestion of adding self-signed certificate into the client's Trusted Root Certification Authorities. I think it can cause issues later on if you plan to distribute/support your software. For example, client might reinstall windows, or move his profile to another PC, or whatever - and understanding WHY your software suddenly stopped working will be a pain (again, i'm talking long-term - a year or two from now, when you completely forget this little "trick").
我不同意 Tung 将自签名证书添加到客户的受信任根证书颁发机构的建议。我认为如果您计划分发/支持您的软件,它可能会在以后引起问题。例如,客户可能会重新安装 Windows,或者将他的个人资料移动到另一台 PC 上,或者其他任何事情——并且理解为什么你的软件突然停止工作将是一件痛苦的事情(同样,我说的是长期——一两年后,当你完全忘记了这个小“技巧”)。
Instead i would rather suggest to "hardcode" your certificate (by comparing subject and thumbprint) into client's logic, something like this:
相反,我宁愿建议将您的证书(通过比较主题和指纹)“硬编码”到客户端的逻辑中,如下所示:
X509Certificate2 certificate = (X509Certificate2)cert;
if (certificate.Subject.StartsWith("CN=FAKE_SERVER_WHATEVER") &&
!string.IsNullOrEmpty(certificate.Thumbprint) &&
certificate.Thumbprint.ToLower() == "11c4446c572a9918ced3618728b91b3a07982787")
{
return true;
}
return false;
回答by Joseph
As the Microsoft linkto download pvkimprtis broken and I am a fan of OpenSSL here I leave two solutions with OpenSSL.
由于 Microsoft 的 下载链接pvkimprt已断开,而且我是 OpenSSL 的粉丝,因此我在此处使用 OpenSSL 留下了两个解决方案。
VARIANT #1 - Self Signed Certificate
变体 #1 - 自签名证书
First you will need download OpenSSLand this configuration file. @Tung has said you can use perfectly self-signed certificate. Copy the downloaded configuration file in the same folder where you will run OpenSSL commands.
首先你需要下载OpenSSL和这个配置文件。@Tung 说过你可以使用完美的自签名证书。将下载的配置文件复制到您将运行 OpenSSL 命令的同一文件夹中。
Lets generate the private key and certificate of Certification Authority:
让我们生成证书颁发机构的私钥和证书:
openssl req -x509 -config openssl.cnf -newkey rsa:4096 -sha256 -out ssl-cacert.pem -keyout ssl-cakey.pem -outform PEM
*Use -nodesparameter to omit the passphrase, but for safety reasons personally I do not recommend it.
*使用-nodes参数来省略密码,但出于安全原因,我个人不推荐它。
If you desire inspect the information of CA certificate, execute the follow command:
如果您想查看 CA 证书信息,请执行以下命令:
openssl x509 -purpose -in ssl-cacert.pem -inform PEM
Lets create the certificate request, Common Namemust be set with the machine name:
让我们创建证书请求,Common Name必须设置为机器名称:
openssl req -config openssl.cnf -newkey rsa:2048 -keyout ssl-serverkey.pem -sha256 -out ssl-server.csr -outform PEM
*Same note for -nodesparameter.
* -nodes参数的注释相同。
If you want inspect the certificate request information execute the command:
如果要检查证书请求信息,请执行以下命令:
openssl req -text -noout -verify -in ssl-server.csr
Sign the certificate request with the generated CA certificate:
使用生成的 CA 证书签署证书请求:
openssl x509 -req -days 365 -CA ssl-cacert.pem -CAkey ssl-cakey.pem -CAcreateserial -in ssl-server.csr -out ssl-server-certificate.pem
Lets make the self-signed certificate with PFX format:
让我们用 PFX 格式制作自签名证书:
openssl pkcs12 -export -out ssl-certificate.pfx -inkey ssl-serverkey.pem -in ssl-server-certificate.pem -certfile ssl-cacert.pem -name "SSL Self Signed Certificate"
Now you should import the .pfx certificate.
现在您应该导入 .pfx 证书。
- Double click on ssl-certificate.pfxfile.
- Select "Local Machine" option and Next.
- Type the password and select the checkbox "Mark this key as exportable."
- Select the radio button "Place all certificates in the following store".
- Select Personalstore and click in Next.
- 双击ssl-certificate.pfx文件。
- 选择“本地机器”选项和下一步。
- 键入密码并选中复选框“将此密钥标记为可导出”。
- 选择单选按钮“将所有证书放入以下存储区”。
- 选择个人商店,然后单击下一步。
With this steps must work.
有了这个步骤必须工作。
VARIANT #2 - Generate CA Certificate and Server Certificate
VARIANT #2 - 生成 CA 证书和服务器证书
Personally I prefer this solution over the first because only I have to distribute the Root CA certificate to the clients.
我个人更喜欢这个解决方案而不是第一个,因为我只需要将根 CA 证书分发给客户端。
First download thisconfiguration file.
首先下载这个配置文件。
We will generate the Root CA certificate with the corresponding private key:
我们将使用相应的私钥生成根 CA 证书:
openssl req -x509 -config openssl.cnf -newkey rsa:4096 -sha256 -keyout ssl-cakey.pem -out ssl-cacert.pem -outform PEM
Lets check certificate properties:
让我们检查证书属性:
openssl x509 -purpose -in ssl-cacert.pem -inform PEM
The information must show should look like this:
必须显示的信息应如下所示:
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-----
Create the certificate request with the following command:
使用以下命令创建证书请求:
openssl req -config openssl.cnf -newkey rsa:2048 -sha256 -keyout ssl-serverkey.pem -out ssl-servercert.csr -outform PEM
It's very important set the Common Name with the machine name of server.
将 Common Name 设置为服务器的机器名称非常重要。
Verify the information of this certificate request:
验证此证书请求的信息:
openssl req -text -noout -verify -in ssl-servercert.csr
The information shows must have the following format, check that the CN field in the section Subject is the name of server machine.
显示的信息必须是以下格式,请检查Subject部分的CN字段是否为服务器机器名称。
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
Create the certificates folder:
创建证书文件夹:
mkdir certificates
Create the database index file:
创建数据库索引文件:
Windows:type NUL > index.txt
Unix:touch index.txt
视窗:type NUL > index.txt
Unix:touch index.txt
Create the serial.txt file where is stored the current serial number:
创建用于存储当前序列号的 serial.txt 文件:
echo '01' > serial.txt
Create the server certificate signing the certificate request for 2 years with the command. You will be prompted the pass phrase of CA certificate depending if you used -nodesparameter:
使用命令创建签署证书请求 2 年的服务器证书。根据您是否使用-nodes参数,系统将提示您输入 CA 证书的密码:
openssl ca -config openssl.cnf -days 730 -policy signing_policy -extensions v3_req -out ssl-servercert.pem -infiles ssl-servercert.csr
Then is displayed a text with the format:
然后显示具有以下格式的文本:
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]:
Select yand will prompted the follow text, select yone more time:
选择后y会提示如下文字,再选择y一次:
1 out of 1 certificate requests certified, commit? [y/n]
Export the generated certificate to PFX format:
将生成的证书导出为 PFX 格式:
openssl pkcs12 -export -out ssl-certificate.pfx -inkey ssl-serverkey.pem -in ssl-servercert.pem -name "SSL Signed Certificate"
You will need do the follow steps to enable SSL without problem:
您需要执行以下步骤才能毫无问题地启用 SSL:
On Server Machine:
在服务器机器上:
- Import the Root CA certificate (ssl-cacert.pemfile) on Trusted Root Certification Authorities store selecting Computer account.
- Import Server Certificate for SSL (ssl-certificate.pfx file) on Personal store selecting Computer account.
- 在受信任的根证书颁发机构存储选择计算机帐户上导入根 CA 证书(ssl-cacert.pem文件)。
- 在选择计算机帐户的个人存储上导入 SSL 的服务器证书(ssl-certificate.pfx 文件)。
On Client Machines:
在客户端机器上:
- In each client machine you will need import the Root CA certificate (ssl-cacert.pemfile) on Trusted Root Certification Authorities store selecting Computer account.
- 在每台客户端计算机中,您需要在受信任的根证书颁发机构存储选择计算机帐户上导入根 CA 证书(ssl-cacert.pem文件)。
Feel free to make any changes or suggestions.
随意做出任何更改或建议。

