Code Signing - Kryptografische Signierung von Software
Code Signing bezeichnet die kryptografische Signierung von Software, Skripten und ausführbaren Dateien mit einem privaten Schlüssel, um Herkunft und Integrität nachzuweisen. Signierte Software beweist wer den Code erstellt hat (Authentizität) und dass er nach der Signierung nicht verändert wurde (Integrität). Einsatz: Windows Authenticode, macOS Gatekeeper, Android APK-Signierung, Kernel-Module, UEFI Secure Boot.
Code Signing ist der Prozess bei dem Software, Skripte und ausführbare Dateien mit einem digitalen Zertifikat signiert werden. Betriebssysteme, App-Stores und Deployment-Systeme nutzen diese Signaturen um sicherzustellen, dass Code von einem vertrauenswürdigen Entwickler stammt und seit der Signierung nicht manipuliert wurde.
Technisches Grundprinzip
Wie Code Signing funktioniert
Auf der Entwicklerseite läuft der Prozess in vier Schritten:
- Code kompilieren →
binary.exe - SHA-256-Hash des Binary berechnen
- Hash mit privatem Schlüssel (RSA/ECC) signieren → Signatur
- Binary + Signatur + Zertifikat als
SignedBinary.exeausliefern
Auf der Empfängerseite (OS/Nutzer) wird dann geprüft:
- Signatur mit öffentlichem Schlüssel des Zertifikats verifizieren
- Hash des empfangenen Binary berechnen
- Hash-Vergleich: stimmt Hash mit signiertem Hash überein?
- Zertifikat-Kette prüfen: vertrauenswürdige CA, nicht abgelaufen, nicht revoziert?
Das Ergebnis ist entweder eine Bestätigung (“Verifizierter Entwickler X”) oder eine Warnung (“Unbekannter Entwickler” in Windows SmartScreen oder “Beschädigte Datei”).
Warum Code Signing allein nicht ausreicht
Der SolarWinds-Angriff 2020 zeigt die Grenzen: Die Angreifer hatten Zugriff auf die Build-Infrastruktur von SolarWinds und lieferten ein signiertes Malware-Update an über 18.000 Kunden aus. Das Zertifikat war vollständig legitim - Sicherheitssysteme vertrauten dem Update bedingungslos. Code Signing muss deshalb durch eine abgesicherte Build-Infrastruktur ergänzt werden.
Windows Authenticode
Zertifikats-Typen
Windows unterscheidet zwei Validierungsstufen:
- OV (Organization Validation): Aussteller prüft die Organisation. SmartScreen-Reputation baut sich schrittweise durch Downloads auf.
- EV (Extended Validation): Strengere Prüfung, Hardware-Token erforderlich. Neue EV-Zertifikate erhalten sofort eine gute SmartScreen-Reputation.
Anbieter sind DigiCert, Sectigo, GlobalSign u.a.
Signier-Prozess (signtool.exe)
# PE-Binary signieren (Authenticode):
signtool sign /fd SHA256 /tr http://timestamp.digicert.com /td SHA256 `
/f zertifikat.pfx /p PASSWORT meinprogramm.exe
# Verifizieren:
signtool verify /pa /v meinprogramm.exe
# Ausgabe: "Successfully verified: meinprogramm.exe"
Timestamping
Wichtig: Ohne Timestamp wird die Signatur ungültig, sobald das Zertifikat abläuft. Mit einem RFC 3161 Timestamp gilt die Signatur als gültig, wenn sie zum Gültigkeitszeitpunkt des Zertifikats erstellt wurde. Timestamping ist kostenlos bei allen CAs und sollte immer genutzt werden.
PowerShell-Skripte signieren
# Execution Policy auf AllSigned setzen für vollständige Code-Signing-Enforcement:
Set-ExecutionPolicy AllSigned -Scope LocalMachine
# Skript signieren:
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert
Set-AuthenticodeSignature -FilePath meinskript.ps1 -Certificate $cert `
-TimestampServer "http://timestamp.digicert.com"
macOS und iOS Signing
Gatekeeper-Stufen
macOS Gatekeeper kennt drei Stufen:
- App Store: Ausschließlich App Store Apps erlaubt
- App Store + bekannte Entwickler: Signierte Apps von Apple Developer Accounts erlaubt (empfohlen)
- Überall: Jede App erlaubt (nicht empfohlen)
Code Signing auf macOS
# macOS App signieren:
codesign --sign "Developer ID Application: MeinFirma GmbH (TEAMID)" \
--timestamp \
--options runtime \
meine.app
# Verifizieren:
codesign --verify --verbose meine.app
spctl --assess -v meine.app
# Inhalt inspizieren:
codesign --display --verbose=4 meine.app
Notarisierung (seit macOS Catalina Pflicht)
# App zu Apple zur automatisierten Malware-Prüfung senden:
xcrun notarytool submit meine.app.zip \
--apple-id developer@firma.de \
--password APP_SPECIFIC_PASSWORD \
--team-id TEAMID \
--wait
# Notarisierungs-Ticket in die App einbetten (Stapling):
xcrun stapler staple meine.app
# → App funktioniert auch offline ohne Apple-Server-Check!
Hardened Runtime
Die Option --options runtime erzwingt verschiedene Sicherheitseinschränkungen: kein JIT ohne Entitlement, keine DYLD-Injection und kein Debugger-Attach ohne Entitlement. Hardened Runtime sollte immer aktiviert werden.
iOS/iPadOS App Signing
Alle iOS-Apps müssen von Apple signiert sein - kein Sideloading außer über TestFlight oder AltStore. Development-Certificates dienen zum Testen auf eigenen Geräten, Distribution-Certificates für App Store oder Enterprise-Verteilung. Provisioning Profiles definieren, welche Geräte die App ausführen dürfen.
Android APK Signing
Android Signing Schemes
| Schema | Ab Android-Version | Besonderheit |
|---|---|---|
| v1 (JAR Signing) | Legacy | Anfällig für JAR-Tricks |
| v2 (APK Signing) | Android 7 | Schützt das gesamte APK |
| v3 (Rotating Keys) | Android 9 | Unterstützt Key-Rotation |
| v4 (Incremental) | Android 11 | Für inkrementelle Updates |
APK signieren (apksigner)
# Keystore erstellen:
keytool -genkeypair -v -keystore release.keystore \
-alias meinapp -keyalg RSA -keysize 4096 -validity 10000
# APK signieren (v2+v3):
apksigner sign \
--ks release.keystore \
--ks-key-alias meinapp \
--out meinapp-release.apk \
meinapp-unsigned.apk
# Verifizieren:
apksigner verify --verbose meinapp-release.apk
Wichtig: Ein verlorener Signing Key bedeutet, dass die App nie wieder mit demselben Key aktualisiert werden kann. Der Play Store bindet App-Updates an den originalen Signing Key. Google Play App Signing bietet ein optionales Backup des Keys an. Für Enterprise-Apps empfiehlt sich ein Hardware Security Module (HSM).
CI/CD und HSM-Integration
Das Problem mit einfachen Ansätzen
Ein Private Key in einer CI/CD-Umgebungsvariablen ist für alle Pipeline-Jobs zugänglich. Bei einem kompromittierten CI-Server wird der Key gestohlen und kann für beliebige Signaturen missbraucht werden.
Sichere Ansätze
1. Hardware Security Module (HSM)
Der Private Key verlässt das HSM niemals. Die Signing-Operation findet im HSM statt. Anbieter: AWS CloudHSM, Azure Dedicated HSM, YubiHSM, Thales.
# PKCS#11-Interface zum HSM:
openssl pkeyutl -sign -pkeyopt digest:sha256 \
-engine pkcs11 -keyform engine \
-key "pkcs11:token=MyToken;object=CodeSignKey" \
-in hash.bin -out signature.bin
2. Signing Service (Code Signing as a Service)
Ein dedizierter interner Service stellt Signaturen aus. Die Pipeline schickt das Binary an den Service, der es signiert und zurückgibt. Ein Audit-Log protokolliert alle Signieranfragen. Anbieter: SignPath.io, DigiCert ONE, Garasign.
3. AWS Signer / Azure Code Signing
Cloud-basiertes Signing ohne lokalen Key, mit IAM-Zugriffssteuerung wer Signaturen anfordern darf.
# GitLab-Beispiel mit AWS Signer:
sign-binary:
stage: sign
script:
- aws signer start-signing-job \
--source 's3Payload={bucketName=build-bucket,key=meinapp.exe}' \
--destination 's3={bucketName=signed-bucket,prefix=signed/}' \
--profile-name MeinSigningProfile
only:
- tags # Nur bei Git-Tags signieren!
Revozierung und Rotation
Wann revozieren?
- Private Key kompromittiert (Server-Einbruch, Key-Leak in Git)
- Mitarbeiter der den Key hatte ist ausgeschieden
- Zertifikat läuft ab (Rotation vor Ablauf durchführen)
Revozierung durchführen
Die CA wird kontaktiert (z.B. DigiCert-Portal) und aktualisiert die Certificate Revocation List (CRL). OCSP-Stapling ermöglicht Apps eine Online-Prüfung des Gültigkeitsstatus.
Problem: Nutzer mit älterer (gecachter) Software prüfen die CRL möglicherweise nicht. Im Offline-Modus prüft Windows beim Start signierter Software ebenfalls keine CRL/OCSP, sodass revozierte Zertifikate akzeptiert werden.
Key-Rotation Best Practices
- Zertifikat-Ablauf im Ticketsystem tracken (90 Tage vor Ablauf erneuern)
- Neues Zertifikat parallel verwenden, damit alte Signaturen gültig bleiben
- Niemals denselben Key für Development und Production verwenden
- Hardware-Token (YubiKey) oder HSM für Production-Keys einsetzen
- Regelmäßige Rotation auch ohne Kompromittierung (jährlich empfohlen)
Signierten Code auf Revozierung prüfen
# Windows:
certutil -verify -urlfetch meinprogramm.exe
# Linux (openssl):
openssl ocsp -issuer issuer.pem -cert signing-cert.pem \
-url http://ocsp.digicert.com -text