c# - Genere y firme solicitud de certificado utilizando.NET Framework puro
cryptography system.security (1)
Estoy tratando de usar código .net puro para crear una solicitud de certificado y crear un certificado a partir de la solicitud de certificado contra un certificado de CA existente que tengo disponible (ya sea en el almacén de certificados de Windows o como un archivo separado).
Sé que tengo las clases
X509Certificate
y
X509Certificate2
disponibles para cargar certificados y obtener acceso a su información, pero no veo ninguna clase o funcionalidad dentro del espacio de nombres
System.Security.Cryptography
que pueda usarse para crear una solicitud de certificado o para firmar dicha solicitud de certificado para crear un nuevo certificado firmado.
Y eso, aunque la
documentación en el espacio de nombres
System.Security.Cryptography.Pkcs
dice:
El espacio de nombres System.Security.Cryptography.Pkcs proporciona elementos de programación para los Estándares de criptografía de clave pública (PKCS), incluidos los métodos para firmar datos, intercambiar claves, solicitar certificados , cifrado y descifrado de clave pública y otras funciones de seguridad.
Entonces, ¿cómo puedo crear una solicitud de certificado y firmar esa solicitud para crear un nuevo certificado X509 usando solo clases .net puras de
System.Security.Cryptography
?
Nota:
- No quiero usar un ejecutable externo como openssl o MakeCert
- No quiero usar BouncyCastle
- No quiero usar la API de inscripción de certificados de Windows
- No quiero usar las funciones nativas de la API Win32
Respuesta corta: puede comenzar en .NET Framework 4.7.2.
Esta funcionalidad se agregó originalmente a .NET Core 2.0 en la forma de la clase CertificateRequest , que puede generar una solicitud de firma de certificación PKCS # 10 o un certificado de clave pública X.509 (autofirmado o encadenado).
Las clases para esa característica se pusieron a disposición en .NET Framework 4.7.2.
using (RSA parent = RSA.Create(4096))
using (RSA rsa = RSA.Create(2048))
{
CertificateRequest parentReq = new CertificateRequest(
"CN=Experimental Issuing Authority",
parent,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
parentReq.CertificateExtensions.Add(
new X509BasicConstraintsExtension(true, false, 0, true));
parentReq.CertificateExtensions.Add(
new X509SubjectKeyIdentifierExtension(parentReq.PublicKey, false));
using (X509Certificate2 parentCert = parentReq.CreateSelfSigned(
DateTimeOffset.UtcNow.AddDays(-45),
DateTimeOffset.UtcNow.AddDays(365)))
{
CertificateRequest req = new CertificateRequest(
"CN=Valid-Looking Timestamp Authority",
rsa,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
req.CertificateExtensions.Add(
new X509BasicConstraintsExtension(false, false, 0, false));
req.CertificateExtensions.Add(
new X509KeyUsageExtension(
X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation,
false));
req.CertificateExtensions.Add(
new X509EnhancedKeyUsageExtension(
new OidCollection
{
new Oid("1.3.6.1.5.5.7.3.8")
},
true));
req.CertificateExtensions.Add(
new X509SubjectKeyIdentifierExtension(req.PublicKey, false));
using (X509Certificate2 cert = req.Create(
parentCert,
DateTimeOffset.UtcNow.AddDays(-1),
DateTimeOffset.UtcNow.AddDays(90),
new byte[] { 1, 2, 3, 4 }))
{
// Do something with these certs, like export them to PFX,
// or add them to an X509Store, or whatever.
}
}
}
Respuesta más larga si está atascado en versiones anteriores: para lograr su objetivo sin agregar nuevas P / Invocaciones, deberá leer y comprender los siguientes documentos:
- UIT-T X.680-201508, el lenguaje ASN.1
- IETF RFC 5280 o ITU-T X.509 , los documentos que explican los campos en los certificados X.509.
- IETF RFC 2986 , explica la solicitud de firma de certificación PKCS # 10
- ITU-T X.690 , explica la familia de codificación BER para ASN.1 (incluido DER) que le indica cómo leer y escribir bytes para lograr el significado semántico de X.509 / PKCS # 10.
Y luego podría escribir un escritor / lector DER, y simplemente emitir los bytes para lo que desea.