以编程方式创建带有私钥的虚拟证书以进行测试

时间:2016-12-29 20:41:16

标签: c# testing certificate

我有一个C#单元测试项目,我想测试一些我写过的加密扩展。我想使用虚拟证书进行测试,但我有以下限制:

  • 构建和测试运行是在我无法访问的计算机上远程完成的。因此,我无法在构建计算机上安装证书。
  • 我不能将秘密(例如.pfx文件)包含在git存储库或构建中,因为这样做会违反安全协议。因此,我无法从项目中包含的文件中读取证书。

由于我要进行加密和解密,我需要拥有私钥信息。如何在这些限制内以编程方式创建此证书?

1 个答案:

答案 0 :(得分:3)

执行此操作的一种方法是创建用于测试的证书,将其转换为基本64字符串,然后在代码中从此字符串中读取证书。这需要四个步骤:

<强> 1。创建.cer和.pvk文件

要执行此操作,可以使用MakeCert.exe工具(请注意this tool is deprecated,Microsoft建议您使用New-SelfSignedCertificate PowerShell cmdlet。我还没试过这个,但可能是任何一种方法都可行。)这是一个.NET Framework工具,作为Windows SDK的一部分包含在内。我碰巧在我的机器上安装了Windows 7 SDK,所以对我来说这个exe位于C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\下,但结果可能会有所不同。这个工具完全符合我们的要求!来自documentation

  

证书创建工具生成X.509证书仅用于测试目的。它为数字签名创建公钥和私钥对,并将其存储在证书文件中。此工具还会将密钥对与指定的发布者名称相关联,并创建一个X.509证书,该证书将用户指定的名称绑定到密钥对的公共部分。

为了这个例子,让我们调用证书TestCert。要创建.cer和.pvk文件,请运行以下命令:

MakeCert.exe -sv TestCert.pvk -n "cn=Test Certificate" TestCert.cer -r

-sv标志表示要创建的.pvk文件的名称,-n标志是我们证书的X.500兼容名称(它最容易使用< em>&#34; cn = CertName&#34; 格式如上所述),-r标志表示它将自签名。如果要指定证书的开始日期和结束日期,请使用-b-e标记,并将日期格式设置为mm/dd/yyyy(默认情况下,证书从当天开始有效创作直到2039年)。如果您的证书将用于加密和解密(如我的),则必须指定-sky Exchange-pe标志。在此过程中,系统会提示您为证书创建密码。

<强> 2。创建.pfx文件

这可以使用pvk2pfx.exe工具完成,该工具应与MakeCert.exe位于同一位置。此工具将.pvk和.cer文件转换为.pfx文件。要使用此工具,请运行以下命令:

pvk2pfx.exe -pvk TestCert.pvk -spc TestCert.cer -pfx TestCert.pfx

-pvk标志是要使用的.pvk文件的文件名(在步骤1中创建),-csp标志是要使用的.cer文件的文件名(在步骤中创建) 1),-pfx标志是将要创建的.pfx文件的名称。在此过程中,系统会提示您输入在步骤1中创建的密码。

第3。获取.pfx文件的基本64字符串表示

这非常简单,可以使用Get-Content Powershell cmdlet和System.Convert.ToBase64String方法完成。为此,打开Powershell窗口并运行以下命令:

$content = Get-Content TestCert.pfx -Encoding Byte
[System.Convert]::ToBase64String($content) | Out-File "TestCert.txt"

现在我们在TestCert.txt中为.pfx文件提供了基本64字符串。

<强> 4。以编程方式创建证书

现在我们可以在代码中创建证书,如下所示:

namespace MyTests
{
    using System;
    using System.Security.Cryptography.X509Certificates;

    public class MyTests
    {
        // Copy and paste the string from TestCert.txt here.
        private const string CertText = "<text>";

        // Use the password you created in steps 1 and 2 here.
        private const string Password = "p4ssw0rd";

        // Create the certificate object.
        private readonly X509Certificate2 TestCert = new X509Certificate2(
            Convert.FromBase64String(MyTests.CertText),
            MyTests.Password);
    }
}