Skip to content

Instantly share code, notes, and snippets.

@micah686
Created November 11, 2023 17:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save micah686/a88f61f44c0aa12d5d1c8cfd56fce9a6 to your computer and use it in GitHub Desktop.
Save micah686/a88f61f44c0aa12d5d1c8cfd56fce9a6 to your computer and use it in GitHub Desktop.
Create X509Cert
using System.Globalization;
using System.Net;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
internal class CertHelper
{
internal static void CreateCerts()
{
var rootCA = CreateX509Cert(CertTypes.RootCA);
var normalCert = CreateX509Cert(CertTypes.UtilitiesAPI, "ReflectTube.RootCA.key");
var normalCert2 = CreateX509Cert(CertTypes.DataAPI, "ReflectTube.RootCA.key");
var result = ValidateCertificates(rootCA, normalCert);
var rootca = new X509Certificate2(File.ReadAllBytes("ReflectTube.RootCA.crt"));
var secondary = new X509Certificate2(File.ReadAllBytes("ReflectTube.UtilitiesAPI.crt"));
var isValid = rootca.GetPublicKeyString().Equals(secondary.GetPublicKeyString());
}
public static X509Certificate2 CreateX509Cert(CertTypes certType, string? rsaKeyFile = "")
{
const string ORGANIZATION = "ReflectTube";
string countryCode = RegionInfo.CurrentRegion.TwoLetterISORegionName;
string oid = "1.3.6.1.5.5.7.3.1"; //http://www.oid-info.com/cgi-bin/display?oid=1.3.6.1.5.5.7.3.1&a=display
var sanBuilder = new SubjectAlternativeNameBuilder();
sanBuilder.AddIpAddress(IPAddress.Loopback);
sanBuilder.AddIpAddress(IPAddress.IPv6Loopback);
sanBuilder.AddDnsName(Environment.MachineName);
using (var rsa = RSA.Create(4096))
{
if(!string.IsNullOrEmpty(rsaKeyFile) && File.Exists(rsaKeyFile))
{
rsa.ImportFromPem(File.ReadAllText(rsaKeyFile));
oid = "1.3.6.1.5.5.7.3.2";
}
string dn = $"""CN="{ORGANIZATION}.{certType}",OU="{ORGANIZATION}.{certType}, Copyright (c) {DateTime.UtcNow:yyyy}",O="{ORGANIZATION}",C={countryCode}""";//raw string literal
X500DistinguishedName distinguishedName = new X500DistinguishedName(dn);
var certRequest = new CertificateRequest(distinguishedName, rsa, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1); //matches except 512 vs 256
certRequest.CertificateExtensions.Add(new X509KeyUsageExtension(
X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation, false)); //uses Data and Key
certRequest.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection { new(oid) }, false)); //marked as not critical/false
certRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(certRequest.PublicKey, false)); //I added this
certRequest.CertificateExtensions.Add(sanBuilder.Build());
var selfSigned = certRequest.CreateSelfSigned(DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow.AddYears(50));
string certPem = new string(PemEncoding.Write("CERTIFICATE", selfSigned.RawData));
File.WriteAllText($"{ORGANIZATION}.{certType}.crt", certPem);
using (var certRSA = selfSigned.GetRSAPrivateKey())
{
if (certRSA != null)
{
File.WriteAllText($"{ORGANIZATION}.{certType}.key", certRSA.ExportRSAPrivateKeyPem());
}
else
{
throw new InvalidOperationException("Couldn't export private key!");
}
}
return selfSigned;
}
}
public enum CertTypes
{
RootCA,
DataAPI,
AccountAPI,
QueryAPI,
MessagingAPI,
UtilitiesAPI
}
public static bool ValidateCertificates(X509Certificate2 rootCA, X509Certificate2 certToCheck)
{
using (var chain = new X509Chain
{
ChainPolicy =
{
RevocationMode = X509RevocationMode.NoCheck,
RevocationFlag = X509RevocationFlag.ExcludeRoot,
VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority,
VerificationTime = DateTime.Now
}
})
{
chain.ChainPolicy.ExtraStore.Add(rootCA);
if (!chain.Build(certToCheck))
{
//Errorhandling
}
//Root certificate should always be last in the X509ChainElements collection
var isSignedByCorrectRootCert =
chain.ChainElements
.Cast<X509ChainElement>()
.Last()
.Certificate.Thumbprint == rootCA.Thumbprint;
return isSignedByCorrectRootCert;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment