24

I'm unit testing a .NET application; some of the unit tests involve programmatically generating X509Certificate2 objects.

I don't care about actual signing/private key/validation stuff, I'd just like to have an object that doesn't throw exceptions when its fields are examined. I tried using the parameterless constructor, but then a whole bunch of fields throw exceptions when accessed. As seen in the debugger:

SubjectName = '(new System.Collections.Generic.Mscorlib_CollectionDebugView(result.Certificates)).Items[0].SubjectName' threw an exception of type 'System.Security.Cryptography.CryptographicException'

I also tried passing a byte array with some random numbers in it, but that didn't even construct (does the array need to be a specific size?)

So, question: what is the simplest (fewest lines of code) way to programmatically generate an X509Certificate2 object which will not throw exceptions upon field/property accesses?

4

4 回答 4

10

我建议如下:

  1. 使用makecert生成证书。
  2. 将证书添加到您的项目并将其构建操作更改为嵌入式资源。
  3. 从单元测试设置中的资源加载证书,见下文。

代码:

byte[] embeddedCert;
Assembly thisAssembly = Assembly.GetAssembly(typeof(MyType));
using (Stream certStream = thisAssembly.GetManifestResourceStream("YourProjectName.localhost.pfx"))
{
  embeddedCert = new byte[certStream.Length];
  certStream.Read(embeddedCert, 0, (int)certStream.Length);
}

_signingCert = new X509Certificate2(embeddedCert, "password");

此时,您应该可以与证书进行交互。如果您的单元测试有不同的需求,您可以创建不同的变体。

于 2011-07-26T21:00:23.007 回答
4

这可能看起来很老套,这取决于你想变得多么务实……我使用的一种方法是从机器上随机获取一个证书。

这在以下情况下很好: - 我知道每台运行这些测试的机器都有一个有效的证书。- 我正在使用 GIT 并且不想签入证书的二进制文件 - 我不关心证书内容 - 我使用的代码对模拟不友好并且明确需要不可模拟的 X509Certificate 对象。

绝对不是防弹的,但解开了我的障碍并解开了我的测试场景。

    static X509Certificate2 GetRandomCertificate()
    {
        X509Store st = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        st.Open(OpenFlags.ReadOnly);
        try
        {
            var certCollection = st.Certificates;

            if (certCollection.Count == 0)
            {
                return null;
            }
            return certCollection[0];
        }
        finally
        {
            st.Close();
        }
    }
于 2014-04-15T20:06:11.737 回答
1

应兰登的要求,我自己使用的解决方案:

        //Moling test Certificate
        var cert = new MX509Certificate2();
        var subject = new MX500DistinguishedName();
        // hookup
        cert.SubjectNameGet = () => subject;
        cert.ThumbprintGet = () => "foo";
        subject.NameGet = () => "foobar";

这很有效,因为我在证书中访问的唯一字段是 SubjectName 和 Thumbprint,而我访问的 SubjectName 的唯一字段是名称。我“模拟”了这些字段的 getter 方法以返回虚拟字符串。如果您要访问其他字段,您可能需要将它们调到。

那么,什么是“痣”?

“Moles 是基于委托的 .NET 中用于测试存根和绕行的轻量级框架。Moles 可用于绕行任何 .NET 方法,包括密封类型中的非虚拟/静态方法。Moles 可在 Visual Studio Gallery 上免费获得或与 Pex 捆绑在一起。”

http://research.microsoft.com/en-us/projects/moles/

于 2011-07-28T19:49:27.340 回答
0

还有一种更简单的方法。

  1. 使用 MakeCert 创建证书或导出任何现有证书。
  2. 在项目(App_Data 文件夹)中添加证书。
  3. 请按照以下步骤获取证书。

代码:

        string certificate = "cert.pfx";
        string certPath = string.Format("{0}/App_Data/{1}", HttpRuntime.AppDomainAppPath, certificate);
        byte[] bytes = Util.FileToArray(certPath);
        X509Certificate2 publicKey = new X509Certificate2(bytes, "somepassoword");
于 2016-12-14T16:45:27.923 回答