Search code examples
c#dotnet-httpclientx509certificate2.net-4.8

Creating PEM certificates in .NET Framework 4.8


I need to create a certificate from a .CER en .KEY file. I have a piece of working code in .NET 5, but this code needs to be converted to .NET Framework 4.8. Then method CreateFromPemFile does not exist in .NET Framework 4.8, so I need something else. I have already tried libraries like BouncyCastle, but somehow I keep getting exceptions. I even tried ChatGPT, but no luck yet.

static public X509Certificate2 CreateCertificate(string certificatePath, string keyPath)
{
    return new X509Certificate2(
        X509Certificate2.CreateFromPemFile(certificatePath, keyPath)
        .Export(X509ContentType.Pfx));
}

Maybe obvious, maybe neeeded:

The cer-file starts with: -----BEGIN CERTIFICATE-----

The key-file starts with: -----BEGIN PRIVATE KEY-----


Solution

  • After a lot of reading, trying, and asking chatGPT, I came up with the following solution, using BouncyCastle. This works for me. Maybe it helps others:

    using System.IO;
    using Org.BouncyCastle.Crypto;
    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.OpenSsl;
    using Org.BouncyCastle.Pkcs;
    
    namespace Turien.Relations.TestConsole
    {
        using X509Certificate2 = System.Security.Cryptography.X509Certificates.X509Certificate2;
    
        static class CertificateUtilities
        {
            static public X509Certificate2 CreateCertificate(string certificatePath, string keyPath)
            {
                var certParser = new Org.BouncyCastle.X509.X509CertificateParser();
                var cert = certParser.ReadCertificate(File.ReadAllBytes(certificatePath));
    
                AsymmetricCipherKeyPair keyPair;
                using (var reader = new StreamReader(keyPath))
                {
                    var pemReader = new PemReader(reader);
                    var rsaParams = (RsaPrivateCrtKeyParameters)pemReader.ReadObject();
                    var rsaPubParams = new RsaKeyParameters(false, rsaParams.Modulus, rsaParams.PublicExponent);
                    keyPair = new AsymmetricCipherKeyPair(rsaPubParams, rsaParams);
                }
    
                var store = new Pkcs12Store();
                var certEntry = new X509CertificateEntry(cert);
                store.SetCertificateEntry(cert.SubjectDN.ToString(), certEntry);
                store.SetKeyEntry(cert.SubjectDN.ToString(), new AsymmetricKeyEntry(keyPair.Private), new[] { certEntry });
    
                using (var stream = new MemoryStream())
                {
                    store.Save(stream, null, new Org.BouncyCastle.Security.SecureRandom());
                    return new X509Certificate2(stream.ToArray());
                }
            }
        }
    }