2011-07-26 18 views
13

Estoy probando la unidad de una aplicación .NET; algunas de las pruebas unitarias implican generar mediante programación objetos X509Certificate2.Cómo crear un dummy mínimo X509Certificate2?

No me importa la firma real/clave privada/validación, me gustaría tener un objeto que no arroje excepciones cuando se examinan sus campos. Traté de usar el constructor sin parámetros, pero luego un montón de campos arrojan excepciones cuando se accede. Como se ve en el depurador:

SubjectName = '(nuevo System.Collections.Generic.Mscorlib_CollectionDebugView (result.Certificates)) Artículos [0] .SubjectName' produjo una excepción de tipo 'System.Security.Cryptography.CryptographicException'

también probé pasar una matriz de bytes con algunos números aleatorios en él, pero que ni siquiera se construyen

Por lo tanto, la pregunta (no la matriz tiene que ser de un tamaño específico?): lo que es el más sencillo (pocas líneas de código) forma de generar programáticamente un objeto X509Certificate2 que no arrojará excepciones sobre los accesos de campo/propiedad?

+0

Lo que es Moles? ¿Puedes proporcionar tu solución final como respuesta? Estoy tratando de hacer lo mismo ahora. – Langdon

+0

Supongo que se refiere a un marco para crear pruebas y desvíos de la investigación de Microsoft. Puede mirar aquí: http://research.microsoft.com/en-us/projects/moles/. – Sascha

Respuesta

8

Yo sugeriría lo siguiente:

  1. generar un certificado utilizando makecert.
  2. Agregue el certificado a su proyecto y cambie su Acción de compilación a Recurso incrustado.
  3. Cargue el certificado del recurso en la configuración de prueba de su unidad, consulte a continuación.

Código:

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

En este punto usted debe ser bueno para ir tan lejos como la interacción con el certificado. Puede crear diferentes variantes si las pruebas de su unidad tienen diferentes necesidades.

+1

Supongo que podría simplemente leer esa matriz de bytes * una vez *, imprimirla en un archivo como caracteres, y luego copiar y pegar eso en el código fuente como un byte codificado []? Eso no sería tan malo ... – Cephron

+0

Sí, eso funcionaría también. –

+0

Terminé usando Moles para hacerlo funcionar, pero gracias por una respuesta útil. – Cephron

1

A petición de Langdon, la solución que usé, yo:

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

Esto funcionó porque los únicos campos que los que se accede en el Certificado eran que es Sujeto y la huella digital, y el único campo de la SubjectName Accedí fue el nombre. Me "moled" los métodos getter para estos campos para devolver las cadenas ficticias. Si tuvieras que acceder a otros campos, probablemente tendrías que consultarlos.

Y entonces, ¿qué es "Moles"?

"Moles es un marco liviano para comprobantes de prueba y desvíos en .NET que se basa en delegados. Los moles se pueden utilizar para desviar cualquier método .NET, incluidos los métodos no virtuales/estáticos en tipos sellados. en la galería de Visual Studio o incluido con Pex ".

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

+1

Aceptado la respuesta de Jason sobre la mía porque la suya es más general. – Cephron

2

Esto puede parecer poco limpia, y depende de la forma pragmática quieres ser ... un enfoque que utilicé fue que la puede llevar un certificado de azar de la máquina.

Esto fue bueno cuando: - Sé que cada máquina que ejecuta estas pruebas tiene un certificado válido. - Estaba usando GIT y no quería registrar un archivo binario para el certificado - No me importa el contenido del certificado - Estoy usando un código que no es amigable y explícitamente requiere un X509Certificate no modificable objeto.

Definitivamente no a prueba de balas, pero me desbloqueó y desbloqueó mi escenario de prueba.

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

Esto es brillante para probar. ¿Tenemos que tener cuidado con las contraseñas, por cierto? – Timo

0

Hay una manera más simple de hacerlo.

  1. Crear un certificado utilizando MakeCert o exportar cualquier certificado existente.
  2. Agregue el certificado en el proyecto (carpeta App_Data).
  3. Siga los pasos a continuación para obtener el certificado.

Código:

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