
前段时间,我想知道是否可以在不依靠openssl实用程序的情况下建立证书工厂。如何从密钥生成到认证的整个过程“从按钮开始”。展望未来,我将说这方面的System.Security.Cryptography空间是完全自给自足的。在本文中,我将考虑以下步骤:创建证书,导出为pem和pkcs12格式,将证书存储在文件系统中以及仅使用System.Security.Cryptography中的类进行身份验证的步骤。
生物
在本文中,我将考虑一个没有证书颁发机构的简单的客户端-服务器交互方案。为了进行相互身份验证,我们需要根自签名证书caCert以及两个终端clientCert和serverCert。客户交换他们的证书,成功进行根身份验证。创建证书的步骤与任何openssl手册相同:
- 生成一个非对称密钥: 
 - var rsaKey = RSA.Create(2048);
 
 
- 我们描述认证的主题: 
 - string subject = "CN=myauthority.ru";
 
 - cn – “common name”, , , . , . MSDN "C = US/O = Microsoft/OU = WGA/CN = test". 
 
- : 
 - var certReq = new CertificateRequest(subject, rsaKey,HashAlgorithmName.SHA256,RSASignaturePadding.Pkcs1);
 
 - Pkcs1 openssl. 
 
- : 
 - certReq.CertificateExtensions.Add(new X509BasicConstraintsExtension(true, false, 0, true)); 
certReq.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(certReq.PublicKey, false));
 
 - , , SKI ( ). 
 
- 5 : 
 - var expirate = DateTimeOffset.Now.AddYears(5);
var caCert  = certReq.CreateSelfSigned(DateTimeOffset.Now, expirate);
 
 
.
- : 
 - var clientKey = RSA.Create(2048);
string subject = "CN=10.10.10.*";
var clientReq = new CertificateRequest(subject, clientKey,HashAlgorithmName.SHA256,RSASignaturePadding.Pkcs1);
 
 - ip , . 
 
- : 
 - 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));
 
 
- : 
 - byte[] serialNumber = BitConverter.GetBytes(DateTime.Now.ToBinary());
 
 - Serial Number – , , . , . 
 
- 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.