using System.Security.Cryptography;using System.Security.Cryptography.X509Certificates; // Certificate: RawData is the DER, ExportCertificatePem() the PEM (no trailing newline)using X509Certificate2 cert = X509CertificateLoader.LoadCertificateFromFile("cert.pem"); // PEM or DERFile.WriteAllBytes("cert.der", cert.RawData);using X509Certificate2 fromDer = X509CertificateLoader.LoadCertificate(File.ReadAllBytes("cert.der"));File.WriteAllText("cert-again.pem", fromDer.ExportCertificatePem() + "\n"); Console.WriteLine($"cert DER: {cert.RawData.Length} bytes, sha256 {Convert.ToHexStringLower(SHA256.HashData(cert.RawData))}");Console.WriteLine($"cert PEM again identical: {File.ReadAllText("cert-again.pem") == File.ReadAllText("cert.pem")}"); using System.Security.Cryptography; // Any PEM block: PemEncoding finds the label and the base64 payloadstring pem = File.ReadAllText("key.pem");PemFields fields = PemEncoding.Find(pem);string label = pem[fields.Label]; // "PRIVATE KEY"byte[] der = Convert.FromBase64String(pem[fields.Base64Data]); // PKCS#8 DERFile.WriteAllBytes("key.der", der); // Back to PEM; importing proves the bytes are a valid PKCS#8 keyusing ECDsa key = ECDsa.Create();key.ImportPkcs8PrivateKey(File.ReadAllBytes("key.der"), out _);string again = new string(PemEncoding.Write("PRIVATE KEY", key.ExportPkcs8PrivateKey())) + "\n"; Console.WriteLine($"{label} DER: {der.Length} bytes, sha256 {Convert.ToHexStringLower(SHA256.HashData(der))}");Console.WriteLine($"key PEM again identical: {again == pem}");Console.WriteLine($"ExportECPrivateKey (SEC1) instead: {key.ExportECPrivateKey().Length} bytes"); How it works
X509CertificateLoader.LoadCertificateFromFilereads PEM or DER;RawDatais the DER (563 bytes here) andExportCertificatePem()the PEM without a trailing newline.PemEncoding.Findreturns ranges:pem[fields.Label]is the label (PRIVATE KEY) andConvert.FromBase64String(pem[fields.Base64Data])the DER — 138 bytes of PKCS#8.ImportPkcs8PrivateKeyproves the bytes are a valid key;ExportPkcs8PrivateKeyplusPemEncoding.Write("PRIVATE KEY", …)gives the PEM back, identical to the input.- The run checks the certificate's DER with OpenSSL (
openssl x509 -inform DER).
Gotchas
ExportCertificatePem()andPemEncoding.Writeend without a newline; append\nwhen the file must be byte-identical to OpenSSL's output, as the run does.ExportECPrivateKey()writes SEC1 (121 bytes here),ExportPkcs8PrivateKey()PKCS#8 (138 bytes) — same key, different structures; pick the one the consumer expects.
Related recipes
- How to convert a certificate and a private key between PEM and DER in Java
- How to convert a certificate and a private key between PEM and DER in Python
- How to convert a certificate and a private key between PEM and DER with OpenSSL
- How to export a public key as PEM in C# (.NET)
- How to decode an X.509 certificate in C# (.NET)