Managed Keys let Stronghold use cryptographic keys stored in an external trusted system, such as an HSM or external KMS, without storing the private key material inside Stronghold itself.
This approach is useful when:
- private keys must remain outside Stronghold;
- signing or encryption operations must be performed by an external system;
- security or compliance requirements prohibit exporting key material.
In Stronghold, a managed key is a named record managed through the sys/managed-keys/<TYPE>/<NAME> API.
How it works
Stronghold stores the configuration needed to access an external key, but not the private key itself. When a secrets engine needs to perform signing, signature verification, encryption, or decryption, it calls the corresponding managed key, which then delegates the operation to the external backend.
This means:
- key material remains in the external system;
- Stronghold uses the managed key as an abstraction over the external backend;
- multiple managed keys can be configured for the same backend if you need different keys or different access policies.
Supported backends
Stronghold supports the following managed key types:
pkcs11yandexcloudkms
pkcs11
The pkcs11 type is used for HSMs and PKCS#11-compatible libraries. A managed key of this type references a previously defined kms_library "pkcs11" stanza in Stronghold server configuration.
A typical workflow is:
- configure
kms_library "pkcs11"in the server configuration; - register a managed key through
sys/managed-keys/pkcs11/<NAME>; - optionally verify key access using
test/sign; - allow the key for the required mount path.
Example:
stronghold write sys/managed-keys/pkcs11/my-hsm-key library=softhsm token_label=managed-keys pin=1234 key_label=my-signing-key usages=sign,verifypkcs11 parameters
| Parameter | Description |
|---|---|
library | Required. Name of the kms_library "pkcs11" stanza from the server configuration |
slot | Slot number (decimal string). Exactly one of slot and token_label must be specified |
token_label | Token label. Exactly one of slot and token_label must be specified |
pin | Required. PIN for access to the token. It is never returned when reading the key (the value is redacted) |
key_label, key_id | Label or identifier of the key in the HSM. At least one of them is required. If the key does not exist and allow_generate_key=true, the key is generated with the key_label label |
mechanism | PKCS#11 mechanism of the key. It must be specified in hexadecimal form with the 0x prefix, for example 0x1041 |
curve | For ECDSA — the curve (P256, P384, or P521) when generating a key. For GOST mechanisms — the key profile (see below) |
key_bits | For RSA — the key length when generating a key (2048, 3072, or 4096). For AES, only 256 is allowed when generating a key |
force_rw_session | Forces read/write sessions, to work around some HSMs. Default is false |
max_parallel | Maximum number of concurrent operations submitted to the HSM |
usages | Comma-separated list of allowed operations: encrypt, decrypt, sign, verify, wrap, unwrap. Default is sign,verify |
If mechanism is not specified, the key can only be used with an existing key in the HSM, and generation (allow_generate_key=true) is not available.
The pkcs11 type is available in Stronghold EE.
Supported mechanisms
| Mechanism | Value | Key type | Operations |
|---|---|---|---|
CKM_ECDSA | 0x1041 | ECDSA (P256, P384, P521) | sign, verify |
CKM_RSA_PKCS | 0x1 | RSA (2048, 3072, 4096) | sign, verify (PKCS#1 v1.5 or PSS), encrypt, decrypt, wrap, unwrap |
CKM_RSA_PKCS_OAEP | 0x9 | RSA | same |
CKM_RSA_PKCS_PSS | 0xd | RSA | same |
CKM_GOSTR3410 | 0x1201 | GOST R 34.10-2012, 256 bits (or GOST 2001) | sign, verify |
CKM_GOSTR3410_512 | 0xd4321006 | GOST R 34.10-2012, 512 bits | sign, verify |
CKM_AES_GCM, CKM_AES_CBC, CKM_AES_CBC_PAD | 0x1087, 0x1082, 0x1085 | AES (generated keys are 256-bit) | encrypt, decrypt |
CKM_KUZNECHIK_CTR_ACPKM, CKM_KUZNECHIK_MGM | 0xd4321032, 0xd432102d | Kuznechik | encrypt, decrypt |
RSA and PSS signatures
For RSA keys, the three RSA mechanisms (CKM_RSA_PKCS, CKM_RSA_PKCS_OAEP, CKM_RSA_PKCS_PSS) only select the RSA key: the signature scheme (PKCS#1 v1.5 or RSA-PSS) is chosen by the calling secrets engine for each operation, as in Go’s crypto/rsa. RSA-PSS is used with the salt length equal to the hash length. The signature is verified locally with the public key exported from the HSM.
- In PKI, RSA-PSS is requested with the
use_pssparameter (when generating a root or intermediate CA, signing, and in roles). If the managed key supports only PSS signatures, setrevocation_signature_algorithmfor the issuer to one of the PSS algorithms; otherwise, building the CRL fails with an error that mentions PSS. - In
test/sign, RSA-PSS is requested with theuse_pss=trueparameter (see Basic operations).
GOST keys
GOST keys in the HSM are used only for signing and signature verification. The mechanism determines the key size:
CKM_GOSTR3410— 256-bit keys;CKM_GOSTR3410_512— 512-bit keys.
The curve parameter sets the key generation profile and must match the mechanism:
gost2001orgost2012-256forCKM_GOSTR3410;gost2012-512forCKM_GOSTR3410_512.
If curve is omitted, the profile is selected based on the mechanism.
The Streebog hash algorithm is used for signing: streebog-256 for 256-bit keys and streebog-512 for 512-bit keys.
Signature verification is performed by the HSM.
When a GOST key is used in pki, the signature algorithm is selected based on the type of the key public part. In transit, a managed GOST key accepts only the Streebog hash algorithm matching the key size.
Example of registering a GOST key:
stronghold write sys/managed-keys/pkcs11/gost-ca-key library=rutoken token_label=managed-keys pin=12345678 key_label=my-gost-key mechanism=0x1201 curve=gost2012-256 usages=sign,verifyyandexcloudkms
The yandexcloudkms type is used for integration with Yandex Cloud KMS.
Its configuration uses:
kms_key_idoauth_tokenorservice_account_key_jsonendpointwhen needed
For authentication to Yandex Cloud KMS, Stronghold can use one of the following options:
oauth_tokenservice_account_key_json- the service account attached to the virtual machine in Yandex Cloud
If neither oauth_token nor service_account_key_json is provided, Stronghold attempts to use the virtual machine service account through the standard instance credentials flow. This is similar to common Vault patterns where cloud KMS integrations can rely on the identity of the running VM instance.
Example:
stronghold write sys/managed-keys/yandexcloudkms/my-yc-key kms_key_id=<KMS_KEY_ID> oauth_token=<OAUTH_TOKEN> usages=sign,verifyWhere <KMS_KEY_ID> is the Yandex Cloud KMS key ID, and <OAUTH_TOKEN> is the Yandex Cloud OAuth token.
Example using the virtual machine service account:
stronghold write sys/managed-keys/yandexcloudkms/my-yc-key kms_key_id=<KMS_KEY_ID> usages=sign,verifyThe oauth_token and service_account_key_json parameters are mutually exclusive. If one of them is specified, it is used explicitly for authentication to Yandex Cloud.
For yandexcloudkms, the set of allowed operations depends on the key itself and its configuration. If the managed key is going to be used by pki or ssh, it must support signing. For transit, the required operations depend on the selected usage scenario.
Which secrets engines can use Managed Keys
In Stronghold, managed keys can be used by:
SSHPKITransit
SSH
The SSH secrets engine can use a managed key as its certificate authority key and use it to sign SSH certificates.
This is useful when the SSH CA key must remain in an external HSM or KMS.
PKI
The PKI secrets engine can use a managed key for root and intermediate CA generation and for certificate signing.
This is one of the primary managed key use cases in Stronghold. For PKI, it is also important to allow the managed key for the specific PKI mount if the key was not created with any_mount=true.
Example:
stronghold secrets tune -allowed-managed-keys=my-hsm-key pki/Transit
The Transit secrets engine can use a managed key as an external cryptographic key.
Depending on backend capabilities and the key type, this can allow:
- signing;
- signature verification;
- encryption;
- decryption.
For Transit, the managed key is specified when creating or rotating a transit key.
Namespaces and scope
A managed key is bound to a specific namespace. The secrets engine that uses the key must exist in the same namespace as the managed key itself.
If the key is not created with any_mount=true, you must explicitly allow its use for a given mount path.
Basic operations
List managed keys of a given type:
stronghold list sys/managed-keys/pkcs11Read key configuration:
stronghold read sys/managed-keys/pkcs11/my-hsm-keyVerify key accessibility with a test signature:
stronghold write sys/managed-keys/pkcs11/my-hsm-key/test/signThe test/sign request accepts optional parameters:
hash_algorithm— hash algorithm for the test signature. By default,sha2-256is used; forpkcs11keys with GOST mechanisms,streebog-256orstreebog-512is used, depending on the mechanism.use_pss— for RSA keys, sign using RSA-PSS. For RSA keys inyandexcloudkms, which sign only with PSS, it is enabled by default.
Delete a managed key:
stronghold delete sys/managed-keys/pkcs11/my-hsm-keyPractical recommendations
- Use
pkcs11when keys live in a local or network-attached HSM exposed through a PKCS#11 library. - Use
yandexcloudkmswhen keys are managed in Yandex Cloud KMS. - Restrict
usagesto the minimum required operations. - If the key should not be available to every mount, do not enable
any_mountand configureallowed-managed-keysexplicitly. - Before attaching a key to
pki,ssh, ortransit, verify it withtest/signor another appropriate validation flow.