Scenarij 8.2: Potpisivanje koda
Kategorija: Digitalni potpisi
Složenost: ⭐⭐⭐⭐ (Visoka)
Preduvjeti: Code-Signing certifikat
Procijenjeno vrijeme: 20-30 minuta
Opis
Ovaj scenarij opisuje potpisivanje koda i izvršnih datoteka s Post-Quantum-sigurnim algoritmima. Code Signing omogućuje:
- Autentifikaciju izdavača softvera
- Zaštitu integriteta od manipulacije
- Povjerenje za krajnje korisnike
- Usklađenost sa sigurnosnim smjernicama
Podržani formati:
- Windows Authenticode (EXE, DLL, MSI)
- PowerShell Scripts (.ps1)
- NuGet Packages (.nupkg)
- Java JAR Files
- macOS Code Signature
Tijek rada
flowchart LR
CODE[Executable/DLL] --> HASH[Authenticode Hash]
HASH --> SIGN[ML-DSA + RSA Potpis]
KEY[Code-Signing ključ] --> SIGN
SIGN --> TS[Dodavanje vremenske oznake]
TSA[TSA Server] --> TS
TS --> OUTPUT[Potpisana datoteka]
style SIGN fill:#e8f5e9
style TS fill:#fff3e0
Primjer koda: Authenticode potpisivanje
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using System.Security.Cryptography; using var ctx = PqCryptoContext.Initialize(); // Učitavanje Code-Signing certifikata i ključa var codeSignCert = ctx.LoadCertificate("codesign.crt.pem"); var codeSignKey = ctx.LoadPrivateKey("codesign.key.pem", "KeyPassword!"); // Kreiranje Authenticode potpisa var signatureOptions = new AuthenticodeSignatureOptions { Certificate = codeSignCert, PrivateKey = codeSignKey, HashAlgorithm = HashAlgorithmName.SHA256, TimestampUrl = "http://timestamp.digicert.com", TimestampHashAlgorithm = HashAlgorithmName.SHA256, Mode = CryptoMode.Hybrid, Description = "MyApp - Sigurna aplikacija", DescriptionUrl = "https://myapp.example.com" }; // Potpisivanje EXE datoteke var inputPath = "MyApp.exe"; var outputPath = "MyApp-signed.exe"; ctx.SignAuthenticode(inputPath, outputPath, signatureOptions); Console.WriteLine($"Kod potpisan: {outputPath}"); Console.WriteLine($" Potpisnik: {codeSignCert.Subject}"); Console.WriteLine($" Vremenska oznaka: {signatureOptions.TimestampUrl}");
Windows SignTool integracija
public class SignToolWrapper { public void Sign(string filePath, string pfxPath, string password, string timestampUrl) { var process = new Process { StartInfo = new ProcessStartInfo { FileName = "signtool.exe", Arguments = $"sign " + $"/fd SHA256 " + $"/f \"{pfxPath}\" " + $"/p \"{password}\" " + $"/tr \"{timestampUrl}\" " + $"/td SHA256 " + $"/d \"Signed with PQ-Crypto\" " + $"\"{filePath}\"", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false } }; process.Start(); process.WaitForExit(); if (process.ExitCode != 0) { var error = process.StandardError.ReadToEnd(); throw new InvalidOperationException($"SignTool nije uspio: {error}"); } Console.WriteLine($"Potpisano: {filePath}"); } public bool Verify(string filePath) { var process = new Process { StartInfo = new ProcessStartInfo { FileName = "signtool.exe", Arguments = $"verify /pa /v \"{filePath}\"", RedirectStandardOutput = true, UseShellExecute = false } }; process.Start(); process.WaitForExit(); return process.ExitCode == 0; } }
Potpisivanje PowerShell skripte
public class PowerShellSigner { public void SignScript(string scriptPath, X509Certificate2 cert) { // Dodavanje PowerShell CMS potpisa var scriptContent = File.ReadAllText(scriptPath); // Kreiranje bloka potpisa var signatureBlock = CreatePowerShellSignature(scriptContent, cert); // Dodavanje potpisa skripti var signedContent = scriptContent + Environment.NewLine + signatureBlock; File.WriteAllText(scriptPath, signedContent); Console.WriteLine($"PowerShell skripta potpisana: {scriptPath}"); } private string CreatePowerShellSignature(string content, X509Certificate2 cert) { using var ctx = PqCryptoContext.Initialize(); // Hash skripte var hash = SHA256.HashData(Encoding.UTF8.GetBytes(content)); // CMS potpis var contentInfo = new ContentInfo(hash); var signedCms = new SignedCms(contentInfo, true); var signer = new CmsSigner(cert); signedCms.ComputeSignature(signer); // Base64-kodirani blok potpisa var signatureBase64 = Convert.ToBase64String(signedCms.Encode()); return $@" # SIG # Begin signature block # {signatureBase64} # SIG # End signature block"; } }
Potpisivanje NuGet paketa
public class NuGetSigner { public async Task SignPackage( string packagePath, X509Certificate2 cert, AsymmetricAlgorithm privateKey, string timestampUrl) { using var ctx = PqCryptoContext.Initialize(); // Otvaranje NuGet paketa using var package = new ZipArchive(File.Open(packagePath, FileMode.Open), ZipArchiveMode.Update); // Kreiranje .signature.p7s var signatureEntry = package.CreateEntry(".signature.p7s"); // Izračun hasha paketa (bez unosa potpisa) var packageHash = ComputePackageHash(package); // CMS potpis var contentInfo = new ContentInfo(packageHash); var signedCms = new SignedCms(contentInfo, true); var signer = new CmsSigner(cert) { DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1"), IncludeOption = X509IncludeOption.WholeChain }; signedCms.ComputeSignature(signer, mode: CryptoMode.Hybrid); // Dodavanje vremenske oznake await AddTimestamp(signedCms, timestampUrl); // Pisanje potpisa using var signatureStream = signatureEntry.Open(); signatureStream.Write(signedCms.Encode()); Console.WriteLine($"NuGet paket potpisan: {packagePath}"); } }
Dual-Signature (Legacy + PQ)
Za prijelazno razdoblje: Oba potpisa paralelno
public class DualSignature { public void SignWithDualSignature(string exePath, SigningCredentials credentials) { using var ctx = PqCryptoContext.Initialize(); // 1. Prvi potpis: SHA-1 (za Windows XP/Vista kompatibilnost) ctx.SignAuthenticode(exePath, exePath, new AuthenticodeSignatureOptions { Certificate = credentials.LegacyCert, PrivateKey = credentials.LegacyKey, HashAlgorithm = HashAlgorithmName.SHA1, TimestampUrl = credentials.TimestampUrl, AppendSignature = false // Prvi potpis }); // 2. Drugi potpis: SHA-256 + PQ (za moderne sustave) ctx.SignAuthenticode(exePath, exePath, new AuthenticodeSignatureOptions { Certificate = credentials.PqCert, PrivateKey = credentials.PqKey, HashAlgorithm = HashAlgorithmName.SHA256, Mode = CryptoMode.Hybrid, TimestampUrl = credentials.TimestampUrl, AppendSignature = true // Dodavanje drugog potpisa }); Console.WriteLine("Dual-Signature kreiran (SHA-1 + SHA-256/PQ)"); } }
Timestamp serveri
| Pružatelj | URL | Protokol |
|---|---|---|
| DigiCert | http://timestamp.digicert.com | RFC 3161 |
| Sectigo | http://timestamp.sectigo.com | RFC 3161 |
| GlobalSign | http://timestamp.globalsign.com | RFC 3161 |
| SSL.com | http://ts.ssl.com | RFC 3161 |
VAŽNO: Bez vremenske oznake potpis postaje nevaljan nakon isteka certifikata!
Zahtjevi specifični za industriju
| Industrija | Standard | Zahtjevi |
|---|---|---|
| Windows | Authenticode | EV certifikat za SmartScreen |
| Automobilska | UNECE R156 | Firmware potpisivanje, HSM |
| Zdravstvo | DiGAV | Kvalificirani potpis |
| Industrija | IEC 62443 | SPS-Firmware |
Povezani scenariji
| Povezanost | Scenarij | Opis |
|---|---|---|
| Preduvjet | 3.3 Code-Signing Cert | Kreiranje certifikata |
| Važno | 8.3 Vremenska oznaka | Dugoročna valjanost |
| Povezano | 8.4 Verifikacija potpisa | Provjera |
« ← 8.1 Potpisivanje dokumenata | ↑ Pregled potpisa | 8.3 Vremenska oznaka → »
Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional
Zuletzt geändert: 30.01.2026. u 00:34