Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何创建最小的虚拟X509Certificate2?_C#_X509certificate_X509certificate2 - Fatal编程技术网

C# 如何创建最小的虚拟X509Certificate2?

C# 如何创建最小的虚拟X509Certificate2?,c#,x509certificate,x509certificate2,C#,X509certificate,X509certificate2,我正在对一个.NET应用程序进行单元测试;一些单元测试涉及以编程方式生成X509Certificate2对象 我不关心实际的签名/私钥/验证内容,我只希望有一个对象在检查其字段时不会抛出异常。我尝试使用无参数构造函数,但是当访问时,一大堆字段会抛出异常。如调试器中所示: SubjectName='(新System.Collections.Generic.Mscorlib_CollectionDebugView(result.Certificates)).Items[0]。SubjectName'

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

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

SubjectName='(新System.Collections.Generic.Mscorlib_CollectionDebugView(result.Certificates)).Items[0]。SubjectName'引发了类型为'System.Security.Cryptographics.CryptographicException'的异常

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


因此,问题:以编程方式生成X509Certificate2对象的最简单(代码行数最少)方法是什么,它不会在字段/属性访问时引发异常?我建议如下:

  • 使用生成证书
  • 将证书添加到项目中,并将其生成操作更改为嵌入式资源
  • 从单元测试设置中的资源加载证书,请参见下面的内容
  • 代码:


    在这一点上,您应该能够与证书进行交互。如果您的单元测试有不同的需求,您可以创建不同的变体。

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

            //Moling test Certificate
            var cert = new MX509Certificate2();
            var subject = new MX500DistinguishedName();
            // hookup
            cert.SubjectNameGet = () => subject;
            cert.ThumbprintGet = () => "foo";
            subject.NameGet = () => "foobar";
    
    这是因为我在证书中访问的唯一字段是SubjectName和指纹,而我访问的SubjectName的唯一字段是name。我“mole”了这些字段的getter方法以返回伪字符串。如果要访问其他字段,可能需要将它们移动到

    那么,“痣”是什么呢

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


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

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

    还有一种更简单的方法

  • 使用MakeCert创建证书或导出任何现有证书
  • 在项目(App_数据文件夹)中添加证书
  • 按照以下步骤获取证书
  • 代码:

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

    我想我实际上可以只读取一次字节数组,将其作为字符打印到文件中,然后将其作为硬编码字节[]复制粘贴到源代码中?这还不算太糟糕…@JasonShantz我不明白为什么问这个问题的人会把你的答案标记为“已回答”,而不解释“MyType”是什么???@anhtv13我相信MyType是项目中C类/类型的占位符,该项目包含自签名证书作为嵌入式资源。这允许引用程序集,而程序集又允许将资源作为流读取到embeddedCert字节数组中。一旦有了这个字节数组,就可以为X509Certificate2使用适当的构造函数,在这方面MyType是与资源位于同一项目中的任意对象,如果将证书保留在同一项目中,它可以是UnitTest类本身。注意:“YourProjectName”应该是命名空间(如果项目名称和命名空间不同)。请使用thisAssembly.GetManifestResourceNames()检查一下。什么是Moles?你能提供你的最终解决方案作为答案吗?我现在也在尝试做同样的事情。我想他指的是一个用于创建测试存根的框架,以及Microsoft research的迂回路线。你可以看这里:。接受Jason的答案,而不是我的答案,因为他的答案更一般。这对于测试来说非常棒。我们是否必须小心密码,顺便说一句
            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");