c# - name - ¿Cómo crear un X509Certificate2 simulado mínimo?
summary documentation c# (4)
Estoy probando la unidad de una aplicación .NET; Algunas de las pruebas unitarias implican la generación mediante programación de objetos X509Certificate2.
No me importa la firma real / clave privada / cosas de validación, me gustaría tener un objeto que no arroje excepciones cuando se examinan sus campos. Intenté 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 (resultado.Certificates)). Elementos [0] .SubjectName'' lanzó una excepción de tipo ''System.Security.Cryptography.CryptographicException''
También intenté pasar una matriz de bytes con algunos números aleatorios, pero eso ni siquiera se construyó (¿la matriz debe tener un tamaño específico?)
Entonces, pregunte: ¿cuál es la forma más simple (menos líneas de código) de generar mediante programación un objeto X509Certificate2 que no generará excepciones en los accesos de campo / propiedad?
A petición de Langdon, la solución que utilicé, yo mismo:
//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 a los que accedí en el Certificado eran SubjectName y Thumbprint, y el único campo de SubjectName al que accedí fue el nombre. "Moled" los métodos getter para estos campos para devolver las cadenas ficticias. Si tuvieras que acceder a otros campos, probablemente necesitarías mole.
Y entonces, ¿qué es "Moles"?
"Moles es un marco liviano para stubs de prueba y desvíos en .NET que se basa en delegados. Los topos se pueden usar para desviar cualquier método .NET, incluidos los métodos no virtuales / estáticos en tipos sellados. Los topos están disponibles gratuitamente en Visual Studio Gallery o empaquetado con Pex ".
Esto puede parecer muy intrincado y depende de qué tan pragmático quiera ser ... un enfoque que utilicé fue simplemente tomar un certificado aleatorio 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 simpático y requiere explícitamente un objeto X509Certificate no simulable.
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();
}
}
Hay una forma más simple de hacerlo.
- Cree un certificado utilizando MakeCert o exporte cualquier certificado existente.
- Agregue el Certificado en Proyecto (carpeta App_Data).
- 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");
Sugeriría lo siguiente:
- Generar un certificado utilizando makecert .
- Agregue el certificado a su proyecto y cambie su Acción de compilación a Recurso incrustado.
- Cargue el certificado del recurso en la configuración de prueba de su unidad, vea 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, debería ser bueno ir tan lejos como para interactuar con el certificado. Puedes crear diferentes variantes si tus pruebas unitarias tienen necesidades diferentes.