Files
EnvelopeGenerator/EnvelopeGenerator.Infrastructure.Crypt
TekH 51c0f51738 Refactor contact info handling in PDF signing
Replaced the `ContactInfo` property with separate `Email` and `Phone` fields in `PdfSignOptionsDto` and `PdfSignatureCheckItemDto` for better granularity. Updated the `PdfDigitalSignatureService` to handle the new fields, introducing `BuildContactInfo` and `ParseContactInfo` methods for constructing and parsing contact information.

Modified the `PdfSignatureController` to reflect these changes, updating request models and the `SignPdfAsync` method. Updated the `README.md` to document the new structure. These changes improve the clarity and structure of contact information handling.
2026-10-14 15:10:55 +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/