Kategorija: Uvoz/Izvoz
Kompleksnost: ⭐⭐⭐ (Srednja)
Predpogoji: Certifikat z zasebnim ključem
Predviden čas: 15-20 minut
Ta scenarij opisuje izvoz in uvoz v PFX/PKCS#12 formatu. PFX (Personal Information Exchange) je standardni format za Windows in .NET za shranjevanje certifikatov skupaj z zasebnimi ključi in opcijsko certifikatno verigo v z geslom zaščiteni datoteki.
Lastnosti PFX/PKCS#12:
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using System.Security.Cryptography.X509Certificates; using var ctx = PqCryptoContext.Initialize(); // Nalaganje certifikata in ključa var cert = ctx.LoadCertificate("server.crt.pem"); var privateKey = ctx.LoadPrivateKey("server.key.pem", "KeyPassword!"); // Kombinacija certifikata s ključem var certWithKey = ctx.CombineCertificateAndKey(cert, privateKey); // Izvoz PFX byte[] pfxBytes = certWithKey.Export(X509ContentType.Pfx, "PfxPassword123!"); File.WriteAllBytes("server.pfx", pfxBytes); Console.WriteLine("PFX ustvarjen: server.pfx");
public class PfxExporter { public byte[] ExportWithChain( X509Certificate2 certificate, X509Certificate2Collection chain, string password, PfxExportOptions options = null) { options ??= PfxExportOptions.Default; using var ctx = PqCryptoContext.Initialize(); // Ustvarjanje kolekcije za izvoz var exportCollection = new X509Certificate2Collection(); exportCollection.Add(certificate); // Dodajanje verige (brez Root, če je želeno) foreach (var caCert in chain) { if (options.IncludeRoot || !IsSelfSigned(caCert)) { exportCollection.Add(caCert); } } // Izvoz PFX var pfxBytes = exportCollection.Export(X509ContentType.Pfx, password); Console.WriteLine($"PFX ustvarjen z {exportCollection.Count} certifikati"); return pfxBytes; } public void ExportToFile( X509Certificate2 certificate, X509Certificate2Collection chain, string outputPath, string password) { var pfxBytes = ExportWithChain(certificate, chain, password); File.WriteAllBytes(outputPath, pfxBytes); // Nastavitev dovoljenj (samo lastnik) if (OperatingSystem.IsWindows()) { var fileInfo = new FileInfo(outputPath); var security = fileInfo.GetAccessControl(); security.SetAccessRuleProtection(true, false); fileInfo.SetAccessControl(security); } } private bool IsSelfSigned(X509Certificate2 cert) { return cert.Subject == cert.Issuer; } } public class PfxExportOptions { public bool IncludeRoot { get; set; } = false; public bool IncludeChain { get; set; } = true; public static PfxExportOptions Default => new PfxExportOptions(); }
using var ctx = PqCryptoContext.Initialize(); // Nalaganje PFX var pfxBytes = File.ReadAllBytes("server.pfx"); var cert = new X509Certificate2( pfxBytes, "PfxPassword123!", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet ); Console.WriteLine($"Subject: {cert.Subject}"); Console.WriteLine($"Ima zasebni ključ: {cert.HasPrivateKey}"); // Ekstrakcija zasebnega ključa if (cert.HasPrivateKey) { var privateKey = cert.GetRSAPrivateKey() ?? cert.GetECDsaPrivateKey() ?? (AsymmetricAlgorithm)ctx.GetPqPrivateKey(cert); Console.WriteLine($"Tip ključa: {privateKey.GetType().Name}"); } // Ekstrakcija verige iz PFX var collection = new X509Certificate2Collection(); collection.Import(pfxBytes, "PfxPassword123!", X509KeyStorageFlags.DefaultKeySet); Console.WriteLine($"Certifikati v PFX: {collection.Count}"); foreach (var c in collection) { Console.WriteLine($" - {c.Subject}"); }
public class SecurePfxExporter { public byte[] ExportSecure( X509Certificate2 certificate, string password) { // .NET 5+ podpira moderno PFX šifriranje var exportParams = new PbeParameters( PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, iterations: 100000 ); return certificate.Export(X509ContentType.Pfx, password); } public byte[] ExportWithOpenSsl( X509Certificate2 certificate, AsymmetricAlgorithm privateKey, X509Certificate2Collection chain, string password) { using var ctx = PqCryptoContext.Initialize(); // Izvoz temelječ na OpenSSL za maksimalno združljivost var pfxBuilder = new Pkcs12Builder(); // Dodajanje Key Bag var keyBag = new Pkcs12KeyBag( privateKey.ExportPkcs8PrivateKey(), skipCopy: false ); // Dodajanje Cert Bag var certBag = new Pkcs12CertBag(certificate); // Ustvarjanje Safe Contents var safeContents = new Pkcs12SafeContents(); safeContents.AddBag(keyBag); safeContents.AddBag(certBag); foreach (var caCert in chain) { safeContents.AddBag(new Pkcs12CertBag(caCert)); } // Šifriranje z geslom pfxBuilder.AddSafeContentsEncrypted( safeContents, password, new PbeParameters( PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 100000 ) ); pfxBuilder.SealWithMac(password, HashAlgorithmName.SHA256, 100000); return pfxBuilder.Encode(); } }
public class WindowsCertificateInstaller { public void InstallPfxToStore( string pfxPath, string password, StoreName storeName = StoreName.My, StoreLocation location = StoreLocation.LocalMachine) { var pfxBytes = File.ReadAllBytes(pfxPath); var cert = new X509Certificate2( pfxBytes, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable ); using var store = new X509Store(storeName, location); store.Open(OpenFlags.ReadWrite); // Preverjanje ali že obstaja var existing = store.Certificates.Find( X509FindType.FindByThumbprint, cert.Thumbprint, validOnly: false ); if (existing.Count > 0) { Console.WriteLine("Certifikat že obstaja v shrambi"); return; } store.Add(cert); store.Close(); Console.WriteLine($"Certifikat nameščen: {cert.Subject}"); Console.WriteLine($"Shramba: {storeName} ({location})"); Console.WriteLine($"Prstni odtis: {cert.Thumbprint}"); } public void ExportFromStore( string thumbprint, string outputPath, string password, StoreName storeName = StoreName.My, StoreLocation location = StoreLocation.LocalMachine) { using var store = new X509Store(storeName, location); store.Open(OpenFlags.ReadOnly); var certs = store.Certificates.Find( X509FindType.FindByThumbprint, thumbprint, validOnly: false ); if (certs.Count == 0) { throw new Exception($"Certifikat ni najden: {thumbprint}"); } var cert = certs[0]; if (!cert.HasPrivateKey) { throw new Exception("Certifikat nima zasebnega ključa"); } var pfxBytes = cert.Export(X509ContentType.Pfx, password); File.WriteAllBytes(outputPath, pfxBytes); Console.WriteLine($"PFX izvožen: {outputPath}"); } }
# Ustvarjanje PFX iz PEM datotek openssl pkcs12 -export \ -out server.pfx \ -inkey server.key \ -in server.crt \ -certfile chain.pem \ -passout pass:MyPassword # PFX z modernim algoritmom (AES-256) openssl pkcs12 -export \ -out server.pfx \ -inkey server.key \ -in server.crt \ -certfile chain.pem \ -aes256 \ -passout pass:MyPassword # Pregled PFX openssl pkcs12 -info -in server.pfx -passin pass:MyPassword # Razpakiranje PFX openssl pkcs12 -in server.pfx \ -out combined.pem \ -nodes \ -passin pass:MyPassword
| Panoga | Hramba ključev | Izvoz | Posebnost |
|---|---|---|---|
| Windows Server | MachineKeySet | Exportable | IIS SSL vezava |
| Azure | UserKeySet | Non-Exportable | App Service |
| Podpisovanje kode | MachineKeySet | Non-Exportable | Authenticode |
| Pametna kartica | Strojna oprema | Non-Exportable | PIV certifikati |
| Povezava | Scenarij | Opis |
|---|---|---|
| Alternativa | 12.1 PEM izvoz | Linux format |
| Povezano | 12.3 PKCS#7 veriga | Samo certifikati |
| Predpogoj | 3.1 Strežniški certifikat | Ustvarjanje certifikata |
« ← 12.1 PEM izvoz | ↑ Uvoz/Izvoz | 12.3 PKCS#7 veriga → »
Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional