简体   繁体   English

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

[英]How to create a minimal dummy X509Certificate2?

I'm unit testing a .NET application; 我是一个.NET应用程序的单元测试; some of the unit tests involve programmatically generating X509Certificate2 objects. 一些单元测试涉及以编程方式生成X509Certificate2对象。

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' SubjectName ='(new System.Collections.Generic.Mscorlib_CollectionDebugView(result.Certificates))。Items [0] .SubjectName'抛出了类型'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? 那么,问题: 以编程方式生成X509Certificate2对象的最简单(最少代码行)的方法是什么,该对象不会在字段/属性访问时抛出异常?

I would suggest the following: 我建议如下:

  1. Generate a certificate using makecert . 使用makecert生成证书。
  2. Add the certificate to your project and change its Build Action to Embedded Resource. 将证书添加到项目中,并将其Build Action更改为Embedded Resource。
  3. Load the certificate from the resource in your unit test setup, see below. 从单元测试设置中的资源加载证书,请参见下文。

Code: 码:

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

At this point you should be good to go as far as interacting with the certificate. 此时,您应该善于与证书进行交互。 You can create different variants if your unit tests have different needs. 如果您的单元测试有不同的需求,您可以创建不同的变体。

This may seem very hacky, and it depends on how pragmatic you want to be ... an approach I used was to just grab a random certificate from the machine. 这可能看起来非常h​​acky,这取决于你想要的实用程度......我使用的方法是从机器中获取随机证书。

This was good when: - I know that every machine that's running these tests has a valid certificate. 在以下情况下这很好: - 我知道运行这些测试的每台机器都有一个有效的证书。 - I was using GIT and didn't want to check in a binary file for the cert - I don't care about the cert content - I'm using code that's not mock friendly and explicitly requires a non-mockable X509Certificate object. - 我正在使用GIT,并且不想检查二进制文件中的证书 - 我不关心证书内容 - 我使用的代码不是模拟友好的,并且明确需要一个不可模拟的X509Certificate对象。

Definitely not bullet proof, but unblocked me and unblocked my testing scenario. 绝对不是防弹,但解锁我并解锁我的测试场景。

    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();
        }
    }

At Langdon's request, the solution I used, myself: 在兰登的要求下,我使用的解决方案,我自己:

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

This worked because the only fields I accessed in the Certificate were it's SubjectName and Thumbprint, and the only field of the SubjectName I accessed was the name. 这是有效的,因为我在证书中访问的唯一字段是它的SubjectName和Thumbprint,我访问的SubjectName的唯一字段是名称。 I "moled" the getter methods for these fields to return the dummy strings. 我“moled”这些字段的getter方法返回虚拟字符串。 If you were to access other fields, you'd probably need to mole them to. 如果你要访问其他领域,你可能需要将它们分解为。

And so, what is "Moles"? 那么,什么是“摩尔人”?

"Moles is a lightweight framework for test stubs and detours in .NET that is based on delegates. Moles may be used to detour any .NET method, including non-virtual/static methods in sealed types. Moles is freely available on Visual Studio Gallery or bundled with Pex." “Moles是.NET中基于委托的测试存根和绕行的轻量级框架.Moles可用于绕过任何.NET方法,包括密封类型中的非虚拟/静态方法。在Visual Studio库中可免费获得Moles或与Pex捆绑在一起。“

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

There is one more simple way of doing it. 有一种更简单的方法。

  1. Create a Certificate using MakeCert or export any existing certificate. 使用MakeCert创建证书或导出任何现有证书。
  2. Add the Certificate in Project (App_Data folder). 在项目中添加证书(App_Data文件夹)。
  3. Follow below steps to get the certificate. 按照以下步骤获取证书。

Code: 码:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM