Refactor README.md with localized and detailed guidance

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.
This commit is contained in:
2026-10-14 14:47:40 +02:00
parent 6b3622b366
commit 5194d638ac

View File

@@ -1,391 +1,383 @@
# EnvelopeGenerator.Infrastructure.Crypt
PKCS#11-based cryptographic infrastructure for FES (Advanced Electronic Signature) workflows.
Umfassende technische Dokumentation der PKCS#11/SoftHSM-Integration fuer `EnvelopeGenerator`.
Official references:
Dieses Dokument konsolidiert und ersetzt die verteilten Runbooks aus:
- SoftHSMv2 (official): `https://github.com/softhsm/SoftHSMv2`
- OpenSC `pkcs11-tool` docs: `https://github.com/OpenSC/OpenSC/wiki/Using-pkcs11-tool-and-OpenSSL`
- PKCS#11 standard overview (OASIS): `https://www.oasis-open.org/committees/pkcs11/`
- `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) Scope
## 1. Architekturueberblick
This project is the crypto layer only.
### 1.1 Ziel
- Signs hashes via keys in HSM/SoftHSM.
- Reads certificates from HSM/SoftHSM.
- Verifies signatures.
- Exposes abstractions for Application/Server integration.
`EnvelopeGenerator.Infrastructure.Crypt` stellt die kryptographische Infrastruktur fuer PDF-Signaturen bereit:
This project is not:
- Signaturerzeugung mit Schluesseln in SoftHSM/PKCS#11
- Zertifikat-Auslese aus Token
- Signaturpruefung auf PDF-Ebene
- Health/Startup-Selbsttest fuer Betriebsfaehigkeit
- a REST API,
- a UI module,
- a full document orchestration workflow.
### 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) SoftHSM and PKCS#11 basics
## 2. Linux-Seite: SoftHSM + Proxy Setup
- SoftHSM is a software implementation of an HSM.
- It does not expose REST endpoints.
- Access is via PKCS#11 shared library (`.so`/`.dll`).
- App loads module path and performs PKCS#11 operations.
### 2.1 Basispakete
Supported deployment patterns:
Beispiel (Debian/Ubuntu):
1. Direct module (`libsofthsm2.so`, `softhsm2-x64.dll`, etc.)
2. PKCS#11 proxy module (remote HSM/SoftHSM backend)
Critical platform rule:
- A Windows process cannot load a Linux `.so` directly.
- `Crypt:Pkcs11:AssetsRootPath` must resolve to a directory that contains the expected native assets for the host OS.
- If `AssetsRootPath` is empty, runtime resolves assets from `AppContext.BaseDirectory`.
---
## 2.1) Windows Server + Linux SoftHSM architecture (decision TODO)
Current business requirement: `EnvelopeGenerator.Server` runs on Windows, SoftHSM runs on Linux.
This repository must use one of the following three paths:
1. Linux signing service (recommended)
- Windows `EnvelopeGenerator.Server` calls HTTPS signing API.
- Linux service performs PKCS#11 operations against SoftHSM.
- Private keys stay on Linux.
2. PKCS#11 proxy bridge
- Windows app loads a Windows PKCS#11 proxy client DLL.
- Proxy forwards operations to Linux-side PKCS#11 endpoint connected to SoftHSM.
3. Local Windows SoftHSM (dev/test only, optional)
- SoftHSM is also installed on Windows.
- App talks to local Windows PKCS#11 module.
TODO - architecture lock-in:
- [ ] Select one path as production standard (`1` is recommended).
- [ ] Document final runtime topology (hosts, ports, TLS, auth).
- [ ] Define where audit metadata (IP/email/phone/device) is stored and signed/linked.
- [ ] Update `SignatureController.Submit` integration contract for FES branch.
- [ ] Add environment-specific runbook for Windows host + Linux HSM operations.
---
## 3) FES flow mapping
- Step 6: hash is sent to HSM signing operation -> `ISignatureProvider`
- Step 7: signature and certificate context are resolved -> `Pkcs11SignatureProvider`, `ICertificateProvider`
- Step 8: PDF embedding + audit trail are completed by upper layers; this project provides crypto primitives
---
## 4) Service surface
Main interfaces:
- `ISignatureProvider`
- `ICertificateProvider`
- `ISignatureVerifier`
- `ICryptographicHealthCheck`
DI entry point:
- `CryptDependencyInjection.AddCryptInfrastructure(...)`
---
## 5) Runtime configuration
Configuration section: `Crypt:Pkcs11`
```json
{
"Crypt": {
"Pkcs11": {
"AssetsRootPath": "E:\\DataFiles\\Digital Data\\EnvelopeGenerator",
"SlotId": 1720207650,
"TokenLabel": "DevToken",
"ProxySocket": "tcp://172.24.12.64:5657",
"UserPin": "***",
"PrivateKeyLabel": "sign-key",
"CertificateLabel": "sign-cert",
"ApplicationName": "signFLOW",
"UseUtcSigningTime": true
}
}
}
```bash
sudo apt-get update && sudo apt-get install -y softhsm2 opensc p11-kit libengine-pkcs11-openssl
```
Security rules:
- Never commit real PINs.
- Use environment variables or secret vault.
- Use test-only tokens for development.
Production naming convention used in this repository:
- Token label: `CompanyProdToken`
- Private key label: `company-sign-key-v1`
- Certificate label: `company-sign-cert-v1`
These names are also exposed as constants in `EnvelopeGenerator.Infrastructure.Crypt/Options/Pkcs11ProviderOptions.cs`.
---
## 6) Test configuration source
Crypt tests read PKCS#11 values from `EnvelopeGenerator.Tests/appsettings.json` under `Crypt:Pkcs11`.
Required keys:
- `Crypt:Pkcs11:AssetsRootPath` (optional; if missing, app base directory is used)
- `Crypt:Pkcs11:SlotId` (or `Crypt:Pkcs11:TokenLabel`)
- `Crypt:Pkcs11:UserPin`
- `Crypt:Pkcs11:PrivateKeyLabel`
- `Crypt:Pkcs11:CertificateLabel`
No environment variable is required for crypt tests in this repository anymore.
---
## 7) Full SoftHSM lifecycle runbook (project scope)
### 7.1 Discover module path
### 2.2 SoftHSM-Modulpfad pruefen
```bash
ldconfig -p | grep softhsm
find /usr -name "libsofthsm2.so" 2>/dev/null
```
### 7.2 List slots/tokens
### 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
```
### 7.3 Create new token (recommended for new company/test tenant)
Hinweis: Nach `--init-token` wird der Slot i. d. R. neu zugewiesen.
### 2.4 Schluesselpaar erzeugen
```bash
softhsm2-util --init-token --slot <uninitialized-slot> --label <token-label> --so-pin <so-pin> --pin <user-pin>
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
```
Important:
### 2.5 Zertifikat importieren
- After init, token is reassigned to a new slot id.
- Re-run `--show-slots` and use the new slot id.
```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
```
### 7.4 Login and inspect objects
### 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
```
### 7.5 Generate company signing key pair
### 2.7 Proxy-Daemon endpoint stabilisieren
Ein wiederkehrendes Betriebsproblem war ein zufaelliger/local-only Listener. Fix:
```bash
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot <slot-id> --login --pin <user-pin> \
--keypairgen --key-type rsa:3072 --label sign-key --id 01
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
```
### 7.6 Import company certificate
Pruefung:
```bash
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot <slot-id> --login --pin <user-pin> \
--write-object company-sign-cert.der --type cert --label sign-cert --id 01
```
### 7.7 Read object metadata (for diagnostics)
```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-mechanisms
```
### 7.8 Update operations
PKCS#11 objects are usually immutable for key/cert payload; updates are done by rotation:
1. Create/import new key/cert with new label or id.
2. Update app config/env labels.
3. Validate with integration tests.
4. Delete old objects when safe.
PIN operations:
- User PIN change (while logged in):
```bash
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot <slot-id> --login --pin <old-user-pin> --change-pin --new-pin <new-user-pin>
```
- User PIN reset via SO credentials:
```bash
softhsm2-util --init-pin --slot <slot-id> --so-pin <so-pin> --pin <new-user-pin>
```
### 7.9 Delete operations
Delete by label/id/type:
```bash
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot <slot-id> --login --pin <user-pin> \
--delete-object --type cert --label sign-cert
```
Token-level destructive reset (do not use unless approved):
```bash
softhsm2-util --delete-token --token <token-label>
systemctl show pkcs11-proxy.service -p Environment --no-pager
ss -ltnp | grep 5657
```
---
## 8) New company onboarding checklist
## 3. Web-API/Server-Seite: Installation und Asset-Bereitstellung
For company-level signing model (one company key/cert pair):
### 3.1 Bezugsquellen der Windows-Artefakte
1. Create token with company label (or assign dedicated token in remote HSM).
2. Generate key pair in token.
3. Obtain CA certificate and import into token.
4. Record secure runtime values:
- module path
- slot id or token label
- user pin
- private key label
- certificate label
5. Run crypt integration tests.
6. Store values in vault and wire app environment.
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.
---
## 9) Rotation/update checklist
## 4. Implementierte Services, Modelle, DTOs
1. Create new key/cert (`sign-key-v2`, `sign-cert-v2`).
2. Configure app env to new labels.
3. Run integration tests.
4. Deploy.
5. Keep old key/cert during grace period.
6. Remove old key/cert after legal/operational confirmation.
### 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`
---
## 10) Running tests
## 5. Betriebserfahrungen und Challenges
Before running, configure `EnvelopeGenerator.Tests/appsettings.json` -> `Crypt:Pkcs11` with real Linux SoftHSM values.
### 5.1 Interop vs Tool-Verhalten
Run crypt tests:
Beobachtetes Muster in der realen Umgebung:
```bash
dotnet test "EnvelopeGenerator.Tests/EnvelopeGenerator.Tests.csproj" -f net8.0 --filter "FullyQualifiedName~EnvelopeGenerator.Tests.Application.Crypt"
```
- `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)
---
## 11) Common failures
## 6. Health, Monitoring und Verifikation
- `CKR_PIN_INCORRECT`: wrong user pin for that token.
- `CRYPT_PROVIDER_UNAVAILABLE`: bad module path or native load issue.
- `CRYPT_SLOT_NOT_FOUND`: wrong slot id or token label.
- `CRYPT_LOGIN_FAILED`: login failed (pin/token mismatch).
- `CRYPT_KEY_NOT_FOUND`: key label/id mismatch.
- `CRYPT_CERT_NOT_FOUND`: certificate label/id mismatch.
### 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
---
## 12) Integration note
## 7. Sicherheits- und Betriebsrichtlinien
Current implementation uses `CKM_SHA256_RSA_PKCS` while caller provides hash bytes. Validate mechanism semantics in your provider/HSM policy. If provider expects raw payload instead of digest for selected mechanism, signing flow must be adjusted.
### 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
---
## 13) Production-first onboarding (single-line checkpoints)
## 8. API-Verhalten bei Signaturmetadaten
This section is the authoritative path for production-style setup (critical documents, FES).
Aktueller Standard:
### 13.1 Step 1 - Initialize dedicated company token
- `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.
One-line command:
Damit ist das Verhalten deterministisch und manipulationsaermer fuer Integrationsclients.
```bash
mkdir -p ./fes-prod && cd ./fes-prod && export SO_PIN="$(openssl rand -hex 16)" USER_PIN="$(openssl rand -hex 12)" && softhsm2-util --init-token --slot <uninitialized-slot> --label CompanyProdToken --so-pin "$SO_PIN" --pin "$USER_PIN" && softhsm2-util --show-slots
```
---
Checkpoint:
## 9. Troubleshooting-Checkliste (praxisnah)
- Token appears as initialized with label `CompanyProdToken`.
- SoftHSM reassigns token to a new slot ID; use that slot ID in all next commands.
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`
Security note:
Wenn Interop scheitert, aber Tool funktioniert:
- Do not print/store PINs in shell history in real production operations.
- Persist secrets in a vault or protected secret store.
- Betrieb bleibt verfuegbar (Fallback),
- aber Incident/Bug fuer Interop-Kompatibilitaet erfassen.
### 13.2 Step 2 - Generate company signing key pair inside HSM
---
One-line command:
## 10. Ausblick / empfohlene Verbesserungen
```bash
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot <company-slot-id> --login --pin "$USER_PIN" --keypairgen --key-type rsa:3072 --label company-sign-key-v1 --id 01 && pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot <company-slot-id> --login --pin "$USER_PIN" --list-objects
```
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.
Checkpoint:
---
- `Private Key Object` and `Public Key Object` exist for label `company-sign-key-v1`, id `01`.
- Private key remains non-extractable in token.
## 11. Referenzen
### 13.3 Step 3 - Obtain CA-issued certificate for HSM key
Required policy:
- Certificate must be issued by enterprise CA for the key generated in token.
- Do not use self-signed cert for production signing identity.
Operational note:
- CSR generation method depends on installed PKCS#11 OpenSSL integration (`engine_pkcs11` / provider).
- After CA issues certificate, import certificate DER into token with matching id/label family.
OpenSSL 3 prerequisite check:
```bash
openssl version && openssl engine -t -c 2>/dev/null | grep -i pkcs11 || true
```
If no PKCS#11 engine/provider is listed, install integration packages first (distribution specific), then continue.
### 13.4 Step 4 - Import CA certificate into token
One-line command:
```bash
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot <company-slot-id> --login --pin "$USER_PIN" --write-object ./company-sign-cert-v1.der --type cert --id 01 --label company-sign-cert-v1 && pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot <company-slot-id> --login --pin "$USER_PIN" --list-objects
```
Checkpoint:
- `Certificate Object` exists with id `01` and expected label.
### 13.5 Step 5 - Wire runtime/test configuration
Server runtime (`EnvelopeGenerator.Server/EnvelopeGenerator.Server/appsettings.json`) must include:
- `Crypt:Pkcs11:AssetsRootPath` = base directory that contains `pkcs11\windows\proxy\libpkcs11-proxy.dll`
- If null/empty, runtime resolves assets from application output (`AppContext.BaseDirectory`)
- `Crypt:Pkcs11:SlotId` = `2021549410` (or current company slot)
- `Crypt:Pkcs11:TokenLabel` = `CompanyProdToken`
- `Crypt:Pkcs11:ProxySocket` = `tcp://172.24.12.64:5657`
- `Crypt:Pkcs11:UserPin` = real user pin
- `Crypt:Pkcs11:PrivateKeyLabel` = `company-sign-key-v1`
- `Crypt:Pkcs11:CertificateLabel` = `company-sign-cert-v1`
Test runtime (`EnvelopeGenerator.Tests/appsettings.json`) must mirror the same `Crypt:Pkcs11` values.
Then run tests:
```bash
dotnet test "EnvelopeGenerator.Tests/EnvelopeGenerator.Tests.csproj" -f net8.0 --filter "FullyQualifiedName~EnvelopeGenerator.Tests.Application.Crypt"
```
- 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/`