Scenario 12.1: PEM Export/Import
Category: Import/Export
Complexity: (Low)
Prerequisites: Certificate or key
Estimated Time: 10-15 minutes
</WRAP>
—-
===== Description =====
This scenario describes export and import in PEM format (Privacy-Enhanced Mail). PEM is the most common format for certificates and keys on Linux/Unix systems and is natively supported by OpenSSL.
PEM Properties:
* Encoding: Base64 with header/footer
* Header: —–BEGIN CERTIFICATE—– etc.
* Readability: Text file, easy to inspect
* Concatenation: Multiple objects possible in one file
—-
===== PEM Types =====
^ Type ^ Header ^ Content ^
| Certificate | BEGIN CERTIFICATE | X.509 certificate |
| Private Key | BEGIN PRIVATE KEY | PKCS#8 unencrypted |
| Encrypted Key | BEGIN ENCRYPTED PRIVATE KEY | PKCS#8 encrypted |
| RSA Key | BEGIN RSA PRIVATE KEY | PKCS#1 (legacy) |
| CSR | BEGIN CERTIFICATE REQUEST | PKCS#10 CSR |
| CRL | BEGIN X509 CRL | Certificate Revocation List |
—-
===== Code Example: Export Certificate as PEM =====
<code csharp>
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
using System.Security.Cryptography.X509Certificates;
using var ctx = PqCryptoContext.Initialize();
Load certificate
var cert = new X509Certificate2(„certificate.pfx“, „password“);
Export as PEM
ctx.ToPemFile(cert, „certificate.pem“);
Or as string
string pemString = ctx.ToPem(cert);
Console.WriteLine(pemString);
Output:
—–BEGIN CERTIFICATE—–
MIIBkTCB+wIJAK… (Base64)
—–END CERTIFICATE—–
</code>
—-
===== Code Example: Private Key as PEM =====
<code csharp>
using var ctx = PqCryptoContext.Initialize();
Generate key
using var keyPair = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65);
Unencrypted PEM (ONLY for tests!)
keyPair.ToPemFile(„private-key.pem“);
Encrypted PEM (RECOMMENDED)
keyPair.ToEncryptedPemFile(
path: „private-key-encrypted.pem“,
password: „StrongPassword123!“,
pbeAlgorithm: PbeAlgorithm.Aes256Cbc,
iterations: 100000
);
Public key separately
keyPair.PublicKey.ToPemFile(„public-key.pem“);
</code>
—-
===== Code Example: Import PEM =====
<code csharp>
using var ctx = PqCryptoContext.Initialize();
Load certificate from PEM
var cert = ctx.LoadCertificate(„certificate.pem“);
Console.WriteLine($„Subject: {cert.Subject}“);
Console.WriteLine($„Valid until: {cert.NotAfter:d}“);
Load encrypted private key
var privateKey = ctx.LoadPrivateKey(
path: „private-key-encrypted.pem“,
password: „StrongPassword123!“
);
Combine certificate with private key
var certWithKey = ctx.LoadCertificateWithPrivateKey(
certPath: „certificate.pem“,
keyPath: „private-key-encrypted.pem“,
keyPassword: „StrongPassword123!“
);
Console.WriteLine($„Has private key: {certWithKey.HasPrivateKey}“);
</code>
—-
===== Code Example: Certificate Chain as PEM =====
<code csharp>
public class PemChainExporter
{
public void ExportChainAsPem(
X509Certificate2 endEntity,
X509Certificate2Collection chain,
string outputPath)
{
using var ctx = PqCryptoContext.Initialize();
var sb = new StringBuilder();
End-entity certificate first
sb.AppendLine(„# End-Entity Certificate“);
sb.AppendLine(ctx.ToPem(endEntity));
Then intermediate CAs
foreach (var cert in chain.OrderBy(c ⇒ c.NotAfter))
{
if (cert.Thumbprint != endEntity.Thumbprint)
{
sb.AppendLine($„# Intermediate: {cert.Subject}“);
sb.AppendLine(ctx.ToPem(cert));
}
}
File.WriteAllText(outputPath, sb.ToString());
Console.WriteLine($„Chain exported: {outputPath}“);
}
public X509Certificate2Collection ImportChainFromPem(string pemPath)
{
using var ctx = PqCryptoContext.Initialize();
var pemContent = File.ReadAllText(pemPath);
var collection = new X509Certificate2Collection();
Extract PEM blocks
var certPattern = @„—–BEGIN CERTIFICATE—–(.*?)—–END CERTIFICATE—–“;
var matches = Regex.Matches(pemContent, certPattern, RegexOptions.Singleline);
foreach (Match match in matches)
{
var base64 = match.Groups[1].Value.Trim();
var certBytes = Convert.FromBase64String(base64);
collection.Add(new X509Certificate2(certBytes));
}
Console.WriteLine($„{collection.Count} certificates imported“);
return collection;
}
}
</code>
—-
===== PEM Conversion with OpenSSL =====
<code bash>
# Convert DER to PEM
openssl x509 -in cert.der -inform DER -out cert.pem -outform PEM
# Convert PEM to DER
openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER
# Inspect PEM certificate
openssl x509 -in cert.pem -text -noout
# Encrypt private key
openssl pkcs8 -topk8 -in key.pem -out key-encrypted.pem -aes256
# Decrypt private key
openssl pkcs8 -in key-encrypted.pem -out key.pem
</code>
—-
===== Industry-Specific PEM Usage =====
^ System ^ PEM Format ^ Specifics ^
| Apache | Separate .crt and .key | SSLCertificateFile, SSLCertificateKeyFile |
| Nginx | Chain in one .pem | ssl_certificate (fullchain) |
| HAProxy | Cert + key in one file | bind … ssl crt combined.pem |
| OpenSSL | All formats | Standard tool |
| Kubernetes | Base64-encoded in secrets | kubectl create secret tls |
—-
===== Related Scenarios =====
^ Relationship ^ Scenario ^ Description ^
| Alternative | 12.2 PFX Export | Windows format |
| Related | 12.3 PKCS#7 Chain | Certificates only |
| Related | 11.2 Key Storage | Secure storage |
—-
« <- Import/Export Overview | ^ Import/Export | 12.2 PFX Export -> »
—- Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional