The README.md has been extensively restructured to improve clarity, technical depth, and usability. Key changes include: - Shifted most sections from English to German for localization. - Consolidated distributed runbooks into a unified reference for PKCS#11/SoftHSM integration. - Expanded architecture overview with deployment patterns and runtime paths. - Replaced PKCS#11 basics with detailed setup instructions and troubleshooting tips. - Updated runtime configuration examples with security best practices. - Highlighted implemented services, models, and DTOs in the DI setup. - Added sections on operational challenges, troubleshooting, and monitoring. - Introduced an API health endpoint and smoke test recommendations. - Clarified API behavior for signature metadata to ensure deterministic integration. - Expanded security guidelines, including key rotation and SSH rollback procedures. - Added a forward-looking section on potential improvements. - Retained and updated references to official documentation and tools. These changes aim to provide a comprehensive, structured, and production-aligned guide for developers and engineers.
384 lines
12 KiB
Markdown
384 lines
12 KiB
Markdown
# EnvelopeGenerator.Infrastructure.Crypt
|
|
|
|
Umfassende technische Dokumentation der PKCS#11/SoftHSM-Integration fuer `EnvelopeGenerator`.
|
|
|
|
Dieses Dokument konsolidiert und ersetzt die verteilten Runbooks aus:
|
|
|
|
- `pkcs11-proxy-production/README.md`
|
|
- `pkcs11-proxy-production/SSH_TEMP_ACCESS_MUST_DO.md`
|
|
- aeltere Abschnitte in diesem README
|
|
|
|
Zielgruppe: Senior Developer, Platform Engineers, DevOps, Security Owner.
|
|
|
|
---
|
|
|
|
## 1. Architekturueberblick
|
|
|
|
### 1.1 Ziel
|
|
|
|
`EnvelopeGenerator.Infrastructure.Crypt` stellt die kryptographische Infrastruktur fuer PDF-Signaturen bereit:
|
|
|
|
- Signaturerzeugung mit Schluesseln in SoftHSM/PKCS#11
|
|
- Zertifikat-Auslese aus Token
|
|
- Signaturpruefung auf PDF-Ebene
|
|
- Health/Startup-Selbsttest fuer Betriebsfaehigkeit
|
|
|
|
### 1.2 Topologie (aktueller Betriebsmodus)
|
|
|
|
Der aktuell implementierte Produktions-nahe Pfad ist:
|
|
|
|
1. Linux hostet SoftHSM + `pkcs11-daemon` (Proxy-Server).
|
|
2. Windows hostet `EnvelopeGenerator.Server`.
|
|
3. Windows laedt ein Windows-kompatibles Proxy-PKCS#11-Modul (`libpkcs11-proxy.dll`).
|
|
4. PKCS#11-Operationen werden ueber Socket (`PKCS11_PROXY_SOCKET`) an Linux weitergeleitet.
|
|
|
|
Wichtig:
|
|
|
|
- Ein Windows-Prozess kann **kein Linux `.so`** direkt laden.
|
|
- Private Keys verbleiben im Token (nicht exportierbar).
|
|
|
|
### 1.3 Laufzeitpfade in der Anwendung
|
|
|
|
`Pkcs11InteropBootstrap` loest Assets relativ zu `Crypt:Pkcs11:AssetsRootPath` auf:
|
|
|
|
- Modul: `pkcs11\windows\proxy\libpkcs11-proxy.dll`
|
|
- Tool-Fallback: `pkcs11\windows\opensc\tools\pkcs11-tool.exe`
|
|
|
|
Wenn `AssetsRootPath` leer ist, wird `AppContext.BaseDirectory` verwendet.
|
|
|
|
---
|
|
|
|
## 2. Linux-Seite: SoftHSM + Proxy Setup
|
|
|
|
### 2.1 Basispakete
|
|
|
|
Beispiel (Debian/Ubuntu):
|
|
|
|
```bash
|
|
sudo apt-get update && sudo apt-get install -y softhsm2 opensc p11-kit libengine-pkcs11-openssl
|
|
```
|
|
|
|
### 2.2 SoftHSM-Modulpfad pruefen
|
|
|
|
```bash
|
|
ldconfig -p | grep softhsm
|
|
find /usr -name "libsofthsm2.so" 2>/dev/null
|
|
```
|
|
|
|
### 2.3 Token initialisieren
|
|
|
|
```bash
|
|
softhsm2-util --show-slots
|
|
softhsm2-util --init-token --slot <uninitialized-slot> --label CompanyProdToken --so-pin <so-pin> --pin <user-pin>
|
|
softhsm2-util --show-slots
|
|
```
|
|
|
|
Hinweis: Nach `--init-token` wird der Slot i. d. R. neu zugewiesen.
|
|
|
|
### 2.4 Schluesselpaar erzeugen
|
|
|
|
```bash
|
|
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so \
|
|
--slot <slot-id> --login --pin <user-pin> \
|
|
--keypairgen --key-type rsa:3072 --label company-sign-key-v1 --id 01
|
|
```
|
|
|
|
### 2.5 Zertifikat importieren
|
|
|
|
```bash
|
|
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so \
|
|
--slot <slot-id> --login --pin <user-pin> \
|
|
--write-object ./company-sign-cert-v1.der --type cert --id 01 --label company-sign-cert-v1
|
|
```
|
|
|
|
### 2.6 Objektzustand verifizieren
|
|
|
|
```bash
|
|
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot <slot-id> --login --pin <user-pin> --list-objects
|
|
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot <slot-id> --login --pin <user-pin> --list-objects --type cert
|
|
```
|
|
|
|
### 2.7 Proxy-Daemon endpoint stabilisieren
|
|
|
|
Ein wiederkehrendes Betriebsproblem war ein zufaelliger/local-only Listener. Fix:
|
|
|
|
```bash
|
|
sudo mkdir -p /etc/systemd/system/pkcs11-proxy.service.d
|
|
printf "[Service]\nEnvironment=PKCS11_DAEMON_SOCKET=tcp://0.0.0.0:5657\n" | sudo tee /etc/systemd/system/pkcs11-proxy.service.d/override.conf
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl restart pkcs11-proxy.service
|
|
```
|
|
|
|
Pruefung:
|
|
|
|
```bash
|
|
systemctl show pkcs11-proxy.service -p Environment --no-pager
|
|
ss -ltnp | grep 5657
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Web-API/Server-Seite: Installation und Asset-Bereitstellung
|
|
|
|
### 3.1 Bezugsquellen der Windows-Artefakte
|
|
|
|
Fuer den Proxy-Betrieb werden auf Windows benoetigt:
|
|
|
|
1. Proxy-PKCS#11-DLL (`libpkcs11-proxy.dll`)
|
|
2. Abhaengige Runtime-DLLs (z. B. MinGW runtime, je nach Build)
|
|
3. `pkcs11-tool.exe` + zugehoerige OpenSC-DLLs fuer Fallback
|
|
|
|
Beschaffung:
|
|
|
|
- Build aus derselben `pkcs11-proxy`-Codebasis/Commit wie Linux-Daemon (Kompatibilitaet sicherstellen)
|
|
- oder kontrolliert bereitgestellte, intern freigegebene Binaries
|
|
|
|
### 3.2 Empfohlene Ablage im Repo
|
|
|
|
Bundled Assets liegen unter:
|
|
|
|
- `EnvelopeGenerator.Infrastructure.Crypt/resources/pkcs11/windows/proxy/`
|
|
- `EnvelopeGenerator.Infrastructure.Crypt/resources/pkcs11/windows/opensc/tools/`
|
|
- `EnvelopeGenerator.Infrastructure.Crypt/resources/pkcs11/windows/opensc/pkcs11/`
|
|
|
|
Diese werden beim Build in den Output kopiert (siehe `.csproj`-Copy-Regeln).
|
|
|
|
### 3.3 Deployment-Muster
|
|
|
|
Es gibt zwei gueltige Wege:
|
|
|
|
1. **Bundled (Dev/QA, schnelle Reproduzierbarkeit)**
|
|
- Assets werden mit dem Build ausgeliefert.
|
|
- `AssetsRootPath = null` -> Aufloesung via `AppContext.BaseDirectory`.
|
|
|
|
2. **Zentraler Asset-Root (Prod, betriebliche Kontrolle)**
|
|
- Assets in zentralem Pfad (z. B. `E:\DataFiles\Digital Data\EnvelopeGenerator`).
|
|
- `AssetsRootPath` in `appsettings.json` auf diesen Root setzen.
|
|
|
|
### 3.4 Anwendungskonfiguration (`Crypt:Pkcs11`)
|
|
|
|
Beispiel:
|
|
|
|
```json
|
|
{
|
|
"Crypt": {
|
|
"Pkcs11": {
|
|
"AssetsRootPath": "E:\\DataFiles\\Digital Data\\EnvelopeGenerator",
|
|
"SlotId": 2021549410,
|
|
"TokenLabel": "CompanyProdToken",
|
|
"ProxySocket": "tcp://172.24.12.64:5657",
|
|
"UserPin": "<secret>",
|
|
"PrivateKeyLabel": "company-sign-key-v1",
|
|
"CertificateLabel": "company-sign-cert-v1",
|
|
"ApplicationName": "signFLOW",
|
|
"DefaultReason": null,
|
|
"UseUtcSigningTime": true,
|
|
"DefaultCertificationLevel": "NoCertification"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Sicherheitsregel:
|
|
|
|
- `UserPin` niemals in versionierte Dateien einchecken.
|
|
- Secrets nur in Secret Store / nicht versionierte `appsettings.Secrets.json` / Vault.
|
|
|
|
---
|
|
|
|
## 4. Implementierte Services, Modelle, DTOs
|
|
|
|
### 4.1 DI und Startverhalten
|
|
|
|
- `AddCryptInfrastructure(...)` in `DependencyInjection/ServiceCollectionExtensions.cs`
|
|
- bindet `Pkcs11Options`
|
|
- registriert `IPdfDigitalSignatureService`
|
|
- registriert Startup-Self-Test Hosted Service
|
|
|
|
### 4.2 Konfigurationsmodell
|
|
|
|
- `Pkcs11Options` (`EnvelopeGenerator.Application/Common/Configurations/Pkcs11Options.cs`)
|
|
- `AssetsRootPath`, `SlotId`, `TokenLabel`, `ProxySocket`
|
|
- `UserPin`, `PrivateKeyLabel`, `CertificateLabel`
|
|
- `ApplicationName`, `DefaultReason`, `UseUtcSigningTime`, `DefaultCertificationLevel`
|
|
- `ResolvedLibraryPath`, `ResolvedToolPath` (Runtime-resolved)
|
|
|
|
### 4.3 Kernservices
|
|
|
|
1. `PdfDigitalSignatureService`
|
|
- Signiert PDF via DevExpress `PdfDeferredSignatureBuilder`
|
|
- Nutzt `Pkcs11ExternalSigner` fuer externe Signatur
|
|
- Erzwingt `ApplicationName` aus Config (nicht client-overridable)
|
|
- Erweitert `Reason` um strukturiertes Metaformat:
|
|
- `SFMETA:v1;doc=<uuid>;sha256=<hash>`
|
|
- Parse beim Verify und Mapping in DTO
|
|
|
|
2. `Pkcs11InteropBootstrap`
|
|
- Loest Modul-/Toolpfade auf
|
|
- Setzt `PKCS11_PROXY_SOCKET`/`PKCS11_DAEMON_SOCKET`
|
|
- PATH-Ergaenzung fuer native Abhaengigkeiten
|
|
- Warmup via `pkcs11-tool -L`
|
|
|
|
3. `Pkcs11SessionRunner`
|
|
- Interop Library-Load mit mehreren Init-Modi (Fallback-Reihenfolge)
|
|
- Slot-Resolution (`SlotId`/`TokenLabel`)
|
|
- Session Login/Logout
|
|
|
|
4. `Pkcs11ToolBridge`
|
|
- Fallback via Prozessaufruf von `pkcs11-tool`
|
|
- Cert read und DigestInfo-Signatur
|
|
|
|
5. `Pkcs11StartupSelfTestHostedService`
|
|
- Fuehrt beim Start Interop-Probe aus
|
|
- Fallback-Probe bei Interop-Fehler
|
|
- Schreibt strukturierten Status
|
|
|
|
### 4.4 Wichtige Interfaces/DTOs
|
|
|
|
- `IPdfDigitalSignatureService`
|
|
- `SignPdfAsync(...)`, `CheckPdfSignatureAsync(...)`, `ExtractOriginalPdfAsync(...)`
|
|
- `IPkcs11SelfTestStatusProvider`
|
|
- `PdfSignOptionsDto`
|
|
- `UUID`, `Reason`, `Name`, `Location`, `ContactInfo`, `SigningTime`, `CertificationLevel`
|
|
- `PdfSignatureCheckResultDto` / `PdfSignatureCheckItemDto`
|
|
- inklusive `BusinessReason`, `UUID`, `OriginalDocumentSha256`
|
|
- `Pkcs11SelfTestStatusDto`
|
|
|
|
---
|
|
|
|
## 5. Betriebserfahrungen und Challenges
|
|
|
|
### 5.1 Interop vs Tool-Verhalten
|
|
|
|
Beobachtetes Muster in der realen Umgebung:
|
|
|
|
- `pkcs11-tool` konnte erfolgreich auf Token zugreifen und signieren.
|
|
- `Pkcs11Interop` scheiterte mit `CKR_FUNCTION_NOT_SUPPORTED` bzw. fehlendem `C_Initialize` Pointer in bestimmten Modi.
|
|
|
|
Konsequenz:
|
|
|
|
- Architektur wurde auf **interop-first + controlled tool-fallback** erweitert.
|
|
- Health-Endpunkt differenziert Modus (`interop`, `pkcs11-tool`, `failed`).
|
|
|
|
### 5.2 Typische Fehlbilder
|
|
|
|
- `CKR_DEVICE_ERROR` bei Socket-/Proxy-Problemen
|
|
- `CRYPT_PROVIDER_UNAVAILABLE` bei Pfad/ABI/Dependency-Mismatch
|
|
- `CRYPT_SLOT_NOT_FOUND` bei Slot-/Label-Mismatch
|
|
- `CKR_PIN_INCORRECT` bei PIN-Fehler
|
|
- 307 Redirects bei HTTP/HTTPS-Mix in manuellen Tests
|
|
|
|
### 5.3 Plattformfallen
|
|
|
|
- MSVC vs MinGW Build-Unterschiede fuer Proxy-Client
|
|
- fehlende Laufzeit-DLLs (`PATH`/Side-by-side)
|
|
- Architektur-Mismatch x86 vs x64
|
|
- Daemon-Bindings nicht stabil (random localhost port statt fixed endpoint)
|
|
|
|
---
|
|
|
|
## 6. Health, Monitoring und Verifikation
|
|
|
|
### 6.1 API Health
|
|
|
|
- Endpoint: `GET /api/health/crypt`
|
|
- Liefert:
|
|
- `success`, `mode`, `summary`, `interopError`, `toolError`, `checkedAtUtc`
|
|
|
|
Empfehlung:
|
|
|
|
- In Monitoring aufnehmen und bei `mode=pkcs11-tool` ueber laengere Zeit Warnung triggern.
|
|
|
|
### 6.2 Smoke-Test (empfohlen vor Release)
|
|
|
|
1. `GET /api/health/crypt` -> `success=true`
|
|
2. `POST /api/PdfSignature/sign` mit Test-PDF
|
|
3. `POST /api/PdfSignature/is-signed`
|
|
4. Pruefen:
|
|
- `signed=true`
|
|
- `allSignaturesCryptographicallyValid=true`
|
|
- `UUID`/`OriginalDocumentSha256` korrekt gemappt
|
|
|
|
---
|
|
|
|
## 7. Sicherheits- und Betriebsrichtlinien
|
|
|
|
### 7.1 Geheimnisse
|
|
|
|
- PIN, SO-PIN, Root-Creds niemals in Doku/Screenshots/Repo.
|
|
- Nach Troubleshooting: Credentials rotieren.
|
|
|
|
### 7.2 Temporare SSH-Freigaben zwingend rueckbauen
|
|
|
|
Wenn SSH temporaer geoeffnet wurde, MUSS danach Rollback erfolgen:
|
|
|
|
```bash
|
|
sudo systemctl disable --now ssh && sudo ufw delete allow from 172.24.10.11 to any port 22 proto tcp && sudo ufw status verbose && sudo systemctl status ssh --no-pager
|
|
```
|
|
|
|
Optional harte Bereinigung:
|
|
|
|
```bash
|
|
sudo apt-get purge -y openssh-server && sudo apt-get autoremove -y
|
|
```
|
|
|
|
### 7.3 Schluesselrotation
|
|
|
|
- Neue Labels (`...-v2`) anlegen
|
|
- App umkonfigurieren
|
|
- Sign/Verify Regression testen
|
|
- Altmaterial erst nach Freigabe entfernen
|
|
|
|
---
|
|
|
|
## 8. API-Verhalten bei Signaturmetadaten
|
|
|
|
Aktueller Standard:
|
|
|
|
- `UUID` kommt aus Sign-Input (nullable string). Wenn ungeltig/leer -> neue Guid wird erzeugt.
|
|
- `Reason` wird intern angereichert mit strukturiertem Meta (`SFMETA:v1`).
|
|
- `ApplicationName` ist rein serverseitig aus `appsettings` gesetzt.
|
|
- `CertificationLevel` wird im Controller serverseitig gesetzt (`FormFillingAndAnnotations`), nicht vom Client.
|
|
|
|
Damit ist das Verhalten deterministisch und manipulationsaermer fuer Integrationsclients.
|
|
|
|
---
|
|
|
|
## 9. Troubleshooting-Checkliste (praxisnah)
|
|
|
|
1. Erreichbarkeit Linux Proxy:
|
|
- `Test-NetConnection <linux-host> -Port 5657`
|
|
2. Token sichtbar?
|
|
- `pkcs11-tool --module <dll> -L -v`
|
|
3. Zertifikat lesbar?
|
|
- `--read-object --type cert --label <cert-label>`
|
|
4. Signatur technisch moeglich?
|
|
- `--sign -m SHA256-RSA-PKCS ...`
|
|
5. App-Health check:
|
|
- `/api/health/crypt`
|
|
6. App-sign/verify end-to-end:
|
|
- `/api/PdfSignature/sign` + `/api/PdfSignature/is-signed`
|
|
|
|
Wenn Interop scheitert, aber Tool funktioniert:
|
|
|
|
- Betrieb bleibt verfuegbar (Fallback),
|
|
- aber Incident/Bug fuer Interop-Kompatibilitaet erfassen.
|
|
|
|
---
|
|
|
|
## 10. Ausblick / empfohlene Verbesserungen
|
|
|
|
1. Binary Transport statt Base64 bei grossen PDFs in Render/Sign-Pipelines.
|
|
2. Persistente Metriken fuer Fallback-Quote (`interop` vs `tool`).
|
|
3. Zertifikatskette/OCSP/CRL Validierung als optionales Policy-Modul.
|
|
4. CI-Pruefung auf unsichere SQL-Muster (parallel zum Security-Workstream).
|
|
5. Standardisierte Toast/UX-Rueckmeldungen fuer Signierfehler in UI.
|
|
|
|
---
|
|
|
|
## 11. Referenzen
|
|
|
|
- SoftHSMv2: `https://github.com/softhsm/SoftHSMv2`
|
|
- OpenSC / pkcs11-tool: `https://github.com/OpenSC/OpenSC/wiki/Using-pkcs11-tool-and-OpenSSL`
|
|
- PKCS#11 Standard: `https://www.oasis-open.org/committees/pkcs11/`
|