Code Signing
„Vertraue niemandem – außer dem, der unterschrieben hat. Und selbst dann..."
Sinn & Zweck
Code Signing ist die digitale Unterschrift für Software. Es beantwortet zwei fundamentale Fragen:
- Authentizität: Wer hat diese Software erstellt?
- Integrität: Wurde sie seit der Erstellung verändert?
Ohne Code Signing kann jeder behaupten, Software von "Microsoft" oder "Google" zu verteilen. Mit Code Signing gibt es einen kryptografischen Beweis für die Herkunft und Unversehrtheit.
Wie es funktioniert
Der Signing-Prozess
┌─────────────────────────────────────────────────────────────────┐
│ Entwickler │
│ ┌─────────────┐ │
│ │ Software │ │
│ │ (Binary) │ │
│ └──────┬──────┘ │
│ │ │
│ ↓ Hash (SHA-256) │
│ ┌─────────────┐ ┌──────────────┐ │
│ │ Hash │────→│ Private Key │ │
│ │ (Digest) │ │ (geheim!) │ │
│ └─────────────┘ └──────┬───────┘ │
│ │ Sign │
│ ↓ │
│ ┌─────────────┐ │
│ │ Signatur │ │
│ └──────┬──────┘ │
│ │ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Signierte Software │ │
│ │ Binary + Signatur + Zertifikat (Public Key) │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Die Verifikation
┌─────────────────────────────────────────────────────────────────┐
│ Endnutzer │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Signierte Software │ │
│ └───────────────────────┬──────────────────────────────────┘ │
│ │ │
│ ┌───────────┴───────────┐ │
│ ↓ ↓ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Binary │ │ Signatur │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ Hash │ Decrypt (Public Key) │
│ ↓ ↓ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Hash A │ ==? │ Hash B │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ └───────────┬───────────┘ │
│ ↓ │
│ Match? ✓ Valid │
│ No Match? ✗ Tampered! │
└─────────────────────────────────────────────────────────────────┘
Arten von Code Signing
Authenticode (Windows)
Für Windows-Executables, DLLs, Treiber, PowerShell-Skripte.
# Signieren mit signtool
signtool sign /f certificate.pfx /p password /tr http://timestamp.digicert.com /td sha256 /fd sha256 myapp.exe
# Verifizieren
signtool verify /pa myapp.exe
macOS Code Signing
Für Apps, Installer, Kernel Extensions.
# Signieren
codesign --sign "Developer ID Application: My Company" --timestamp myapp.app
# Notarisierung (für Gatekeeper)
xcrun notarytool submit myapp.zip --apple-id "dev@example.com" --team-id ABC123
# Verifizieren
codesign --verify --verbose myapp.app
spctl --assess --verbose myapp.app
JAR Signing (Java)
# Keystore erstellen
keytool -genkeypair -alias mykey -keyalg RSA -keysize 2048 -keystore keystore.jks
# JAR signieren
jarsigner -keystore keystore.jks -tsa http://timestamp.digicert.com myapp.jar mykey
# Verifizieren
jarsigner -verify -verbose myapp.jar
GPG/PGP Signing
Für Open-Source-Software, Git Commits, Packages.
# Datei signieren
gpg --detach-sign --armor myfile.tar.gz
# Erzeugt: myfile.tar.gz.asc
# Verifizieren
gpg --verify myfile.tar.gz.asc myfile.tar.gz
Container Image Signing
Mit Cosign (Sigstore):
# Image signieren
cosign sign --key cosign.key registry.example.com/myapp:v1.0.0
# Verifizieren
cosign verify --key cosign.pub registry.example.com/myapp:v1.0.0
Zertifikate & PKI
Zertifikatshierarchie
┌─────────────────────────────────────┐
│ Root CA (Offline) │
│ DigiCert, Sectigo, GlobalSign │
└─────────────────┬───────────────────┘
│ Signs
↓
┌─────────────────────────────────────┐
│ Intermediate CA │
│ (mehrere Ebenen möglich) │
└─────────────────┬───────────────────┘
│ Signs
↓
┌─────────────────────────────────────┐
│ End-Entity Certificate │
│ "My Company" Code Signing Cert │
└─────────────────────────────────────┘
Zertifikatstypen
| Typ | Validierung | Vertrauen | Preis |
|---|---|---|---|
| OV (Organization Validation) | Organisation geprüft | Mittel | €€ |
| EV (Extended Validation) | Umfassende Prüfung | Hoch | €€€ |
| Self-Signed | Keine | Keins (extern) | Kostenlos |
EV-Zertifikate:
- Strenge Identitätsprüfung
- Höheres Vertrauen bei Windows SmartScreen
- Erforderlich für Kernel-Treiber (Windows)
HSM (Hardware Security Module)
Für maximale Sicherheit: Private Keys in Hardware.
┌─────────────────────────────────────────────┐
│ HSM (Tamper-proof) │
│ ┌─────────────────────────────────────┐ │
│ │ Private Key │ │
│ │ (verlässt HSM nie!) │ │
│ └─────────────────────────────────────┘ │
│ ↑ │
│ │ API Call: "Sign this" │
│ │ │
│ ┌─────────────────────────────────────┐ │
│ │ Signing Operations │ │
│ │ (passiert komplett im HSM) │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
Timestamping
Warum?
Zertifikate laufen ab. Ohne Timestamp ist die Signatur nach Ablauf ungültig.
Mit Timestamp:
"Diese Software wurde am 2024-01-15 signiert,
als das Zertifikat noch gültig war."
Wie?
# SignTool mit Timestamp
signtool sign /tr http://timestamp.digicert.com /td sha256 myapp.exe
# Jarsigner mit Timestamp
jarsigner -tsa http://timestamp.digicert.com myapp.jar mykey
RFC 3161 Timestamp Server
Kostenlose Optionen:
CI/CD Integration
GitHub Actions
name: Build and Sign
on: [push]
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: Build
run: dotnet build -c Release
- name: Sign
env:
CERTIFICATE: ${{ secrets.CODE_SIGNING_CERT }}
PASSWORD: ${{ secrets.CERT_PASSWORD }}
run: |
# Zertifikat aus Secret dekodieren
echo "$CERTIFICATE" | base64 -d > cert.pfx
# Signieren
signtool sign /f cert.pfx /p "$PASSWORD" /tr http://timestamp.digicert.com /td sha256 /fd sha256 bin/Release/myapp.exe
# Aufräumen
rm cert.pfx
Azure DevOps mit Azure Key Vault
- task: AzureKeyVault@2
inputs:
azureSubscription: 'My Subscription'
KeyVaultName: 'my-keyvault'
SecretsFilter: 'code-signing-cert'
- task: DotNetCoreCLI@2
inputs:
command: 'build'
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
$cert = Get-AzKeyVaultCertificate -VaultName "my-keyvault" -Name "code-signing-cert"
# Sign using Azure SignTool or similar
Sigstore (Keyless Signing)
Keine langlebigen Keys nötig – Identity-basiert:
# Keyless Signing mit OIDC
cosign sign --oidc-issuer https://accounts.google.com myapp.tar.gz
# Verifiziert gegen OIDC-Identität
cosign verify --certificate-identity dev@example.com --certificate-oidc-issuer https://accounts.google.com myapp.tar.gz
Risiken & Angriffe
Gestohlene Private Keys
Beispiele:
- Stuxnet (gestohlene Realtek/JMicron Zertifikate)
- SolarWinds (kompromittierter Build-Prozess)
- ASUS Live Update (2019)
Mitigationen
- HSM nutzen – Keys verlassen nie die Hardware
- Access Control – Wer kann signieren?
- Audit Logging – Jede Signatur protokollieren
- Short-lived Certificates – Weniger Zeit für Angreifer
- Multi-Person Signing – Separation of Duties
Zertifikatsmissbrauch erkennen
# Certificate Transparency Monitoring
# Überwache, ob jemand Zertifikate für deine Domain beantragt
# Tools:
# - crt.sh
# - Facebook CT Monitor
# - SSLMate Cert Spotter
Best Practices
1. Private Keys schützen
Schlecht: Private Key auf Developer-Laptop
Besser: Private Key auf Build-Server (verschlüsselt)
Am besten: Private Key in HSM
2. Separation of Duties
Developer: Kann Code schreiben
QA: Kann Code testen
Release: Kann signieren
Niemand: Alles alleine
3. Audit Trail
{
"timestamp": "2024-01-15T10:23:45Z",
"action": "sign",
"artifact": "myapp-v1.2.3.exe",
"hash": "sha256:abc123...",
"signer": "release-bot@company.com",
"certificate": "CN=My Company, O=My Company Inc",
"build_id": "build-12345"
}
4. Revocation planen
Was passiert, wenn der Key kompromittiert wird?
- Wie schnell kann das Zertifikat widerrufen werden?
- Wie werden Nutzer informiert?
- Wie werden betroffene Versionen identifiziert?
5. Timestamping immer nutzen
# Immer mit Timestamp signieren!
signtool sign /tr http://timestamp.digicert.com ...
Plattform-spezifische Anforderungen
Windows
| Szenario | Anforderung |
|---|---|
| User-Mode Apps | OV oder EV Zertifikat |
| SmartScreen Trust | EV Zertifikat (schneller) |
| Kernel-Treiber | EV Zertifikat + Microsoft Signatur |
| UEFI Bootloader | Microsoft-Signatur |
macOS
| Szenario | Anforderung |
|---|---|
| App Store | Apple Developer ID + App Review |
| Direct Distribution | Developer ID + Notarization |
| Kernel Extensions | Apple approval + Notarization |
Linux
| Szenario | Anforderung |
|---|---|
| Distro Packages | Distro GPG Key |
| Secure Boot | MOK oder Distro Key |
| Custom Packages | Eigener GPG Key |
Tools & Infrastruktur
Signing-Services
| Service | Typ | Kosten |
|---|---|---|
| DigiCert ONE | Cloud HSM | Enterprise |
| Azure Key Vault | Cloud HSM | Pay-per-use |
| AWS CloudHSM | Dedicated HSM | $$$ |
| Sigstore | Keyless | Free |
| SignPath | SaaS | Subscription |
Lokale Tools
# Windows
signtool.exe (Windows SDK)
# macOS
codesign, notarytool, spctl
# Java
jarsigner, keytool
# Allgemein
gpg, cosign, openssl
Vorteile
Vertrauen
Nutzer wissen, dass die Software wirklich von dir kommt.
Integrität
Manipulation wird sofort erkannt.
Compliance
Viele Anforderungen verlangen signierte Software:
- PCI-DSS
- HIPAA
- Government Standards
Reputation
SmartScreen und Gatekeeper vertrauen signierter Software schneller.
Supply Chain Security
Code Signing ist ein Baustein gegen Supply-Chain-Angriffe.
Fazit
Code Signing ist wie ein Wachssiegel auf einem Brief: Es beweist, von wem er kommt und dass er nicht geöffnet wurde. In einer Welt voller Malware und Supply-Chain-Angriffe ist es keine Option mehr – es ist Pflicht.
Ein unsigniertes Binary ist wie ein anonymer Brief: Niemand weiß, ob man ihm trauen kann.
Weiterführende Ressourcen: