Key ManagementΒΆ
The keys used for signing operations in EUDIPLO can be managed by one or
more KMS (Key Management System) providers running simultaneously. Providers are
configured in a single kms.json file inside the config folder.
π‘ Encryption operations always use database-stored keys and are independent from the KMS providers configured for signing.
Available ProvidersΒΆ
| Provider | Type | Description | Import Support |
|---|---|---|---|
db |
Built-in | Keys stored encrypted in the database | β Yes |
vault |
Built-in | HashiCorp Vault Transit secrets engine | β No |
aws-kms |
Built-in | AWS Key Management Service | β No |
ConfigurationΒΆ
KMS providers are configured in <CONFIG_FOLDER>/kms.json. If no file is found,
a single db provider is registered automatically.
{
"defaultProvider": "db",
"providers": [
{ "id": "db", "type": "db", "description": "Default database provider" },
{
"id": "vault",
"type": "vault",
"description": "HashiCorp Vault",
"vaultUrl": "http://localhost:8200",
"vaultToken": "your-vault-token"
},
{
"id": "aws",
"type": "aws-kms",
"description": "AWS KMS",
"region": "eu-central-1"
}
]
}
| Field | Description |
|---|---|
defaultProvider |
ID of the provider used when no explicit kmsProvider is specified (default: db). |
providers |
Array of provider configurations. Each entry must have a unique id and a type. |
Each provider entry has:
| Field | Description |
|---|---|
id |
Unique identifier for the provider instance (used when generating keys). |
type |
Adapter type: db, vault, or aws-kms. |
description |
Optional human-readable description. |
| ... | Additional type-specific configuration fields. |
Environment-variable placeholders (${VAULT_URL}, ${VAULT_TOKEN:default}) are
resolved at startup, so secrets can still be injected through the environment.
When generating or importing a key through the API, include the kmsProvider
field to select a specific provider by its id. If omitted, the defaultProvider is used.
Multiple Providers of the Same TypeΒΆ
You can configure multiple instances of the same provider type with different IDs:
{
"defaultProvider": "main-vault",
"providers": [
{ "id": "db", "type": "db" },
{
"id": "main-vault",
"type": "vault",
"description": "Production Vault",
"vaultUrl": "${VAULT_URL}",
"vaultToken": "${VAULT_TOKEN}"
},
{
"id": "backup-vault",
"type": "vault",
"description": "Backup Vault",
"vaultUrl": "${BACKUP_VAULT_URL}",
"vaultToken": "${BACKUP_VAULT_TOKEN}"
}
]
}
Database Key Management (db)ΒΆ
When the db provider is configured (the default), keys are stored encrypted in the
database. This mode is ideal for development or testing.
Key Chain SupportΒΆ
Each tenant can manage multiple key chains simultaneously. Each key chain has a unique ID and is isolated via the tenant_id field.
Key chains are unified entities containing both keys and certificates, organized by usage type (access, attestation, trustList, statusList, encrypt).
Vault (HashiCorp Vault)ΒΆ
To use HashiCorp Vault for key management,
add a vault entry to the providers array in kms.json:
{
"defaultProvider": "vault",
"providers": [
{ "id": "db", "type": "db" },
{
"id": "vault",
"type": "vault",
"description": "HashiCorp Vault",
"vaultUrl": "http://localhost:8200",
"vaultToken": "your-vault-token"
}
]
}
| Field | Description |
|---|---|
vaultUrl |
Base URL of the Vault server (without /v1/β¦). |
vaultToken |
Authentication token for Vault API access. |
You can use environment-variable placeholders to avoid storing secrets in the config file:
Transit Mount Auto-CreationΒΆ
For each tenant, a transit secret engine mount is created automatically on first use. If the mount already exists the creation step is silently skipped (idempotent). If a Vault API call returns 404 (mount not found), the service retries the operation once after creating the mount.
To issue credentials, you need to have a signed certificate for the public key that is bound to your domain.
In this mode:
- All signing operations are delegated to Vault via its API.
- The private key never leaves the Vault server.
- A stub key entity is stored in the database for tracking purposes (no private key material).
- Access can be tightly controlled using Vault's policies and authentication mechanisms.
Vault is well-suited for production environments where secure, auditable key usage is required.
AWS KMSΒΆ
To use AWS Key Management Service for key management,
add an aws-kms entry to the providers array in kms.json:
{
"defaultProvider": "aws",
"providers": [
{ "id": "db", "type": "db" },
{
"id": "aws",
"type": "aws-kms",
"description": "AWS KMS",
"region": "eu-central-1"
}
]
}
| Field | Description |
|---|---|
region |
AWS region where KMS keys will be created (required). |
accessKeyId |
AWS access key ID (optional β uses SDK credential chain if not provided). |
secretAccessKey |
AWS secret access key (optional β uses SDK credential chain if not provided). |
You can use environment-variable placeholders to avoid storing secrets in the config file:
{
"id": "aws",
"type": "aws-kms",
"region": "${AWS_REGION}",
"accessKeyId": "${AWS_ACCESS_KEY_ID}",
"secretAccessKey": "${AWS_SECRET_ACCESS_KEY}"
}
AuthenticationΒΆ
If accessKeyId and secretAccessKey are not provided, the adapter uses the
AWS SDK default credential chain,
which supports:
- Environment variables (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY) - Shared credentials file (
~/.aws/credentials) - IAM roles for EC2/ECS/Lambda
- Web identity tokens (EKS IRSA)
This is the recommended approach for production deployments.
Key CreationΒΆ
Keys are created as asymmetric ECC_NIST_P256 keys with SIGN_VERIFY usage.
Each key is tagged with:
TenantIdβ the tenant identifierLocalKeyIdβ the local key ID stored in the databaseManagedByβ set toeudiplo
Key DeletionΒΆ
When deleting a key, AWS KMS schedules it for deletion with a 7-day pending window (the minimum allowed by AWS). The local database reference is removed immediately.
In this mode:
- All signing operations are delegated to AWS KMS via its API.
- The private key never leaves AWS KMS.
- A stub key entity is stored in the database for tracking purposes (no private key material).
- Access can be controlled using AWS IAM policies and KMS key policies.
AWS KMS is well-suited for production environments on AWS where you need HSM-backed keys, audit logging via CloudTrail, and fine-grained access control.
β οΈ Note: AWS KMS does not support importing EC keys. Use
createto generate new keys directly in AWS KMS.
ExtensibilityΒΆ
The key management system is designed to be extensible. You can integrate other key management backends such as:
- β AWS KMS (built-in)
- π Azure Key Vault
- π Google Cloud KMS
- π Hardware Security Modules (HSMs)
To add a new backend:
- Create a new class extending
KmsAdapter(seeaws-kms-key.service.tsorvault-key.service.tsfor reference). - Register a factory function for the new type in
kms-adapter.factory.ts. - Add a config DTO in
dto/kms-config.dto.tsextendingBaseKmsProviderConfigDto. - Add the provider entry to
kms.json:
{
"providers": [
{
"id": "azure",
"type": "azure-kv",
"description": "Azure Key Vault",
"vaultUrl": "https://my-vault.vault.azure.net",
"tenantId": "...",
"clientId": "..."
}
]
}
If you need help integrating a new provider, feel free to open an issue or contact the maintainers.
Key ChainsΒΆ
EUDIPLO uses a unified Key Chain model that combines cryptographic keys and their certificates into a single managed entity. This eliminates orphaned keys and simplifies key lifecycle management.
Key Chain ModelΒΆ
A Key Chain encapsulates:
- Active signing key with its certificate
- Optional root CA key (for internal certificate chains / rotation)
- Previous key (for grace period after rotation)
- Rotation policy (automatic certificate renewal)
βββββββββββββββββββββββββββββββββββββββββββββββ
β Key Chain β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β Root CA Key (optional) β
β Root CA Certificate (self-signed) β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β Active Signing Key β
β Active Certificate (CA-signed or self) β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β Previous Key (optional, grace period) β
β Previous Certificate β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β Rotation Policy β
β - Interval Days β
β - Certificate Validity Days β
βββββββββββββββββββββββββββββββββββββββββββββββ
Usage TypesΒΆ
Each key chain is assigned a usage type that determines how it can be used:
| Usage Type | Purpose |
|---|---|
access |
OAuth/OIDC access token signing and authentication |
attestation |
Credential/attestation signing (SD-JWT VC, mDOC) |
trustList |
Trust list signing |
statusList |
Status list (credential revocation) signing |
encrypt |
Encryption (JWE) |
Key Chain TypesΒΆ
Standalone Key Chain:
- Single key with self-signed certificate
- Suitable for development/testing
- No rotation support
Internal CA Key Chain (Rotation Enabled):
- Root CA key signs leaf certificates
- Active key is separate from root CA
- Supports automatic rotation
- Satisfies HAIP section 4.5.1 requirement (credentials MUST NOT be signed with self-signed certificates)
Automatic Key Chain GenerationΒΆ
On startup, if no key chains are found for a tenant, the service automatically generates key chains for each required usage type:
access- For OAuth/OIDC operationsattestation- For credential signing
Certificate Chain SupportΒΆ
When using internal CA key chains, the certificate includes a full chain:
- Leaf certificate (signs credentials/tokens)
- Root CA certificate (signs leaf certificates)
This chain is included in the x5c header of signed tokens.
Certificate FormatΒΆ
Certificates must be in PEM format:
- Use
\nescape sequences in JSON - Include both
-----BEGIN CERTIFICATE-----and-----END CERTIFICATE-----headers - Base64-encoded DER content between headers
Certificate ValidationΒΆ
Certificates are validated during import:
- PEM format verification
- Public key matching with associated key
- Certificate expiration checking
- X.509 standard compliance
When using the Registrar, it will generate a certificate for the public key that can be used to secure the OID4VCI and OID4VP requests.
Note: In the future the access certificate generation will follow the official standard that is under development right now.
Multi-Tenant Key ManagementΒΆ
Automatic Key Chain GenerationΒΆ
Tenant Initialization Process:
- Client registers with credentials (
client_id,client_secret) - Key chains automatically generated for each required usage type
- Keys and certificates stored in the unified key chain
- Certificates linked to keys in the same entity
Key Chain Import and ManagementΒΆ
EUDIPLO supports importing key chains through multiple methods to accommodate different deployment scenarios and security requirements.
API-Based Key Chain ImportΒΆ
Import key chains through the REST API using authenticated requests:
Endpoint: POST /key-chain
Request Body (Standalone - self-signed certificate):
{
"id": "optional-uuid",
"usageType": "attestation",
"key": {
"kty": "EC",
"x": "pmn8SKQKZ0t2zFlrUXzJaJwwQ0WnQxcSYoS_D6ZSGho",
"y": "rMd9JTAovcOI_OvOXWCWZ1yVZieVYK2UgvB2IPuSk2o",
"crv": "P-256",
"d": "rqv47L1jWkbFAGMCK8TORQ1FknBUYGY6OLU1dYHNDqU",
"alg": "ES256"
},
"description": "Optional description"
}
Request Body (With Rotation - imported key becomes root CA):
{
"id": "optional-uuid",
"usageType": "attestation",
"key": {
"kty": "EC",
"x": "pmn8SKQKZ0t2zFlrUXzJaJwwQ0WnQxcSYoS_D6ZSGho",
"y": "rMd9JTAovcOI_OvOXWCWZ1yVZieVYK2UgvB2IPuSk2o",
"crv": "P-256",
"d": "rqv47L1jWkbFAGMCK8TORQ1FknBUYGY6OLU1dYHNDqU",
"alg": "ES256"
},
"description": "HAIP-compliant key chain with CA-signed leaf",
"rotationPolicy": {
"enabled": true,
"intervalDays": 90,
"certValidityDays": 365
}
}
When rotationPolicy.enabled is true:
- The imported key becomes the root CA key
- A new leaf signing key is automatically generated
- The leaf certificate is signed by the imported CA key
- This satisfies HAIP section 4.5.1 (credentials MUST NOT be signed with self-signed certificates)
Response:
Configuration-Based Key Chain ImportΒΆ
Import key chains automatically during application startup using the configuration import system.
Environment Variables:
Directory Structure:
assets/config/
βββ tenant-1/
β βββ key-chains/
β βββ attestation.json
β βββ access.json
β βββ status-list.json
βββ tenant-2/
βββ key-chains/
βββ attestation.json
Key Chain File Format (Standalone):
{
"id": "uuid-for-this-key-chain",
"description": "Attestation signing key chain",
"usageType": "attestation",
"key": {
"kty": "EC",
"x": "...",
"y": "...",
"crv": "P-256",
"d": "...",
"alg": "ES256"
}
}
Key Chain File Format (With Rotation / Internal CA):
{
"id": "uuid-for-this-key-chain",
"description": "HAIP-compliant attestation key chain",
"usageType": "attestation",
"key": {
"kty": "EC",
"x": "...",
"y": "...",
"crv": "P-256",
"d": "...",
"alg": "ES256"
},
"rotationPolicy": {
"enabled": true,
"intervalDays": 90,
"certValidityDays": 365
}
}
Key Chain File Format (With Provided Certificate):
{
"id": "uuid-for-this-key-chain",
"description": "Key chain with external certificate",
"usageType": "attestation",
"key": {
"kty": "EC",
"x": "...",
"y": "...",
"crv": "P-256",
"d": "...",
"alg": "ES256"
},
"crt": [
"-----BEGIN CERTIFICATE-----\nLEAF_CERT...\n-----END CERTIFICATE-----",
"-----BEGIN CERTIFICATE-----\nCA_CERT...\n-----END CERTIFICATE-----"
]
}
Key Chain Management OperationsΒΆ
For detailed key chain management endpoints, parameters, and request/response schemas, see:
API Reference: Key Chain API Endpoints
Available operations include listing key chains, importing key chains, rotating keys, and managing key chain metadata.
Supported Key FormatsΒΆ
- Algorithm Support: ES256 (ECDSA P-256)
- Key Format: JSON Web Key (JWK) format
- Certificate Support: Optional X.509 certificates in PEM format (leaf first, then CA chain)
- Key Generation: Automatic generation if no key chains exist