Skip to content

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.

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": {
        "db": {},
        "vault": {
            "vaultUrl": "http://localhost:8200",
            "vaultToken": "your-vault-token"
        }
    }
}
Field Description
defaultProvider Name of the provider used when no explicit kmsProvider is specified (default: db).
providers Object where each key is a provider name and the value is its configuration.

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. If omitted, the defaultProvider is used.


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.

Multiple Key SupportΒΆ

Each tenant can manage multiple cryptographic keys simultaneously. Each key has a unique key id and is also isolated via the tenant_id field.

Each key file contains the private key in JWK format:

{
    "kty": "EC",
    "x": "pmn8SKQKZ0t2zFlrUXzJaJwwQ0WnQxcSYoS_D6ZSGho",
    "y": "rMd9JTAovcOI_OvOXWCWZ1yVZieVYK2UgvB2IPuSk2o",
    "crv": "P-256",
    "d": "rqv47L1jWkbFAGMCK8TORQ1FknBUYGY6OLU1dYHNDqU",
    "kid": "039af178-3ca0-48f4-a2e4-7b1209f30376",
    "alg": "ES256"
}

Automatic Key GenerationΒΆ

On startup, if no keys are found for a tenant, the service will automatically generate a new key pair. Even when using the database mode, the private key will never be exposed by the api.


Vault (HashiCorp Vault)ΒΆ

To use HashiCorp Vault for key management, add a vault entry to the providers section of kms.json:

{
    "defaultProvider": "vault",
    "providers": {
        "db": {},
        "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:

{
    "vaultUrl": "${VAULT_URL}",
    "vaultToken": "${VAULT_TOKEN}"
}

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.


ExtensibilityΒΆ

The key management system is designed to be extensible. You can integrate other key management backends such as:

  • πŸ” AWS KMS
  • πŸ” Azure Key Vault
  • πŸ” Google Cloud KMS
  • πŸ” Hardware Security Modules (HSMs)

To add a new backend:

  1. Create a new class extending KmsAdapter (see vault-key.service.ts for reference).
  2. Register a factory function for the new type in kms-adapter.factory.ts.
  3. Add the provider entry to kms.json:
{
    "providers": {
        "awskms": {
            "region": "eu-central-1",
            "keyArn": "arn:aws:kms:..."
        }
    }
}

If you need help integrating a new provider, feel free to open an issue or contact the maintainers.


CertificatesΒΆ

EUDIPLO supports comprehensive management of X.509 certificates that are linked to cryptographic keys. Certificates can be used to verify the authenticity of public keys and establish trust between parties.

Certificate ManagementΒΆ

Certificates are managed separately from keys and can be associated with any imported key. Each certificate has a unique identifier and is linked to a key via the keyId field.

Certificate Types:

  • Access Certificates (isAccessCert): Used for authenticating access to protected resources
  • Signing Certificates (isSigningCert): Used for signing credentials and tokens

A single certificate can serve both purposes by setting both flags to true.

Certificate OperationsΒΆ

The certificate management API provides endpoints for creating, reading, updating, and deleting certificates. For detailed endpoint specifications, parameters, and request/response schemas, see:

API Reference: Certificate API Endpoints

Available operations:

  • List all certificates for a tenant
  • Get certificate details by ID
  • Create/Import certificate for a specific key
  • Update certificate metadata and type flags
  • Delete certificate
  • Generate self-signed certificate for a key

Self-Signed Certificate GenerationΒΆ

Generate a self-signed certificate for an existing key using the dedicated endpoint. This automatically creates a certificate with:

  • Subject: Common Name based on tenant configuration
  • Validity: 1 year from generation
  • Algorithm: Matches the key algorithm (ES256)
  • Extensions: Subject Alternative Name (SAN) for localhost

API Reference: Self-Signed Certificate Generation

Certificate Import via ConfigurationΒΆ

Certificates can be imported during application startup using the configuration system.

Directory Structure:

assets/config/
└── tenant-1/
    └── certs/
        β”œβ”€β”€ signing-cert.json
        └── access-cert.json

Certificate File Format:

{
    "keyId": "039af178-3ca0-48f4-a2e4-7b1209f30376",
    "isAccessCert": true,
    "isSigningCert": true,
    "description": "Production certificate",
    "crt": "-----BEGIN CERTIFICATE-----\nMIIBYTCCAQigAwIB...\n-----END CERTIFICATE-----"
}

See Configuration Import for more details.

Certificate Chain SupportΒΆ

EUDIPLO supports certificate chains for establishing trust hierarchies. Import multiple certificates and link them to the same key to build a chain from leaf to root certificate.

Certificate ValidationΒΆ

Certificates are validated during import:

  • PEM format verification
  • Public key matching with associated key
  • Certificate expiration checking
  • X.509 standard compliance

Certificate FormatΒΆ

Certificates must be in PEM format with proper line breaks:

  • Use \n escape sequences in JSON
  • Include both -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- headers
  • Base64-encoded DER content between headers

When a new key pair is generated, a self-signed certificate is also created. This certificate includes the public key and is stored alongside the key files. The certificate can be overwritten any time via the API.

When using the Registrar, it will generate a certificate for the public key that can be used to secure the OID4VCI and OID4VP requests. Each tenant will only have one access certificate.

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 GenerationΒΆ

Tenant Initialization Process:

  1. Client registers with credentials (client_id, client_secret)
  2. Cryptographic key pair automatically generated
  3. Keys stored in tenant-specific location
  4. Generation of certificate for public key

Key Import and ManagementΒΆ

EUDIPLO supports importing existing keys through multiple methods to accommodate different deployment scenarios and security requirements.

The kid provided in the key files is used to identify and manage keys within the system. An optional description field can be included for additional context.

API-Based Key ImportΒΆ

Import keys through the REST API using authenticated requests:

Endpoint: POST /key

Request Body:

{
    "privateKey": {
        "kty": "EC",
        "x": "pmn8SKQKZ0t2zFlrUXzJaJwwQ0WnQxcSYoS_D6ZSGho",
        "y": "rMd9JTAovcOI_OvOXWCWZ1yVZieVYK2UgvB2IPuSk2o",
        "crv": "P-256",
        "d": "rqv47L1jWkbFAGMCK8TORQ1FknBUYGY6OLU1dYHNDqU",
        "kid": "039af178-3ca0-48f4-a2e4-7b1209f30376",
        "alg": "ES256"
    },
    "description": "Optional key description",
    "crt": "-----BEGIN CERTIFICATE-----\n...optional certificate...\n-----END CERTIFICATE-----"
}

Response:

{
    "id": "039af178-3ca0-48f4-a2e4-7b1209f30376"
}

Configuration-Based Key ImportΒΆ

Import keys automatically during application startup using the configuration import system.

Environment Variables:

CONFIG_IMPORT=true
CONFIG_IMPORT_FORCE=false  # Set to true to overwrite existing keys

Directory Structure:

assets/config/
β”œβ”€β”€ tenant-1/
β”‚   └── keys/
β”‚       β”œβ”€β”€ primary-key.json
β”‚       β”œβ”€β”€ backup-key.json
β”‚       └── legacy-key.json
└── tenant-2/
    └── keys/
        └── signing-key.json

Key File Format:

{
    "privateKey": {
        "kty": "EC",
        "x": "...",
        "y": "...",
        "crv": "P-256",
        "d": "...",
        "kid": "unique-key-identifier",
        "alg": "ES256"
    },
    "crt": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
}

Key Management OperationsΒΆ

For detailed key management endpoints, parameters, and request/response schemas, see:

API Reference: Key Management API Endpoints

Available operations include listing keys, importing keys, and managing key 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
  • Key Generation: Automatic generation if no keys exist