How to create a minimal dummy X509Certificate2?

风流意气都作罢 提交于 2019-12-18 14:10:17

问题


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?


回答1:


I would suggest the following:

  1. Generate a certificate using makecert.
  2. Add the certificate to your project and change its Build Action to 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.




回答2:


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.

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.

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



回答3:


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. I "moled" the getter methods for these fields to return the dummy strings. 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."

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




回答4:


There is one more simple way of doing it.

  1. Create a Certificate using MakeCert or export any existing certificate.
  2. Add the Certificate in Project (App_Data folder).
  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");


来源:https://stackoverflow.com/questions/6836247/how-to-create-a-minimal-dummy-x509certificate2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!