Files
EnvelopeGenerator/EnvelopeGenerator.Infrastructure.Crypt
TekH 04cea1ca4b Refactor to use streams for PDF handling
Refactored `IPdfDigitalSignatureService` to replace `byte[]` with `Stream` for input and output, improving memory efficiency and scalability. Updated `PdfDigitalSignatureService` implementation to support stream-based operations, including signing, checking, and extracting PDFs.

Modified `SignPdfAsync` to handle multiple signatures sequentially using streams and ensured proper disposal of intermediate streams. Updated `CheckPdfSignatureAsync` and `ExtractOriginalPdfAsync` to use streams, reducing memory overhead.

Refactored `PdfSignatureController` to use streams for file handling, enabling efficient processing of large files. Introduced helper methods for stream handling and enhanced cancellation support. Improved code maintainability by consolidating common logic and reducing duplication.
2026-10-15 11:04:05 +02:00
..

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):

sudo apt-get update && sudo apt-get install -y softhsm2 opensc p11-kit libengine-pkcs11-openssl

2.2 SoftHSM-Modulpfad pruefen

ldconfig -p | grep softhsm
find /usr -name "libsofthsm2.so" 2>/dev/null

2.3 Token initialisieren

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

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

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

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:

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:

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:

{
  "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, Email, Phone, 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:

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:

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.
  • SigningTime ist rein serverseitig und wird automatisch gesetzt (UseUtcSigningTime=true => UtcNow, sonst lokale Zeit).
  • 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/