~~NOTOC~~
====== Scenarij 12.3: PKCS#7 izvoz lanca ======
**Kategorija:** [[.:start|Uvoz/Izvoz]] \\
**Složenost:** ⭐⭐ (Niska) \\
**Preduvjeti:** Lanac certifikata \\
**Procijenjeno vrijeme:** 10-15 minuta
----
===== Opis =====
Ovaj scenarij opisuje **izvoz i uvoz lanaca certifikata u PKCS#7 formatu**. PKCS#7 (također CMS - Cryptographic Message Syntax) idealan je za distribuciju lanaca certifikata bez privatnih ključeva.
**PKCS#7 svojstva:**
* **Sadržaj:** Samo certifikati (bez privatnih ključeva!)
* **Uporaba:** Distribucija lanca, S/MIME
* **Ekstenzije:** .p7b, .p7c
* **Kodiranje:** DER (Binary) ili PEM (Base64)
----
===== Tijek rada =====
flowchart TD
subgraph Ulaz
ROOT[Root-CA]
INT[Intermediate-CA]
EE[End-Entity]
end
subgraph PKCS7["PKCS#7 kontejner"]
CERTS[SignedData.Certificates]
end
ROOT --> CERTS
INT --> CERTS
EE --> CERTS
PKCS7 --> DER[.p7b Binary]
PKCS7 --> PEM[.p7b PEM]
----
===== Primjer koda: Izvoz lanca kao PKCS#7 =====
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
public class Pkcs7ChainExporter
{
public byte[] ExportChain(X509Certificate2Collection certificates)
{
// SignedCms bez potpisa (samo certifikati)
var content = new ContentInfo(Array.Empty());
var signedCms = new SignedCms(content, detached: true);
// Dodavanje certifikata
foreach (var cert in certificates)
{
signedCms.Certificates.Add(cert);
}
// Izvoz kao PKCS#7 (DER)
return signedCms.Encode();
}
public void ExportToFile(
X509Certificate2Collection certificates,
string outputPath,
bool asPem = false)
{
var p7bBytes = ExportChain(certificates);
if (asPem)
{
// PEM format
var pem = new StringBuilder();
pem.AppendLine("-----BEGIN PKCS7-----");
pem.AppendLine(Convert.ToBase64String(p7bBytes, Base64FormattingOptions.InsertLineBreaks));
pem.AppendLine("-----END PKCS7-----");
File.WriteAllText(outputPath, pem.ToString());
}
else
{
// Binary (DER)
File.WriteAllBytes(outputPath, p7bBytes);
}
Console.WriteLine($"PKCS#7 izvezen: {outputPath} ({certificates.Count} certifikata)");
}
}
----
===== Primjer koda: Kreiranje i izvoz potpunog lanca =====
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
public class FullChainExporter
{
public void ExportFullChain(
X509Certificate2 endEntity,
string outputPath)
{
using var ctx = PqCryptoContext.Initialize();
// Izgradnja lanca
using var chain = new X509Chain();
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
chain.Build(endEntity);
// Prikupljanje svih certifikata
var collection = new X509Certificate2Collection();
collection.Add(endEntity);
foreach (var element in chain.ChainElements)
{
if (element.Certificate.Thumbprint != endEntity.Thumbprint)
{
collection.Add(element.Certificate);
}
}
// Izvoz kao PKCS#7
var exporter = new Pkcs7ChainExporter();
exporter.ExportToFile(collection, outputPath);
// Ispis detalja
Console.WriteLine("Lanac izvezen:");
foreach (var cert in collection)
{
Console.WriteLine($" [{cert.Thumbprint.Substring(0, 8)}] {cert.Subject}");
}
}
}
----
===== Primjer koda: Uvoz PKCS#7 =====
public class Pkcs7ChainImporter
{
public X509Certificate2Collection ImportChain(byte[] p7bBytes)
{
var collection = new X509Certificate2Collection();
collection.Import(p7bBytes);
Console.WriteLine($"{collection.Count} certifikata uvezeno");
return collection;
}
public X509Certificate2Collection ImportFromFile(string filePath)
{
byte[] data;
var content = File.ReadAllText(filePath);
if (content.Contains("-----BEGIN PKCS7-----"))
{
// PEM format
var base64 = Regex.Match(
content,
@"-----BEGIN PKCS7-----(.*?)-----END PKCS7-----",
RegexOptions.Singleline
).Groups[1].Value.Trim();
data = Convert.FromBase64String(base64);
}
else
{
// Binary (DER)
data = File.ReadAllBytes(filePath);
}
return ImportChain(data);
}
public void InstallChainToStore(
string p7bPath,
StoreName storeName = StoreName.CertificateAuthority,
StoreLocation location = StoreLocation.LocalMachine)
{
var certs = ImportFromFile(p7bPath);
using var store = new X509Store(storeName, location);
store.Open(OpenFlags.ReadWrite);
foreach (var cert in certs)
{
// Provjera je li samopotpisan (Root)
var targetStore = cert.Subject == cert.Issuer
? new X509Store(StoreName.Root, location)
: store;
if (targetStore.Name != store.Name)
{
targetStore.Open(OpenFlags.ReadWrite);
}
// Provjera postoji li već
var existing = targetStore.Certificates.Find(
X509FindType.FindByThumbprint,
cert.Thumbprint,
validOnly: false
);
if (existing.Count == 0)
{
targetStore.Add(cert);
Console.WriteLine($"Instalirano: {cert.Subject}");
}
if (targetStore.Name != store.Name)
{
targetStore.Close();
}
}
store.Close();
}
}
----
===== Primjer koda: CA Bundle za web server =====
public class CaBundleCreator
{
public void CreateCaBundle(
X509Certificate2 rootCa,
X509Certificate2Collection intermediateCas,
string outputPath)
{
var collection = new X509Certificate2Collection();
// Intermediates prvo (najbliži serveru)
foreach (var intermediate in intermediateCas.OrderByDescending(c => c.NotAfter))
{
collection.Add(intermediate);
}
// Root zadnji
collection.Add(rootCa);
var exporter = new Pkcs7ChainExporter();
exporter.ExportToFile(collection, outputPath);
Console.WriteLine("CA Bundle kreiran:");
Console.WriteLine($" Intermediates: {intermediateCas.Count}");
Console.WriteLine($" Root: {rootCa.Subject}");
}
public void CreateNginxCaBundle(
X509Certificate2 serverCert,
X509Certificate2Collection chain,
string outputPath)
{
// Nginx očekuje PEM lanac (server prvo, zatim intermediates)
var sb = new StringBuilder();
// Serverski certifikat
sb.AppendLine(ToPem(serverCert));
// Intermediates (ne Root!)
foreach (var cert in chain.Where(c => c.Subject != c.Issuer))
{
sb.AppendLine(ToPem(cert));
}
File.WriteAllText(outputPath, sb.ToString());
Console.WriteLine($"Nginx CA Bundle: {outputPath}");
}
private string ToPem(X509Certificate2 cert)
{
var sb = new StringBuilder();
sb.AppendLine("-----BEGIN CERTIFICATE-----");
sb.AppendLine(Convert.ToBase64String(cert.RawData, Base64FormattingOptions.InsertLineBreaks));
sb.AppendLine("-----END CERTIFICATE-----");
return sb.ToString();
}
}
----
===== PKCS#7 s OpenSSL =====
# Kreiranje PKCS#7 iz više certifikata
openssl crl2pkcs7 -nocrl \
-certfile root-ca.pem \
-certfile intermediate-ca.pem \
-certfile server.pem \
-out chain.p7b \
-outform DER
# PKCS#7 kao PEM
openssl crl2pkcs7 -nocrl \
-certfile chain.pem \
-out chain.p7b \
-outform PEM
# Pregled PKCS#7
openssl pkcs7 -in chain.p7b -print_certs -noout
# Ekstrakcija certifikata iz PKCS#7
openssl pkcs7 -in chain.p7b -print_certs -out extracted.pem
# PKCS#7 informacije
openssl pkcs7 -in chain.p7b -inform DER -text
----
===== Uporaba u različitim sustavima =====
^ Sustav ^ PKCS#7 uporaba ^ Format ^
| **Windows** | Intermediate-CA Store | .p7b (DER) |
| **IIS** | SSL Certificate Chain | .p7b |
| **Java** | Trust Store Import | .p7b (DER) |
| **S/MIME** | E-mail šifriranje | Dio poruke |
| **Code Signing** | Timestamp + Chain | Ugrađeno |
----
===== Povezani scenariji =====
^ Povezanost ^ Scenarij ^ Opis ^
| **Alternativa** | [[.:pem_export|12.1 PEM izvoz]] | Lanac kao PEM |
| **Povezano** | [[.:pfx_export|12.2 PFX izvoz]] | S privatnim ključem |
| **Preduvjet** | [[hr:int:pqcrypt:szenarien:pki:ca_hierarchie|1.3 CA hijerarhija]] | Izgradnja lanca |
| **Povezano** | [[hr:int:pqcrypt:szenarien:validierung:chain_building|5.1 Izgradnja lanca]] | Validacija lanca |
----
<< [[.:pfx_export|← 12.2 PFX izvoz]] | [[.:start|↑ Uvoz/Izvoz]] | [[.:interop|12.4 Interoperabilnost →]] >>
{{tag>scenarij uvoz izvoz pkcs7 lanac p7b}}
----
//Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//