X.509 with your forces in .Net Core

image


Some time ago I wondered if it is possible to set up a certificate factory without resorting to the openssl utility . How to bring the whole process “from the button” from key generation to authentication. Looking ahead, I will say that the System.Security.Cryptography space in this regard is completely self-sufficient. In this article, I will consider the steps of creating certificates, exporting to pem and pkcs12 formats , storing certificates in the file system, and authentication using only classes from System.Security.Cryptography .


Creature


In this article, I will consider a simple client-server interaction scheme, without a certification authority. For mutual authentication, we need the root self-signed certificate caCert and the two end clientsCert and serverCert . Clients exchange their certificates, authenticate by root, success. Creating certificates consists of the same steps as any openssl manual :


  1. Generate an asymmetric key:


    var rsaKey = RSA.Create(2048);

  2. We describe the subject of certification:


    string subject = "CN=myauthority.ru";

    cn – “common name”, , , . , . MSDN "C = US/O = Microsoft/OU = WGA/CN = test".


  3. :


    var certReq = new CertificateRequest(subject, rsaKey,HashAlgorithmName.SHA256,RSASignaturePadding.Pkcs1);

    Pkcs1 openssl.


  4. :


    certReq.CertificateExtensions.Add(new X509BasicConstraintsExtension(true, false, 0, true)); 
    certReq.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(certReq.PublicKey, false));

    , , SKI ( ).


  5. 5 :


    var expirate = DateTimeOffset.Now.AddYears(5);
    var caCert  = certReq.CreateSelfSigned(DateTimeOffset.Now, expirate);


.


  1. :


    var clientKey = RSA.Create(2048);
    string subject = "CN=10.10.10.*";
    var clientReq = new CertificateRequest(subject, clientKey,HashAlgorithmName.SHA256,RSASignaturePadding.Pkcs1);

    ip , .


  2. :


    clientReq.CertificateExtensions.Add(new X509BasicConstraintsExtension(false, false, 0, false));
    clientReq.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation, false));
    clientReq.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(clientReq.PublicKey, false));

  3. :


    byte[] serialNumber = BitConverter.GetBytes(DateTime.Now.ToBinary());

    Serial Number – , , . , .


  4. 5 :


    var clientCert = clientReq.Create(caCert, DateTimeOffset.Now, expirate, serialNumber):

    , . , caCert.Subject clientCert.Issuer, , .




, , . openssl pem, public.crt private.key. X509Certificate2, . , , base64 :


StringBuilder builder = new StringBuilder();
builder.AppendLine("-----BEGIN CERTIFICATE-----");
builder.AppendLine(Convert.ToBase64String(cert.RawData, Base64FormattingOptions.InsertLineBreaks));
builder.AppendLine("-----END CERTIFICATE-----");
File.WriteAllText("public.crt", builder.ToString());

:


RSA key = (RSA)cert.PrivateKey;
string name = key.SignatureAlgorithm.ToUpper();
StringBuilder builder = new StringBuilder();
builder.AppendLine($"-----BEGIN {name} PRIVATE KEY-----");
builder.AppendLine(Convert.ToBase64String(key.ExportRSAPrivateKey(), Base64FormattingOptions.InsertLineBreaks));
builder.AppendLine($"-----END {name} PRIVATE KEY-----");
File.WriteAllText("private.key", builder.ToString());

, ExportRSAPrivateKey netcore 3.0, .


pkcs12 pfx, . X509Certificate2 Export, X509ContentType.Pkcs12 X509ContentType.Pfx. , , cert.HasPrivateKey == false. , X509Certificate2 , , . . p12 pfx, :


var exportCert = new X509Certificate2(cert.Export(X509ContentType.Cert), (string)null, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet).CopyWithPrivateKey((RSA)cert.PrivateKey);
File.WriteAllBytes("client.pfx", exportCert.Export(X509ContentType.Pfx));
File.WriteAllBytes("client.p12", exportCert.Export(X509ContentType.Pkcs12));

Export .


.net core , X509Store. :


X509Store store = new X509Store("test");
store.Open(OpenFlags.ReadWrite);
store.Add(cert);

OC Linux "~/.dotnet/corefx/cryptography/x509stores/ test/" "827...E3E.pfx", ( Thumbprint). - openssl , . *.pfx , . X509Store , IssueName .



. , https. , . . « », , — , .
nginx :


server {
        listen 443;
        ssl on;
        ssl_certificate /etc/nginx/ssl/public.crt;
        ssl_certificate_key /etc/nginx/ssl/private.key;
        ssl_client_certificate /etc/nginx/ssl/caCert.crt;
        ssl_verify_client on;
}

HttpClient:


SocketsHttpHandler handler = new SocketsHttpHandler();
handler.SslOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
 {
    X509Chain chain = new X509Chain(false);
    chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
    chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
    chain.ChainPolicy.ExtraStore.Add(caCert);
    var serverert = new X509Certificate2(certificate);
    return chain.Build(serverert);
};
handler.SslOptions.ClientCertificates = new X509CertificateCollection() { clientCert };
HttpClient client = new HttpClient(handler);
var resp = await client.GetAsync…

"" "" .



.net core Linux OpenSSL. . , BouncyCastle, , , , 10 . , , X.509.


All Articles