如何创建一个最小的虚拟X509Certificate2?

时间:2011-07-26 20:34:08

标签: c# x509certificate x509certificate2

我正在测试.NET应用程序;一些单元测试涉及以编程方式生成X509Certificate2对象。

我不关心实际的签名/私钥/验证内容,我只想拥有一个在检查字段时不会抛出异常的对象。我尝试使用无参数构造函数,但是当访问时,一大堆字段会抛出异常。如调试器中所示:

SubjectName ='(new System.Collections.Generic.Mscorlib_CollectionDebugView(result.Certificates))。Items [0] .SubjectName'抛出类型为'System.Security.Cryptography.CryptographicException'的异常

我也试过传递一个包含一些随机数的字节数组,但是甚至没有构造(数组是否需要特定的大小?)

那么,问题:以编程方式生成X509Certificate2对象的最简单(最少代码行)的方法是什么?这个对象在字段/属性访问时不会抛出异常?

4 个答案:

答案 0 :(得分:9)

我建议如下:

  1. 使用makecert生成证书。
  2. 将证书添加到项目中,并将其Build Action更改为Embedded Resource。
  3. 从单元测试设置中的资源加载证书,请参阅下文。
  4. 代码:

    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");
    

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

答案 1 :(得分:3)

这可能看起来非常h​​acky,这取决于你想要的实用程度......我使用的方法是从机器中获取随机证书。

这在以下情况下很好: - 我知道运行这些测试的每台机器都有一个有效的证书。 - 我正在使用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();
        }
    }

答案 2 :(得分: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的唯一字段是名称。我“moled”这些字段的getter方法返回虚拟字符串。如果你要访问其他领域,你可能需要将它们分解为。

那么,什么是“摩尔人”?

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

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

答案 3 :(得分:0)

还有一种更简单的方法。

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

            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");