Added a detailed README for the `EnvelopeGenerator.Infrastructure.Crypt` project, explaining its purpose, functionality, and integration with PKCS#11-based cryptographic workflows. Highlights include: - Overview of the project's role in FES workflows. - Explanation of SoftHSM and PKCS#11 deployment patterns. - Mapping of functionality to FES diagram steps 6-8. - Documentation of service interfaces and DI entry point. - Configuration guidance with JSON examples and security best practices. - Instructions for obtaining PKCS#11 values and setting up SoftHSM. - Checklist for IT handover and environment setup. - Steps for running cryptographic tests with PowerShell and Linux examples. - Common failure diagnostics and their meanings. - Clarification of signing semantics and validation requirements. - FAQ addressing common questions about SoftHSM and PKCS#11 usage. This update ensures clear guidance for developers and IT teams to configure and integrate the cryptographic layer effectively.
EnvelopeGenerator.Infrastructure.Crypt
This project provides PKCS#11-based cryptographic infrastructure for FES (Advanced Electronic Signature) workflows.
If you are new to HSM/SoftHSM: this README is written to let you start from zero and still understand the full path from setup to testing.
1) What this project is (and what it is not)
This project is the cryptography layer only.
- It signs hashes using private keys stored in HSM/SoftHSM.
- It reads certificates from HSM/SoftHSM.
- It verifies signatures.
- It exposes service abstractions for Application/Server integration.
It is not:
- a REST API by itself,
- a UI component,
- a full document workflow orchestrator.
2) SoftHSM and PKCS#11 in one minute
SoftHSMv2is a software HSM implementation.- It does not provide a REST endpoint.
- You access it through a PKCS#11 library/module (
.so/.dll). - Your app loads that library and calls PKCS#11 functions.
Two deployment patterns are possible:
- Direct local module
- Example library path:
libsofthsm2.so
- Example library path:
- PKCS#11 proxy module (remote HSM/SoftHSM)
- Example library path:
libpkcs11-proxy.soor proxy DLL
- Example library path:
Both are valid for this project.
3) How this maps to the FES diagram (Ablauf SignFlow Unternehmenszertifikat)
From the shared draw.io/PDF process:
- Step 6: Backend computes document hash and sends it with PIN context to HSM.
- Implemented by:
ISignatureProvider/Pkcs11SignatureProvider
- Implemented by:
- Step 7: HSM returns digital signature (and cert context can be resolved).
- Implemented by:
Pkcs11SignatureProvider+ICertificateProvider
- Implemented by:
- Step 8: Backend embeds signature + certificate into PDF and creates audit trail.
- This project provides crypto primitives for this step.
- PDF embedding and audit document composition are integrated in later layers.
So this project is the cryptographic core for diagram steps 6-8.
Actor mapping from the diagram:
Ersteller(sender): creates envelope and defines recipients.Signierer(recipient/signer): completes 2FA and signs.Backend(our stack): computes hash, requests HSM signature, embeds proof in PDF.HSM/SoftHSM: stores private keys and performs cryptographic signing.CA: issues/renews certificates.
4) Service surface
Main interfaces:
ISignatureProviderICertificateProviderISignatureVerifierICryptographicHealthCheck
DI entry point:
CryptDependencyInjection.AddCryptInfrastructure(...)
5) Required configuration
Configuration section: Crypt:Pkcs11
Typical keys:
{
"Crypt": {
"Pkcs11": {
"LibraryPath": "/usr/lib/softhsm/libsofthsm2.so",
"SlotId": 0,
"TokenLabel": null,
"UserPin": "***",
"PrivateKeyLabel": "sign-key",
"PrivateKeyIdHex": null,
"CertificateLabel": "sign-cert",
"CertificateIdHex": null
}
}
}
Security rule:
- Do not commit real PINs to source control.
- Use environment variables / secret vault for production.
6) The 5 test values you must provide
Integration tests need these environment variables:
FES_TEST_PKCS11_LIBRARY_PATHFES_TEST_PKCS11_SLOT_IDFES_TEST_PKCS11_USER_PINFES_TEST_PKCS11_PRIVATE_KEY_LABELFES_TEST_PKCS11_CERTIFICATE_LABEL
Without these values, integration tests are skipped by design.
6.1 Which certificate/key should be created?
This is the most important business decision for IT and architecture.
Based on your shared diagram, the primary model is:
- one company certificate + company key pair in HSM,
- reused for all signers,
- signer identity proven by audit-trail + 2FA evidence.
What this means in practical terms:
- Not one key per sender.
- Not one key per recipient by default.
- One company signing identity, many signing events.
Alternative model (future/optional):
- per-signer certificate/key pair (more complex CA lifecycle).
For current fast validation and your FES flow, use the company-level key/certificate model.
7) How to obtain these values (IT-friendly)
7.1 If you use direct SoftHSM module
A) Find module path
What it is:
- PKCS#11 shared library file used by the app to talk to SoftHSM.
Why needed:
- Without this exact file path, PKCS#11 cannot be loaded.
Linux examples:
ldconfig -p | grep softhsm
find /usr -name "libsofthsm2.so" 2>/dev/null
Use the resolved full path as FES_TEST_PKCS11_LIBRARY_PATH.
B) List slots/tokens
What it is:
- Slot: logical container position in PKCS#11.
- Token: initialized security container in a slot.
Why needed:
- The app must know which slot/token contains the company key and certificate.
softhsm2-util --show-slots
Pick your slot as FES_TEST_PKCS11_SLOT_ID.
C) Identify key and certificate labels
What it is:
Private key label: name of the signing private key object.Certificate label: name of the matching X.509 certificate object.
Why needed:
- Tests and runtime use labels to select correct objects in HSM.
Use pkcs11-tool against your module:
pkcs11-tool --module /path/to/libsofthsm2.so --slot <slot-id> --login --pin <user-pin> --list-objects
From output:
- private key label ->
FES_TEST_PKCS11_PRIVATE_KEY_LABEL - certificate label ->
FES_TEST_PKCS11_CERTIFICATE_LABEL
D) User PIN
What it is:
- User authorization secret to open authenticated session on token.
Why needed:
- HSM will not allow signing with private key without login.
PIN is assigned during token initialization and must be provided by IT/security team.
E) Optional: Initialize token and create objects (Linux quick bootstrap)
Only if token/keys are not already provisioned by IT PKI team.
# 1) Initialize token in slot 0 (example)
softhsm2-util --init-token --slot 0 --label "CompanySignToken"
# 2) Verify slot/token
softhsm2-util --show-slots
# 3) Generate RSA key pair inside token (example)
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot 0 --login --pin <USER_PIN> \
--keypairgen --key-type rsa:3072 --label sign-key --id 01
# 4) Import certificate (already issued by CA)
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot 0 --login --pin <USER_PIN> \
--write-object company-sign-cert.der --type cert --label sign-cert --id 01
# 5) List objects and confirm labels
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot 0 --login --pin <USER_PIN> --list-objects
Notes:
- Use this only in non-production unless approved.
- In production, key generation/import should follow company security policy.
7.2 If you use PKCS#11 proxy module
What it is:
- A local PKCS#11 bridge library that forwards calls to remote HSM/SoftHSM service.
Why needed:
- App still loads a local module path, but crypto operations happen remotely.
Ask IT for:
- proxy module path (
libpkcs11-proxy.*) - slot id or token label
- user pin
- private key label
- certificate label
In proxy mode, values come from proxy-backed token, not local SoftHSM token files.
7.3 Linux handover checklist for IT (copy/paste friendly)
- Confirm module path exists (
libsofthsm2.soor proxy module). - Confirm token exists and slot id is known.
- Confirm company private key label and certificate label.
- Confirm user PIN for test environment.
- Share these five values securely with development team.
8) Test execution checklist (single command flow)
8.1 Set environment variables
PowerShell example:
$env:FES_TEST_PKCS11_LIBRARY_PATH = "<module-path>"
$env:FES_TEST_PKCS11_SLOT_ID = "<slot-id>"
$env:FES_TEST_PKCS11_USER_PIN = "<user-pin>"
$env:FES_TEST_PKCS11_PRIVATE_KEY_LABEL = "<private-key-label>"
$env:FES_TEST_PKCS11_CERTIFICATE_LABEL = "<certificate-label>"
Linux (bash) example:
export FES_TEST_PKCS11_LIBRARY_PATH="/usr/lib/softhsm/libsofthsm2.so"
export FES_TEST_PKCS11_SLOT_ID="0"
export FES_TEST_PKCS11_USER_PIN="<user-pin>"
export FES_TEST_PKCS11_PRIVATE_KEY_LABEL="sign-key"
export FES_TEST_PKCS11_CERTIFICATE_LABEL="sign-cert"
Verify env values quickly:
echo "$FES_TEST_PKCS11_LIBRARY_PATH"
echo "$FES_TEST_PKCS11_SLOT_ID"
echo "$FES_TEST_PKCS11_PRIVATE_KEY_LABEL"
echo "$FES_TEST_PKCS11_CERTIFICATE_LABEL"
8.2 Run only crypt tests
dotnet test "EnvelopeGenerator.Tests/EnvelopeGenerator.Tests.csproj" -f net8.0 --filter "FullyQualifiedName~EnvelopeGenerator.Tests.Application.Crypt"
Expected:
- Unit tests pass always.
- Integration tests pass when env values are correct.
- Integration tests skip when env values are missing.
If all five values are correct:
- integration tests run automatically,
- no code change is required,
- only environment setup is required.
9) Common failure meanings
CRYPT_PROVIDER_UNAVAILABLE- invalid library path, missing native dependency, provider cannot load
CRYPT_SLOT_NOT_FOUND- wrong slot id or token label
CRYPT_LOGIN_FAILED- wrong PIN
CRYPT_KEY_NOT_FOUND- private key label/id mismatch
CRYPT_CERT_NOT_FOUND- certificate label/id mismatch
This is exactly what IT needs for first-level diagnostics.
10) Integration in the full stack architecture
Current role by layer:
Infrastructure.Crypt(this project): PKCS#11 crypto operationsApplication: orchestration use-cases and business process stepsServer: API endpoints and presentation concerns
Recommended integration path:
- Stabilize crypt tests and environment setup (this stage).
- Integrate
ISignatureProvider+ICertificateProviderinto Application command flow. - Connect Application flow to Server endpoints.
- Add PDF embedding and audit-trail generation for full step-8 compliance.
- Add archiving/distribution orchestration for steps 9-10.
11) Important note about signing semantics
PKCS#11 mechanisms differ in whether they expect raw data or a precomputed digest.
Current implementation signs with CKM_SHA256_RSA_PKCS and receives hash bytes from caller.
This must be validated in your real provider environment.
If provider expects raw data for this mechanism, integration may require adjustment. This is why integration tests are critical.
12) Quick FAQ
Q: Do I need REST calls to SoftHSM?
No. SoftHSM is not a REST server. Use PKCS#11 library calls.
Q: Can I use proxy and still call it SoftHSM setup?
Yes. Proxy can forward to SoftHSM-backed token infrastructure.
Q: Once I provide the 5 values, can tests run directly?
Yes. Set env vars and run the single dotnet test command above.
Q: Will one company cert/key be enough for this phase?
Yes, for the diagram-aligned company-signing model, one company key/certificate is enough for initial implementation and validation.