symfony / kmip-key-management
Symfony KMIP Key Management Bridge
Package info
github.com/symfony/kmip-key-management
Type:symfony-key-management-bridge
pkg:composer/symfony/kmip-key-management
Requires
- php: >=8.4.1
- ext-openssl: *
- symfony/key-management: ^8.2
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-04 12:36:16 UTC
README
Provides EncrypterInterface, DecrypterInterface and DataKeyGeneratorInterface
implementations backed by a KMIP server.
The server keeps the master key and performs authenticated encryption and
decryption. Applications can also wrap locally generated data keys with it.
This Bridge is experimental. Experimental features are not covered by Symfony's Backward Compatibility Promise.
Install the bridge with composer require symfony/kmip-key-management.
Getting started
Provision an active symmetric key on the KMIP server with Encrypt and Decrypt
in its Cryptographic Usage Mask, for AES-GCM. Use its KMIP Unique Identifier
as $keyId.
use Symfony\Component\KeyManagement\Bridge\Kmip\KmipKmsFactory; use Symfony\Component\KeyManagement\Dsn; use Symfony\Component\KeyManagement\EnvelopeEncrypter; $kms = (new KmipKmsFactory())->create(Dsn::fromString( 'kmip://kmip.example.org?cert=/run/secrets/kmip-client.crt&key=/run/secrets/kmip-client.key&version=2.0&ca=/run/secrets/kmip-ca.crt' )); $keyId = 'your-kmip-unique-identifier'; $ciphertext = $kms->encrypt($keyId, 'hello world', 'context'); $plaintext = $kms->decrypt($ciphertext, 'context'); $envelopes = new EnvelopeEncrypter($kms); $envelope = $envelopes->encrypt($keyId, 'another secret', 'context'); $envelopePlaintext = $envelopes->decrypt($envelope, 'context');
Using encrypted data
The context argument above is associated data ($aad). It is authenticated
but not encrypted; pass the same bytes when decrypting. Persist a direct
Ciphertext with both its keyId and blob intact. Persist a self-contained
Envelope as its string value and restore it with Envelope::fromBytes().
Keep the server key available while data encrypted with it is needed.
Direct encryption sends plaintext to the KMIP server. A complete TTLV message,
including its headers, must fit within 16 MiB, so direct payloads have a lower
limit. EnvelopeEncrypter handles larger payloads locally and asks the server
to protect only the data key. With the built-in TLS transport, each KMIP
operation opens a connection. Using a stored data key can reduce KMIP calls
for repeated operations.
PyKMIP reports an invalid authentication tag as KMIP General Failure
(0x100). That reason can also mean a server error, so the bridge leaves it as
a KMIP RuntimeException. With PyKMIP, tampered ciphertext or incorrect AAD
can therefore raise RuntimeException rather than DecryptionFailedException.
Authentication and DSN
A client certificate and private key are required, including when KMIP
username and password credentials are supplied. The server certificate is
verified against the ca certificate authority file, or PHP's system trust
store when ca is omitted. The expected server name defaults to the DSN host;
use peer_name if that host differs from the name on the server certificate,
for example when connecting by IP address. TLS verification cannot be disabled.
Use passphrase for an encrypted client private key, and keep it and any KMIP
password in application secrets.
kmip://[<username>:<password>@]<host>[:<port>]?cert=<client-cert-file>&key=<client-private-key-file>&version=<version>[&ca=<ca-file>][&peer_name=<name>][&passphrase=<passphrase>][&cipher=aes-gcm][&mode=<vendor-mode>][&iv_length=12][&timeout=10]
cert, key and version are required. The port defaults to 5696 and the
timeout to 10 seconds. Supply both username and password or neither, and
percent-encode reserved characters in credentials and option values.
The bridge supports KMIP 1.4, 2.0 and 2.1 for authenticated Encrypt and Decrypt. Select the server's version in the DSN. KMIP 1.0 and 1.1 lack Encrypt and Decrypt; 1.2 and 1.3 lack the authentication tag and associated data fields required by this bridge.
For example:
kmip://kmip.example.org:5696?cert=/run/secrets/kmip-client.crt&key=/run/secrets/kmip-client.key&version=2.0&ca=/run/secrets/kmip-ca.crt
In a Symfony application, configure a named client with the DSN:
key_management: clients: app: '%env(KMIP_DSN)%'
Encryption
The server encrypts with AES-GCM, unless the cipher option selects another cipher (see below).
All the ciphers use a 16-byte authentication tag.
With AES-GCM, new ciphertexts use a 12-byte IV, as NIST SP 800-38D recommends.
Set iv_length (from 12 to 255 bytes) for a server that requires another length.
Each ciphertext records the algorithm, the mode and the IV length it was produced with.
So changing iv_length leaves earlier data readable, as long as the server accepts their IV length.
Encryption ciphers
The cipher option defaults to aes-gcm. To use ChaCha20-Poly1305, set
cipher=chacha20-poly1305 and provision a 256-bit ChaCha20Poly1305 key with
Encrypt and Decrypt in its usage mask. The server must support that algorithm.
ChaCha20-Poly1305 uses a 12-byte nonce and a 16-byte authentication tag; the
iv_length option is only available with AES-GCM.
To use AES-GCM-SIV, set cipher=aes-gcm-siv&mode=<vendor-mode> and provision an AES key with Encrypt and Decrypt in its usage mask.
KMIP does not assign a standard Block Cipher Mode to AES-GCM-SIV.
Use the value documented by the server, written as a hexadecimal string between 0x80000000 and 0x8FFFFFFF.
For example, cipher=aes-gcm-siv&mode=0x80000002 selects a server's documented 0x80000002 mode; that value is not a default for other servers.
AES-GCM-SIV uses a 12-byte nonce and a 16-byte authentication tag.
Ciphertexts store and authenticate their algorithm, mode and IV length.
Changing cipher affects new ciphertexts; earlier AES-GCM and
ChaCha20-Poly1305 ciphertexts remain readable if the server and key support them.
Decryption accepts a vendor mode only when it matches the configured mode.
Keep that option while ciphertexts using it remain stored.
It can also be set with cipher=aes-gcm, cipher=chacha20-poly1305 or with the default cipher to retain access to earlier AES-GCM-SIV ciphertexts while writing new ciphertexts with another cipher.
Encryption limits
The bridge draws a random IV for each encryption and sends it to the server.
Because the IV is random, NIST SP 800-38D limits an AES-GCM key to 2^32 encryptions, even with a longer iv_length.
ChaCha20-Poly1305 also uses random 96-bit nonces, so apply the same limit to its keys.
The limit is per server key.
It includes the encryptions of every application that uses that key.
EnvelopeEncrypter wraps a new data key with the master key for each envelope.
So each envelope counts as one encryption.
StoredEnvelopeEncrypter uses one stored data key for many payloads, so it needs far fewer encryptions with the master key.
AES-GCM-SIV resists nonce misuse.
With AES-GCM-SIV, a repeated nonce only reveals that the same plaintext was encrypted twice with the same AAD.
Your server may support it with a vendor mode, see the mode option above.
Key rotation
Before retiring a master key, migrate data encrypted under it. For the direct
Ciphertext and self-contained Envelope APIs shown above, decrypt and
re-encrypt the data with the new key. The built-in rewrap command only updates
data keys in a registered RewrappableDataKeyStoreInterface; rewrap those
stored keys before revoking or destroying the old master key.