Category: Certificate Management
Complexity: ⭐⭐⭐ (Medium)
Prerequisites: Existing certificate, same key
Estimated Time: 10-15 Minutes
This scenario describes the renewal of an expiring certificate while retaining the existing key pair. Renewal is appropriate when the key has not been compromised and the key strength is still sufficient.
Renewal vs. Rekey:
| Aspect | Renewal | Rekey |
|---|---|---|
| Key Pair | Same | New |
| CSR | Optionally new | Required new |
| Subject | Can be adjusted | Can be adjusted |
| Reason | Expiry | Compromise, upgrade |
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using var ctx = PqCryptoContext.Initialize(); // Load existing certificate and key var oldCert = ctx.LoadCertificate("server.crt.pem"); var existingKey = ctx.LoadPrivateKey("server.key.pem", "KeyPassword!"); // Load CA var caCert = ctx.LoadCertificate("intermediate-ca.crt.pem"); var caKey = ctx.LoadPrivateKey("intermediate-ca.key.pem", "CaPassword!"); // Check if renewal makes sense var daysUntilExpiry = (oldCert.NotAfter - DateTime.UtcNow).Days; if (daysUntilExpiry > 90) { Console.WriteLine($"Certificate still valid for {daysUntilExpiry} days."); } // Create CSR with existing key var csr = ctx.CreateCertificateRequest( existingKey, oldCert.SubjectName, // Preserve subject ctx.GetExtensions(oldCert) // Preserve extensions ); // Issue new certificate var newCert = ctx.IssueCertificate( csr, issuerCert: caCert, issuerKey: caKey, serialNumber: ctx.GenerateSerialNumber(), // New serial! validFrom: DateTime.UtcNow.AddDays(-1), // Overlap validDays: 365, extensions: new ExtBuilder() .BasicConstraints(ca: false, critical: true) .KeyUsage(KeyUsageFlags.DigitalSignature | KeyUsageFlags.KeyEncipherment) .ExtendedKeyUsage(ExtKeyUsage.ServerAuth) .SubjectKeyIdentifier(existingKey.PublicKey) // Same SKI! .AuthorityKeyIdentifier(caCert) .CrlDistributionPoint("http://crl.example.com/intermediate.crl") .Build() ); // Save newCert.ToPemFile("server-renewed.crt.pem"); Console.WriteLine("Certificate renewed:"); Console.WriteLine($" Old Serial: {oldCert.SerialNumber}"); Console.WriteLine($" New Serial: {newCert.SerialNumber}"); Console.WriteLine($" New Expiry Date: {newCert.NotAfter:yyyy-MM-dd}");
// Check all certificates in store public IEnumerable<X509Certificate2> GetExpiringCertificates( X509Store store, int warningDays = 30) { store.Open(OpenFlags.ReadOnly); try { return store.Certificates .Where(c => c.NotAfter <= DateTime.UtcNow.AddDays(warningDays)) .Where(c => c.NotAfter > DateTime.UtcNow) // Not yet expired .OrderBy(c => c.NotAfter) .ToList(); } finally { store.Close(); } } // Usage using var store = new X509Store(StoreName.My, StoreLocation.LocalMachine); var expiring = GetExpiringCertificates(store, warningDays: 30); foreach (var cert in expiring) { Console.WriteLine($"WARNING: {cert.Subject} expires on {cert.NotAfter:d}"); }
| Industry | Typical Cycle | Renewal Lead Time | Special Feature |
|---|---|---|---|
| Standard IT | 1 year | 30 days | Automation recommended |
| Energy/SCADA | 3-5 years | 90 days | Observe maintenance windows |
| Healthcare | 1-2 years | 60 days | Audit trail required |
| Automotive | 2-3 years | 180 days | OTA update planning |
Renewal Recommendations:
When NOT to renew:
| Relationship | Scenario | Description |
|---|---|---|
| Alternative | 4.2 Rekey | New key |
| Next Step | 6.4 Revoke | Old certificate |
| Related | 4.4 Backup | Backup before renewal |
« ← Management Overview | ↑ Scenarios | 4.2 Rekey → »
Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional