SSLStream示例 - 如何获取有效的证书?

时间:2012-04-02 19:49:57

标签: c# ssl certificate

我正在使用msdn here中的SSLStream示例。客户端代码“似乎”工作正常,因为我可以连接到谷歌,它至少得到过去的身份验证,但服务器没有。

从msdn页面的评论中,我使用this page上的过程生成我自己的私钥,但它不起作用。我得到System.NotSupportedException: The server mode SSL must use a certificate with the associated private key.的例外所以我很确定我做的事情是错的。

所以我的问题很简单:如何从msdn获取/生成适用于我自己的小示例程序的密钥?它可以是自签名的,但是我对SSL来说太新了,甚至不知道我到底需要什么。除了为本地服务器指定自己的证书之外,我想要做的就是运行as-given示例。如果我只是想在他们两个人之间进行通信,那么知道我必须在我的第二台机器上安装什么是很好的(因此它不是100%本地主机示例)。

我个人认为这是示例文档中的一个缺陷。它应该说“要运行它,你需要做A,B,C等”,但事实并非如此。

3 个答案:

答案 0 :(得分:44)

即使使用自签名证书,您也可以使用该示例。我已经从你正在使用的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文件夹中找到

cert2pscMicrosoft SDKs\Window\v7.0A\Bin。 可以下载pvkImport.exe安装程序here (Provided by @Jospeph and VirusTotal verified)。以前这可以从Microsoft站点下载,但他们已经将其删除。或者,@ Dweeberly向我们指出了Microsoft提供的新替代品pvk2pfx

对于下一步,请确保在pvkimprt对话框出现时选择导出私钥

pvkimprt -pfx TempCert.spc TempCert.pvk

enter image description here

当您选择包含私钥时,

pvkimprt会提示您输入密码。将生成的.pfx文件导入服务器计算机的个人存储中时,需要稍后提供此密码

enter image description here

接下来,将RootCATest.cer导入您的Computer商店的受信任的根证书颁发机构(在服务器和客户端上)。请注意,证书颁发给 FakeServerName 。这必须与SslTcpClient期望的服务器名称匹配:sslStream.AuthenticateAsClient(serverName),其中serverName是传递给SslTcpClient.exe的第二个参数的值。

当您的客户端连接时,服务器会提供一个证书,告诉客户端“我是FakeServerName”。如果客户端计算机信任颁发证书的CA,则客户端将接受此声明,这通过将RootCATest.cer导入客户端的受信任的根证书颁发机构来实现。

最后,您需要将服务器将要使用的私钥导入服务器计算机的个人存储中。 此步骤很重要,因为它解决了The server mode SSL must use a certificate with the associated private key.。这是通过导入先前生成的.pfx文件来实现的。确保将文件类型过滤器更改为“所有文件”,以便您可以看到生成的.pfx文件:

enter image description here

MSDN提供的示例代码使用端口443(标准的ssl端口)。自从我创建了控制台应用程序以来,我将示例类使用的端口更改为8080:

SslTcpServer:

TcpListener listener = new TcpListener(IPAddress.Any, 8080);

SslTcpClient:

TcpClient client = new TcpClient(machineName, 8080);

这是输出:

enter image description here

你会像这样启动你的服务器:

SslTcpServer.exe TempCert.cer 

来自客户端,你会这样连接:

SslTcpClient.exe <ip to your server> FakeServerName

答案 1 :(得分:9)

使用以下命令生成证书:

makecert -r -pe -n "CN=localhost" -m 12 -sky CertSubject -ss my serverCert.cer

然后从客户端连接到这样的服务器(假设我们使用你提到的MSDN示例):

SslTcpClient.RunClient ("localhost", "CertSubject");

您将在ValidateServerCertificate()调用中收到验证错误 - 但这是预期的 - 您使用的是自签名证书。只要在那里回归真实。

<强>更新

我不同意董建议将自签名证书添加到客户的受信任的根证书颁发机构的建议。如果您计划分发/支持您的软件,我认为以后可能会导致问题。例如,客户端可能会重新安装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;

答案 2 :(得分:5)

由于下载pvkimprt的Microsoft link已被破坏且我是OpenSSL的粉丝,我在OpenSSL中留下了两个解决方案。

VARIANT#1 - 自签名证书

首先,您需要下载OpenSSL和此配置file。 @Tung说你可以使用完美的自签名证书。将下载的配置文件复制到运行OpenSSL命令的同一文件夹中。

让我们生成私钥和证书颁发机构证书:

openssl req -x509 -config openssl.cnf -newkey rsa:4096 -sha256 -out ssl-cacert.pem -keyout ssl-cakey.pem -outform PEM

*使用 -nodes 参数来省略密码,但出于安全原因,我个人不建议使用。

如果您希望检查CA证书的信息,请执行以下命令:

openssl x509 -purpose -in ssl-cacert.pem -inform PEM

让我们创建证书申请,公共名称必须使用机器名称设置:

openssl req -config openssl.cnf -newkey rsa:2048 -keyout ssl-serverkey.pem -sha256 -out ssl-server.csr -outform PEM

* -nodes 参数的相同注释。

如果要检查证书请求信息,请执行以下命令:

openssl req -text -noout -verify -in ssl-server.csr

使用生成的CA证书对证书请求进行签名:

openssl x509 -req -days 365 -CA ssl-cacert.pem -CAkey ssl-cakey.pem -CAcreateserial -in ssl-server.csr -out ssl-server-certificate.pem

让我们使用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"

现在您应该导入.pfx证书。

  1. 双击 ssl-certificate.pfx 文件。
  2. 选择“本地计算机”选项,然后选择“下一步”。
  3. 输入密码并选中复选框“将此密钥标记为可导出。”
  4. 选择单选按钮“将所有证书放在以下商店中”
  5. 选择个人商店,然后点击下一步。
  6. 这一步必须有效。

    VARIANT#2 - 生成CA证书和服务器证书

    我个人更喜欢这个解决方案,因为只有我必须将根CA证书分发给客户。

    首先下载this配置文件。

    我们将使用相应的私钥生成根CA证书:

    openssl req -x509 -config openssl.cnf -newkey rsa:4096 -sha256 -keyout ssl-cakey.pem -out ssl-cacert.pem -outform PEM
    

    让我们检查证书属性:

    openssl x509 -purpose -in ssl-cacert.pem -inform PEM
    

    必须显示的信息应如下所示:

    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
    

    将Common Name设置为服务器的机器名称非常重要。

    验证此证书申请的信息:

    openssl req -text -noout -verify -in ssl-servercert.csr
    

    信息显示必须具有以下格式,检查主题部分中的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
    

    创建证书文件夹:

    mkdir certificates
    

    创建数据库索引文件:

    Windows: type NUL > index.txt
        Unix: touch index.txt

    创建serial.txt文件,其中存储了当前序列号:

    echo '01' > serial.txt
    

    使用该命令创建签署证书请求2年的服务器证书。如果您使用 -nodes 参数,系统将提示您输入CA证书的密码:

    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]: 
    

    选择y并会提示以下文字,再次选择y

    1 out of 1 certificate requests certified, commit? [y/n]
    

    将生成的证书导出为PFX格式:

    openssl pkcs12 -export -out ssl-certificate.pfx -inkey ssl-serverkey.pem -in ssl-servercert.pem -name "SSL Signed Certificate"
    

    您需要执行以下步骤才能正常启用SSL:

    在服务器上:

    • 在“受信任的根证书颁发机构”商店中导入根CA证书( ssl-cacert.pem 文件),选择“计算机帐户”。
    • 在个人存储选择计算机帐户时导入SSL的服务器证书( ssl-certificate.pfx文件)。

    在客户端计算机上:

    • 在每台客户端计算机中,您需要在“受信任的根证书颁发机构”商店中导入根CA证书( ssl-cacert.pem 文件),然后选择“计算机帐户”。

    随意进行任何更改或建议。