Last active
April 15, 2023 02:47
-
-
Save micah686/4c4f66fbc217c2f5788a1cbaaa317a2d to your computer and use it in GitHub Desktop.
TestCert-- Generate Certificate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Security; | |
using System.Security.Cryptography; | |
using System.Security.Cryptography.X509Certificates; | |
using System.Threading.Tasks; | |
namespace TestCert | |
{ | |
internal class Complete | |
{ | |
#region CA Cert | |
public static void SaveCACertAndKeys() | |
{ | |
var cert = GenerateCertificate("TEST-CA"); | |
string certPem = new string(PemEncoding.Write("CERTIFICATE", cert.RawData)); | |
string keyPem; | |
if (cert.GetRSAPrivateKey() is RSA rsaKey) | |
{ | |
keyPem = new string(PemEncoding.Write("PRIVATE KEY", rsaKey.ExportPkcs8PrivateKey())); | |
} | |
else if (cert.GetECDsaPrivateKey() is ECDsa ecdsaKey) | |
{ | |
keyPem = new string(PemEncoding.Write("PRIVATE KEY", ecdsaKey.ExportPkcs8PrivateKey())); | |
} | |
else if (cert.GetDSAPrivateKey() is DSA dsaKey) | |
{ | |
keyPem = new string(PemEncoding.Write("PRIVATE KEY", dsaKey.ExportPkcs8PrivateKey())); | |
} | |
else | |
{ | |
throw new CryptographicException("Unknown certificate algorithm"); | |
} | |
Console.WriteLine(certPem); | |
Console.WriteLine(keyPem); | |
File.WriteAllText("pub.crt", certPem); | |
File.WriteAllText("priv.key", keyPem); | |
} | |
public static X509Certificate2 GenerateCertificate(string name) | |
{ | |
string subjectName = $"CN={name}"; | |
using (RSA rsa = RSA.Create(4096)) | |
{ | |
CertificateRequest req = new CertificateRequest( | |
subjectName, | |
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)); | |
var selfSigned = req.CreateSelfSigned( | |
DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow.AddYears(50)); | |
return req.CreateSelfSigned( | |
DateTimeOffset.UtcNow.AddDays(-1), | |
DateTimeOffset.UtcNow.AddYears(50)); | |
} | |
} | |
#endregion | |
private void GenNewPrivKey() | |
{ | |
var rsa = RSA.Create(2048); | |
var secKey = rsa.ExportRSAPrivateKey(); | |
var keyPem = new string(PemEncoding.Write("PRIVATE KEY", secKey)); | |
File.WriteAllText("server.key", keyPem); | |
} | |
#region Pem Helper | |
public static void GetPemData(X509Certificate2 cert, string fileName) | |
{ | |
byte[] certificateBytes = cert.RawData; | |
char[] certificatePem = PemEncoding.Write("CERTIFICATE", certificateBytes); | |
AsymmetricAlgorithm? key; | |
var rsaKey = cert.GetRSAPrivateKey(); | |
key = rsaKey != null ? rsaKey : cert.GetECDsaPrivateKey(); | |
//AsymmetricAlgorithm key = cert.GetRSAPrivateKey() ?? cert.GetECDsaPrivateKey(); | |
byte[] pubKeyBytes = key.ExportSubjectPublicKeyInfo(); | |
byte[] privKeyBytes = key.ExportPkcs8PrivateKey(); | |
char[] pubKeyPem = PemEncoding.Write("PUBLIC KEY", pubKeyBytes); | |
char[] privKeyPem = PemEncoding.Write("PRIVATE KEY", privKeyBytes); | |
File.WriteAllText($"{fileName}.crt", new string(pubKeyPem)); | |
File.WriteAllText($"{fileName}.key", new string(privKeyPem)); | |
} | |
public static X509Certificate2 SaveCertAsPem(X509Certificate2 cert, string fileName) | |
{ | |
string certPem = new string(PemEncoding.Write("CERTIFICATE", cert.RawData)); | |
string keyPem; | |
if (cert.GetRSAPrivateKey() is RSA rsaKey) | |
{ | |
keyPem = new string(PemEncoding.Write("PRIVATE KEY", rsaKey.ExportPkcs8PrivateKey())); | |
} | |
else if (cert.GetECDsaPrivateKey() is ECDsa ecdsaKey) | |
{ | |
keyPem = new string(PemEncoding.Write("PRIVATE KEY", ecdsaKey.ExportPkcs8PrivateKey())); | |
} | |
else if (cert.GetDSAPrivateKey() is DSA dsaKey) | |
{ | |
keyPem = new string(PemEncoding.Write("PRIVATE KEY", dsaKey.ExportPkcs8PrivateKey())); | |
} | |
else | |
{ | |
throw new CryptographicException("Unknown certificate algorithm"); | |
} | |
File.WriteAllText($"{fileName}.crt", certPem); | |
File.WriteAllText($"{fileName}.key", keyPem); | |
var certAgain = X509Certificate2.CreateFromPem(certPem, keyPem); | |
return certAgain; | |
} | |
#endregion | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Net; | |
using System.Net.Http; | |
using System.Net.Security; | |
using System.Net.Sockets; | |
using System.Security; | |
using System.Security.Cryptography; | |
using System.Security.Cryptography.X509Certificates; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace TestCert | |
{ | |
internal class Complete2 | |
{ | |
//https://www.codeproject.com/Articles/5315010/How-to-Use-Certificates-in-ASP-NET-Core | |
static void Main2(string[] args) | |
{ | |
Console.WriteLine("Hello, World!"); | |
const string CERT_NAME = "TestCert"; | |
const string CERT_PASS = "123456"; | |
TestGen1(); | |
var ca = GenerateCertificate("CA"); | |
SaveCertAsPem(ca, "CA"); | |
var ss = GenerateCertificateWithRSAKey("SERVER", ca); | |
//var ss = CreateSignedCert("CA.crt", "123456", "SERVER", "querty", "SERVER"); | |
SaveCertAsPem(ss, "SERVER"); | |
//File.WriteAllBytes($"{CERT_NAME}.crt", cert.Export(X509ContentType.Cert, CERT_PASS)); | |
//File.WriteAllBytes("test.crt", cert.Export(X509ContentType.Pfx, "123456")); | |
Console.WriteLine("Cert generated"); | |
//var contents = File.ReadAllText($"{CERT_NAME}.crt"); | |
//Console.WriteLine(contents); | |
Console.ReadKey(); | |
} | |
private static bool ValidateCert(X509Certificate2 rootCA, X509Certificate2 serverCert) | |
{ | |
X509Chain x509Chain = new X509Chain(); | |
x509Chain.ChainPolicy.ExtraStore.Add(rootCA); | |
x509Chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; | |
x509Chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; | |
x509Chain.Build(serverCert); | |
foreach (X509ChainElement x509ChainElement in x509Chain.ChainElements) | |
{ | |
//var dh = x509ChainElement.Certificate.PublicKey.GetECDiffieHellmanPublicKey(); | |
var foo = x509ChainElement.Certificate.GetPublicKeyString(); | |
var bar = rootCA.GetPublicKeyString(); | |
Console.WriteLine("Name: " + x509ChainElement.Certificate.GetNameInfo(X509NameType.SimpleName, false)); | |
foreach (X509ChainStatus x509ChainStatus in x509ChainElement.ChainElementStatus) | |
Console.WriteLine("status: " + x509ChainStatus.StatusInformation); | |
if (x509ChainElement.ChainElementStatus.Length != 0 && (x509ChainElement.Certificate.Thumbprint != rootCA.Thumbprint))// || x509ChainElement.ChainElementStatus[0].Status != X509ChainStatusFlags.UntrustedRoot)) | |
return false; | |
} | |
return true; | |
} | |
private static bool ValidateTestServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) | |
{ | |
// If the certificate is a valid, signed certificate, return true. | |
if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None) | |
{ | |
return true; | |
} | |
// If there are errors in the certificate chain, look at each error to determine the cause. | |
if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) != 0) | |
{ | |
if (chain != null && chain.ChainStatus != null) | |
{ | |
foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus status in chain.ChainStatus) | |
{ | |
if ((certificate.Subject == certificate.Issuer) && | |
(status.Status == System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.UntrustedRoot)) | |
{ | |
// Self-signed certificates with an untrusted root are valid. | |
continue; | |
} | |
else | |
{ | |
if (status.Status != System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.NoError) | |
{ | |
// If there are any other errors in the certificate chain, the certificate is invalid, | |
// so the method returns false. | |
return false; | |
} | |
} | |
} | |
} | |
// When processing reaches this line, the only errors in the certificate chain are | |
// untrusted root errors for self-signed certificates. These certificates are valid | |
// for default Exchange server installations, so return true. | |
return true; | |
} | |
else | |
{ | |
// In all other cases, return false. | |
return false; | |
} | |
} | |
public static void TrySignCert(string caCert, string caKey, string newCertName) | |
{ | |
string subjectName = $"CN={newCertName}"; | |
var caPub = File.ReadAllText("CA_PEM.crt"); | |
var caPriv = File.ReadAllText("CA_PEM.key"); | |
var rootCA = X509Certificate2.CreateFromPem(caPub, caPriv); | |
var rsa = rootCA.GetRSAPrivateKey(); | |
var request = new CertificateRequest(newCertName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); | |
request.CertificateExtensions.Add( | |
new X509KeyUsageExtension(X509KeyUsageFlags.KeyAgreement | X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, true)); | |
request.CertificateExtensions.Add( | |
new X509EnhancedKeyUsageExtension( | |
new OidCollection { new Oid("1.3.6.1.5.5.7.3.1"), new Oid("1.3.6.1.5.5.7.3.2") }, true)); | |
SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder(); | |
sanBuilder.AddDnsName("localhost"); | |
request.CertificateExtensions.Add(sanBuilder.Build()); | |
var csr = request.CreateSelfSigned(DateTimeOffset.MinValue, DateTimeOffset.MaxValue); | |
var cert = csr.CopyWithPrivateKey(rsa); | |
byte[] certificateBytes = cert.RawData; | |
char[] certificatePem = PemEncoding.Write("CERTIFICATE", certificateBytes); | |
AsymmetricAlgorithm? key; | |
var rsaKey = cert.GetRSAPrivateKey(); | |
key = rsaKey != null ? rsaKey : cert.GetECDsaPrivateKey(); | |
//AsymmetricAlgorithm key = cert.GetRSAPrivateKey() ?? cert.GetECDsaPrivateKey(); | |
byte[] pubKeyBytes = key.ExportSubjectPublicKeyInfo(); | |
byte[] privKeyBytes = key.ExportPkcs8PrivateKey(); | |
char[] pubKeyPem = PemEncoding.Write("PUBLIC KEY", pubKeyBytes); | |
char[] privKeyPem = PemEncoding.Write("PRIVATE KEY", privKeyBytes); | |
var srvPub = new string(pubKeyPem); | |
var srvPriv = new string(privKeyPem); | |
File.WriteAllText("SERVER.crt", srvPub); | |
File.WriteAllText("SERVER.key", srvPriv); | |
} | |
public static X509Certificate2 GenerateCertificateWithRSAKey(string name, X509Certificate2 rootCACert) | |
{ | |
AsymmetricAlgorithm? key; | |
var rsaKey = rootCACert.GetRSAPrivateKey(); | |
string subjectName = $"CN={name}"; | |
CertificateRequest req = new CertificateRequest( | |
subjectName, | |
rsaKey, | |
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)); | |
var selfSigned = req.CreateSelfSigned( | |
DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow.AddYears(50)); | |
return req.CreateSelfSigned( | |
DateTimeOffset.UtcNow.AddDays(-1), | |
DateTimeOffset.UtcNow.AddYears(50)); | |
} | |
public static IPAddress GetLocalIPAddress() | |
{ | |
var host = Dns.GetHostEntry(Dns.GetHostName()); | |
foreach (var ip in host.AddressList) | |
{ | |
if (ip.AddressFamily == AddressFamily.InterNetwork) | |
{ | |
return ip; | |
} | |
} | |
return IPAddress.Loopback; | |
} | |
public static void TestGen1() | |
{ | |
string Organization = "MirrorTube"; | |
string CommonName = "MirrorTube.RootCA"; | |
var CountryCode = "US"; | |
var OrganizationalUnits = new[] { "Copyright (c), " + DateTime.UtcNow.ToString("yyyy") + " MirrorTube.RootCA" }; | |
SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder(); | |
sanBuilder.AddIpAddress(GetLocalIPAddress()); | |
sanBuilder.AddDnsName(Environment.MachineName); | |
sanBuilder.AddUserPrincipalName(Environment.OSVersion.ToString()); | |
var dn = new StringBuilder(); | |
dn.Append("CN=\"" + CommonName.Replace("\"", "\"\"") + "\""); | |
foreach (var ou in OrganizationalUnits) | |
{ | |
dn.Append(",OU=\"" + ou.Replace("\"", "\"\"") + "\""); | |
} | |
dn.Append(",O=\"" + Organization.Replace("\"", "\"\"") + "\""); | |
dn.Append(",C=" + CountryCode.ToUpper()); | |
var strDn = dn.ToString(); | |
X500DistinguishedName distinguishedName = new X500DistinguishedName(strDn); | |
var rsaKey = RSA.Create(4096); | |
string subjectName = $"CN=CA"; | |
CertificateRequest req = new CertificateRequest( | |
distinguishedName, | |
rsaKey, | |
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)); | |
req.CertificateExtensions.Add(sanBuilder.Build()); | |
var selfSigned = req.CreateSelfSigned( | |
DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow.AddYears(50)); | |
SaveCertAsPem(selfSigned, "TEXTCRT"); | |
} | |
public static X509Certificate2 CreateSelfSignedCert(string CommonName, string Password, string Destination, string FriendlyName = null, string[] DnsNames = null, DateTime? ExpirationBefore = null, DateTime? ExpirationAfter = null, bool IsCertificateAuthority = false, string CountryCode = "US", string Organization = "JCCE", string[] OrganizationalUnits = null) | |
{ | |
SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder(); | |
if (DnsNames == null) | |
{ | |
sanBuilder.AddIpAddress(IPAddress.Loopback); | |
sanBuilder.AddIpAddress(IPAddress.IPv6Loopback); | |
sanBuilder.AddDnsName("localhost"); | |
sanBuilder.AddDnsName(Environment.MachineName); | |
} | |
else | |
{ | |
foreach (var dnsName in DnsNames) | |
{ | |
sanBuilder.AddDnsName(dnsName); | |
} | |
} | |
if (CountryCode.Length != 2) CountryCode = "US"; | |
if (OrganizationalUnits == null) OrganizationalUnits = new[] { "Copyright (c), " + DateTime.UtcNow.ToString("yyyy") + " JCCE" }; | |
var dn = new StringBuilder(); | |
dn.Append("CN=\"" + CommonName.Replace("\"", "\"\"") + "\""); | |
foreach (var ou in OrganizationalUnits) | |
{ | |
dn.Append(",OU=\"" + ou.Replace("\"", "\"\"") + "\""); | |
} | |
dn.Append(",O=\"" + Organization.Replace("\"", "\"\"") + "\""); | |
dn.Append(",C=" + CountryCode.ToUpper()); | |
dn.Append(",C=" + "JP"); | |
var strDn = dn.ToString(); | |
X500DistinguishedName distinguishedName = new X500DistinguishedName(strDn); | |
X509Certificate2 cert; | |
using (RSA rsa = RSA.Create(2048)) | |
{ | |
var request = new CertificateRequest(distinguishedName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); | |
var usages = X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature; | |
if (IsCertificateAuthority) usages = usages | X509KeyUsageFlags.KeyCertSign; | |
request.CertificateExtensions.Add(new X509KeyUsageExtension(usages, false)); | |
request.CertificateExtensions.Add( | |
new X509EnhancedKeyUsageExtension( | |
new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, false)); | |
request.CertificateExtensions.Add(sanBuilder.Build()); | |
if (IsCertificateAuthority) request.CertificateExtensions.Add(new X509BasicConstraintsExtension(true, true, 1, true)); | |
if (ExpirationAfter == null) { ExpirationAfter = DateTime.UtcNow.AddDays(-1).AddYears(10); } | |
if (ExpirationBefore == null) ExpirationBefore = DateTime.UtcNow; | |
var certificate = request.CreateSelfSigned(new DateTimeOffset(ExpirationBefore.Value), new DateTimeOffset(ExpirationAfter.Value)); | |
if (FriendlyName == null) FriendlyName = CommonName; | |
cert = new X509Certificate2(certificate.Export(X509ContentType.Pfx, Password), Password, X509KeyStorageFlags.MachineKeySet); | |
File.WriteAllBytes(Destination, certificate.Export(X509ContentType.Pkcs12, Password)); | |
} | |
return cert; | |
} | |
public static X509Certificate2 CreateSignedCert(string IssuerCertLocation, string IssuerPassword, string CommonName, string Password, string Destination, string FriendlyName = null, string[] DnsNames = null, DateTime? ExpirationBefore = null, DateTime? ExpirationAfter = null, string CountryCode = "US", string Organization = "JCCE", string[] OrganizationalUnits = null) | |
{ | |
SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder(); | |
if (DnsNames == null) | |
{ | |
sanBuilder.AddIpAddress(IPAddress.Loopback); | |
sanBuilder.AddIpAddress(IPAddress.IPv6Loopback); | |
sanBuilder.AddDnsName("localhost"); | |
sanBuilder.AddDnsName(Environment.MachineName); | |
} | |
else | |
{ | |
foreach (var dnsName in DnsNames) | |
{ | |
sanBuilder.AddDnsName(dnsName); | |
} | |
} | |
if (CountryCode.Length != 2) CountryCode = "US"; | |
if (OrganizationalUnits == null) OrganizationalUnits = new[] { "Copyright (c), " + DateTime.UtcNow.ToString("yyyy") + " \"JCCE\"", "JcceEventBusServer" }; | |
var dn = new StringBuilder(); | |
dn.Append("CN=\"" + CommonName.Replace("\"", "\"\"") + "\""); | |
foreach (var ou in OrganizationalUnits) | |
{ | |
dn.Append(";OU=\"" + ou.Replace("\"", "\"\"") + "\""); | |
} | |
dn.Append(";O=\"" + Organization.Replace("\"", "\"\"") + "\""); | |
dn.Append(";C=" + CountryCode.ToUpper()); | |
dn.Append(";C=" + "JP"); | |
var strDn = dn.ToString(); | |
X500DistinguishedName distinguishedName = new X500DistinguishedName(strDn); | |
var issuerCert = new X509Certificate2(fileName: IssuerCertLocation, password: IssuerPassword, keyStorageFlags: X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); | |
var uniqueId = Guid.NewGuid(); | |
using (var rsa = RSA.Create(2048)) | |
{ | |
var request = new CertificateRequest(distinguishedName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); | |
request.CertificateExtensions.Add( | |
new X509KeyUsageExtension(X509KeyUsageFlags.KeyAgreement | X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, true)); | |
request.CertificateExtensions.Add( | |
new X509EnhancedKeyUsageExtension( | |
new OidCollection { new Oid("1.3.6.1.5.5.7.3.1"), new Oid("1.3.6.1.5.5.7.3.2") }, true)); | |
request.CertificateExtensions.Add(sanBuilder.Build()); | |
if (ExpirationAfter == null) { ExpirationAfter = issuerCert.NotAfter.Date; } //DateTime.ParseExact(issuerCert.GetExpirationDateString(), "M/dd/yyyy h:mm:ss tt", CultureInfo.InvariantCulture); } | |
if (ExpirationBefore == null) ExpirationBefore = DateTime.UtcNow; | |
var certificate = request.Create(issuerCert, new DateTimeOffset(ExpirationBefore.Value), new DateTimeOffset(ExpirationAfter.Value), uniqueId.ToByteArray()); | |
certificate = certificate.CopyWithPrivateKey(rsa); | |
if (FriendlyName == null) FriendlyName = CommonName; | |
var key = certificate.GetRSAPrivateKey(); | |
File.WriteAllBytes(Destination, certificate.Export(X509ContentType.Pfx, Password)); | |
return certificate; | |
} | |
//return uniqueId; | |
} | |
public static X509Certificate2 GenerateCertificate(string name) | |
{ | |
string subjectName = $"CN={name}"; | |
using (RSA rsa = RSA.Create(4096)) | |
{ | |
CertificateRequest req = new CertificateRequest( | |
subjectName, | |
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)); | |
var selfSigned = req.CreateSelfSigned( | |
DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow.AddYears(50)); | |
return req.CreateSelfSigned( | |
DateTimeOffset.UtcNow.AddDays(-1), | |
DateTimeOffset.UtcNow.AddYears(50)); | |
} | |
} | |
#region Pem Helper | |
public static void GetPemData(X509Certificate2 cert, string fileName) | |
{ | |
byte[] certificateBytes = cert.RawData; | |
char[] certificatePem = PemEncoding.Write("CERTIFICATE", certificateBytes); | |
AsymmetricAlgorithm? key; | |
var rsaKey = cert.GetRSAPrivateKey(); | |
key = rsaKey != null ? rsaKey : cert.GetECDsaPrivateKey(); | |
//AsymmetricAlgorithm key = cert.GetRSAPrivateKey() ?? cert.GetECDsaPrivateKey(); | |
byte[] pubKeyBytes = key.ExportSubjectPublicKeyInfo(); | |
byte[] privKeyBytes = key.ExportPkcs8PrivateKey(); | |
char[] pubKeyPem = PemEncoding.Write("PUBLIC KEY", pubKeyBytes); | |
char[] privKeyPem = PemEncoding.Write("PRIVATE KEY", privKeyBytes); | |
File.WriteAllText($"{fileName}.crt", new string(pubKeyPem)); | |
File.WriteAllText($"{fileName}.key", new string(privKeyPem)); | |
} | |
public static X509Certificate2 SaveCertAsPem(X509Certificate2 cert, string fileName) | |
{ | |
string certPem = new string(PemEncoding.Write("CERTIFICATE", cert.RawData)); | |
string keyPem; | |
if (cert.GetRSAPrivateKey() is RSA rsaKey) | |
{ | |
keyPem = new string(PemEncoding.Write("PRIVATE KEY", rsaKey.ExportPkcs8PrivateKey())); | |
} | |
else if (cert.GetECDsaPrivateKey() is ECDsa ecdsaKey) | |
{ | |
keyPem = new string(PemEncoding.Write("PRIVATE KEY", ecdsaKey.ExportPkcs8PrivateKey())); | |
} | |
else if (cert.GetDSAPrivateKey() is DSA dsaKey) | |
{ | |
keyPem = new string(PemEncoding.Write("PRIVATE KEY", dsaKey.ExportPkcs8PrivateKey())); | |
} | |
else | |
{ | |
throw new CryptographicException("Unknown certificate algorithm"); | |
} | |
File.WriteAllText($"{fileName}.crt", certPem); | |
File.WriteAllText($"{fileName}.key", keyPem); | |
var certAgain = X509Certificate2.CreateFromPem(certPem, keyPem); | |
return certAgain; | |
} | |
#endregion | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Security; | |
using System.Security.Cryptography; | |
using System.Security.Cryptography.X509Certificates; | |
using System.Threading.Tasks; | |
namespace TestCert | |
{ | |
internal class Old | |
{ | |
private static X509Certificate2 buildSelfSignedServerCertificate() | |
{ | |
string CertificateName = "MirrorTubeCert"; | |
SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder(); | |
//sanBuilder.AddIpAddress(IPAddress.Loopback); | |
//sanBuilder.AddIpAddress(IPAddress.IPv6Loopback); | |
sanBuilder.AddDnsName("localhost"); | |
sanBuilder.AddDnsName(Environment.MachineName); | |
X500DistinguishedName distinguishedName = new X500DistinguishedName($"CN={CertificateName}"); | |
using (RSA rsa = RSA.Create(2048)) | |
{ | |
var request = new CertificateRequest(distinguishedName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); | |
request.CertificateExtensions.Add( | |
new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, false)); | |
request.CertificateExtensions.Add( | |
new X509EnhancedKeyUsageExtension( | |
new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, false)); | |
request.CertificateExtensions.Add(sanBuilder.Build()); | |
var certificate = request.CreateSelfSigned(new DateTimeOffset(DateTime.UtcNow.AddDays(-1)), new DateTimeOffset(DateTime.UtcNow.AddDays(3650))); | |
certificate.FriendlyName = CertificateName; | |
return new X509Certificate2(certificate.Export(X509ContentType.Pfx, "WeNeedASaf3rPassword"), "WeNeedASaf3rPassword", X509KeyStorageFlags.MachineKeySet); | |
} | |
} | |
private static void CreateCertificateForServerAuthentication() | |
{ | |
// Generate private-public key pair | |
var rsaKey = RSA.Create(2048); | |
// Describe certificate | |
string subject = "CN=localhost"; | |
// Create certificate request | |
var certificateRequest = new CertificateRequest( | |
subject, | |
rsaKey, | |
HashAlgorithmName.SHA256, | |
RSASignaturePadding.Pkcs1 | |
); | |
certificateRequest.CertificateExtensions.Add( | |
new X509BasicConstraintsExtension( | |
certificateAuthority: false, | |
hasPathLengthConstraint: false, | |
pathLengthConstraint: 0, | |
critical: true | |
) | |
); | |
certificateRequest.CertificateExtensions.Add( | |
new X509KeyUsageExtension( | |
keyUsages: | |
X509KeyUsageFlags.DigitalSignature | |
| X509KeyUsageFlags.KeyEncipherment, | |
critical: false | |
) | |
); | |
certificateRequest.CertificateExtensions.Add( | |
new X509SubjectKeyIdentifierExtension( | |
key: certificateRequest.PublicKey, | |
critical: false | |
) | |
); | |
certificateRequest.CertificateExtensions.Add( | |
new X509Extension( | |
new AsnEncodedData( | |
"Subject Alternative Name", | |
new byte[] { 48, 11, 130, 9, 108, 111, 99, 97, 108, 104, 111, 115, 116 } | |
), | |
false | |
) | |
); | |
var expireAt = DateTimeOffset.Now.AddYears(5); | |
var certificate = certificateRequest.CreateSelfSigned(DateTimeOffset.Now, expireAt); | |
// Export certificate with private key | |
var exportableCertificate = new X509Certificate2( | |
certificate.Export(X509ContentType.Cert), | |
(string)null, | |
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet | |
).CopyWithPrivateKey(rsaKey); | |
exportableCertificate.FriendlyName = "Ivan Yakimov Test-only Certificate For Server Authorization"; | |
// Create password for certificate protection | |
var passwordForCertificateProtection = new SecureString(); | |
foreach (var @char in "p@ssw0rd") | |
{ | |
passwordForCertificateProtection.AppendChar(@char); | |
} | |
// Export certificate to a file. | |
File.WriteAllBytes( | |
"certificateForServerAuthorization.pfx", | |
exportableCertificate.Export( | |
X509ContentType.Pfx, | |
passwordForCertificateProtection | |
) | |
); | |
// Test correctness of export | |
var loadedCertificate = new X509Certificate2("certificateForServerAuthorization.pfx", passwordForCertificateProtection); | |
Console.WriteLine(loadedCertificate.FriendlyName); | |
} | |
private static void CreateCertificateForClientAuthentication() | |
{ | |
// Generate private-public key pair | |
var rsaKey = RSA.Create(2048); | |
// Describe certificate | |
string subject = "CN=Ivan Yakimov"; | |
// Create certificate request | |
var certificateRequest = new CertificateRequest( | |
subject, | |
rsaKey, | |
HashAlgorithmName.SHA256, | |
RSASignaturePadding.Pkcs1 | |
); | |
certificateRequest.CertificateExtensions.Add( | |
new X509BasicConstraintsExtension( | |
certificateAuthority: false, | |
hasPathLengthConstraint: false, | |
pathLengthConstraint: 0, | |
critical: true | |
) | |
); | |
certificateRequest.CertificateExtensions.Add( | |
new X509KeyUsageExtension( | |
keyUsages: | |
X509KeyUsageFlags.DigitalSignature | |
| X509KeyUsageFlags.KeyEncipherment, | |
critical: false | |
) | |
); | |
certificateRequest.CertificateExtensions.Add( | |
new X509SubjectKeyIdentifierExtension( | |
key: certificateRequest.PublicKey, | |
critical: false | |
) | |
); | |
var expireAt = DateTimeOffset.Now.AddYears(5); | |
var certificate = certificateRequest.CreateSelfSigned(DateTimeOffset.Now, expireAt); | |
// Export certificate with private key | |
var exportableCertificate = new X509Certificate2( | |
certificate.Export(X509ContentType.Cert), | |
(string)null, | |
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet | |
).CopyWithPrivateKey(rsaKey); | |
exportableCertificate.FriendlyName = "Ivan Yakimov Test-only Certificate For Client Authorization"; | |
// Create password for certificate protection | |
var passwordForCertificateProtection = new SecureString(); | |
foreach (var @char in "p@ssw0rd") | |
{ | |
passwordForCertificateProtection.AppendChar(@char); | |
} | |
// Export certificate to a file. | |
File.WriteAllBytes( | |
"certificateForClientAuthorization.pfx", | |
exportableCertificate.Export( | |
X509ContentType.Pfx, | |
passwordForCertificateProtection | |
) | |
); | |
// Test correctness of export | |
var loadedCertificate = new X509Certificate2("certificateForClientAuthorization.pfx", passwordForCertificateProtection); | |
Console.WriteLine(loadedCertificate.FriendlyName); | |
} | |
public static X509Certificate2 GenerateCertificate(string name) | |
{ | |
string subjectName = $"CN={name}"; | |
using (RSA rsa = RSA.Create(4096)) | |
{ | |
CertificateRequest req = new CertificateRequest( | |
subjectName, | |
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)); | |
var selfSigned = req.CreateSelfSigned( | |
DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow.AddYears(50)); | |
return req.CreateSelfSigned( | |
DateTimeOffset.UtcNow.AddDays(-1), | |
DateTimeOffset.UtcNow.AddYears(50)); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Net; | |
using System.Net.Http; | |
using System.Net.Security; | |
using System.Net.Sockets; | |
using System.Security; | |
using System.Security.Cryptography; | |
using System.Security.Cryptography.X509Certificates; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace TestCert | |
{ | |
internal class Program | |
{ | |
//https://www.codeproject.com/Articles/5315010/How-to-Use-Certificates-in-ASP-NET-Core | |
static void Main(string[] args) | |
{ | |
Console.WriteLine("Hello, World!"); | |
const string CERT_NAME = "TestCert"; | |
const string CERT_PASS = "123456"; | |
//TestGen1(); | |
CreateRootCACert(); | |
var rootPub = File.ReadAllText($"RootCA.crt"); | |
var rootKey = File.ReadAllText($"RootCA.key"); | |
var rootCA = X509Certificate2.CreateFromPem(rootPub, rootKey); | |
var normalCert = CreateNormalCert(rootCA, "SERVER"); | |
var isValid = rootCA.GetPublicKeyString().Equals(normalCert.GetPublicKeyString()); | |
Console.WriteLine("Cert generated"); | |
//var contents = File.ReadAllText($"{CERT_NAME}.crt"); | |
//Console.WriteLine(contents); | |
Console.ReadKey(); | |
} | |
private static bool ValidateCert(X509Certificate2 rootCA, X509Certificate2 serverCert) | |
{ | |
X509Chain x509Chain = new X509Chain(); | |
x509Chain.ChainPolicy.ExtraStore.Add(rootCA); | |
x509Chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; | |
x509Chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; | |
x509Chain.Build(serverCert); | |
foreach (X509ChainElement x509ChainElement in x509Chain.ChainElements) | |
{ | |
//var dh = x509ChainElement.Certificate.PublicKey.GetECDiffieHellmanPublicKey(); | |
var foo = x509ChainElement.Certificate.GetPublicKeyString(); | |
var bar = rootCA.GetPublicKeyString(); | |
Console.WriteLine("Name: " + x509ChainElement.Certificate.GetNameInfo(X509NameType.SimpleName, false)); | |
foreach (X509ChainStatus x509ChainStatus in x509ChainElement.ChainElementStatus) | |
Console.WriteLine("status: " + x509ChainStatus.StatusInformation); | |
if (x509ChainElement.ChainElementStatus.Length != 0 && (x509ChainElement.Certificate.Thumbprint != rootCA.Thumbprint))// || x509ChainElement.ChainElementStatus[0].Status != X509ChainStatusFlags.UntrustedRoot)) | |
return false; | |
} | |
return true; | |
} | |
public static X509Certificate2 CreateRootCACert() | |
{ | |
const string ORGANIZATIONAL_UNIT = "RootCA"; | |
var cert = GenerateCert(ORGANIZATIONAL_UNIT, null); | |
SaveCertAsPem(cert, ORGANIZATIONAL_UNIT); | |
return cert; | |
} | |
public static X509Certificate2 CreateNormalCert(X509Certificate2 rootCA, string name) | |
{ | |
var rsaKey = rootCA.GetRSAPrivateKey(); | |
if (rsaKey != null) | |
{ | |
var cert = GenerateCert(name, rsaKey); | |
SaveCertAsPem(cert, name); | |
return cert; | |
} | |
return null; | |
} | |
private static IPAddress GetLocalIPAddress() | |
{ | |
var host = Dns.GetHostEntry(Dns.GetHostName()); | |
foreach (var ip in host.AddressList) | |
{ | |
if (ip.AddressFamily == AddressFamily.InterNetwork) | |
{ | |
return ip; | |
} | |
} | |
return IPAddress.Loopback; | |
} | |
private static X509Certificate2 GenerateCert(string CommonName, RSA? rsaKey) | |
{ | |
const string ORGANIZATION = "MirrorTube"; | |
if (rsaKey == null) | |
{ | |
rsaKey = RSA.Create(4096); | |
} | |
var OrganizationalUnit = $"{ORGANIZATION}.{CommonName}, Copyright (c) {DateTime.UtcNow.ToString("yyyy")}"; | |
SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder(); | |
sanBuilder.AddIpAddress(GetLocalIPAddress()); | |
sanBuilder.AddDnsName(Environment.MachineName); | |
var sb = new StringBuilder(); | |
sb.Append("CN=\"" + $"{ORGANIZATION}.{CommonName}".Replace("\"", "\"\"") + "\""); | |
sb.Append(",OU=\"" + OrganizationalUnit.Replace("\"", "\"\"") + "\""); | |
sb.Append(",O=\"" + ORGANIZATION.Replace("\"", "\"\"") + "\""); | |
sb.Append(",C=" + "US"); | |
var dn = sb.ToString(); | |
X500DistinguishedName distinguishedName = new X500DistinguishedName(dn); | |
string subjectName = $"CN=CA"; | |
CertificateRequest req = new CertificateRequest( | |
distinguishedName, | |
rsaKey, | |
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)); | |
req.CertificateExtensions.Add(sanBuilder.Build()); | |
var selfSigned = req.CreateSelfSigned( | |
DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow.AddYears(50)); | |
return selfSigned; | |
} | |
#region Pem Helper | |
public static void GetPemData(X509Certificate2 cert, string fileName) | |
{ | |
byte[] certificateBytes = cert.RawData; | |
char[] certificatePem = PemEncoding.Write("CERTIFICATE", certificateBytes); | |
AsymmetricAlgorithm? key; | |
var rsaKey = cert.GetRSAPrivateKey(); | |
key = rsaKey != null ? rsaKey : cert.GetECDsaPrivateKey(); | |
//AsymmetricAlgorithm key = cert.GetRSAPrivateKey() ?? cert.GetECDsaPrivateKey(); | |
byte[] pubKeyBytes = key.ExportSubjectPublicKeyInfo(); | |
byte[] privKeyBytes = key.ExportPkcs8PrivateKey(); | |
char[] pubKeyPem = PemEncoding.Write("PUBLIC KEY", pubKeyBytes); | |
char[] privKeyPem = PemEncoding.Write("PRIVATE KEY", privKeyBytes); | |
File.WriteAllText($"{fileName}.crt", new string(pubKeyPem)); | |
File.WriteAllText($"{fileName}.key", new string(privKeyPem)); | |
} | |
public static X509Certificate2 SaveCertAsPem(X509Certificate2 cert, string fileName) | |
{ | |
string certPem = new string(PemEncoding.Write("CERTIFICATE", cert.RawData)); | |
string keyPem; | |
if (cert.GetRSAPrivateKey() is RSA rsaKey) | |
{ | |
keyPem = new string(PemEncoding.Write("PRIVATE KEY", rsaKey.ExportPkcs8PrivateKey())); | |
} | |
else if (cert.GetECDsaPrivateKey() is ECDsa ecdsaKey) | |
{ | |
keyPem = new string(PemEncoding.Write("PRIVATE KEY", ecdsaKey.ExportPkcs8PrivateKey())); | |
} | |
else if (cert.GetDSAPrivateKey() is DSA dsaKey) | |
{ | |
keyPem = new string(PemEncoding.Write("PRIVATE KEY", dsaKey.ExportPkcs8PrivateKey())); | |
} | |
else | |
{ | |
throw new CryptographicException("Unknown certificate algorithm"); | |
} | |
File.WriteAllText($"{fileName}.crt", certPem); | |
File.WriteAllText($"{fileName}.key", keyPem); | |
var certAgain = X509Certificate2.CreateFromPem(certPem, keyPem); | |
return certAgain; | |
} | |
#endregion | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment