A comprehensive Go implementation of the Key Management Interoperability Protocol (KMIP), supporting KMIP versions 1.0 through 1.4. This library provides both client and server implementations with full support for cryptographic operations, key lifecycle management, and secure communication. See KMIP v1.4 protocole specification.
- Full KMIP Protocol Support: Implements KMIP v1.0 to v1.4 specifications
- Complete Client Library: High-level fluent API with comprehensive operation support
- Server Implementation: Production-ready KMIP server components
- Multiple Encoding Formats: Binary TTLV, XML, JSON, and human-readable text formats
- Extensible: Easily declare user defined KMIP types and extensions
- Comprehensive Cryptographic Operations: Key generation, encryption, decryption, signing, verification
- Flexible Authentication: Mutual TLS, username/password, device, and attestation-based authentication
- TLS Security: Built-in TLS support with client certificate authentication
- Batch Operations: Support for batching multiple operations in a single request
- Middleware System: Extensible middleware for logging, debugging, and custom functionality
- Go standard crypto compatible: Implements crypto.Signer interface and support cryptographic key types from the standard library
- Production Ready: Developed and tested against OVHcloud KMS
- Installation
- Quick Start
- Client API
- Server API
- Advanced Features
- Authentication
- Examples
- Implementation Status
- Contributing
- Troubleshooting
- Development
- License
- Support
- Acknowledgments
go get github.com/ovh/kmip-go@latest
package main
import (
"fmt"
"log"
"github.com/ovh/kmip-go"
"github.com/ovh/kmip-go/kmipclient"
)
func main() {
// Connect to KMIP server
client, err := kmipclient.Dial(
"your-kmip-server:5696",
kmipclient.WithClientCertFiles("cert.pem", "key.pem"),
)
if err != nil {
log.Fatal(err)
}
defer client.Close()
// Create an AES key
resp := client.Create().
AES(256, kmip.CryptographicUsageEncrypt|kmip.CryptographicUsageDecrypt).
WithName("my-encryption-key").
MustExec()
fmt.Printf("Created AES key: %s\n", resp.UniqueIdentifier)
// Activate the key
client.Activate(resp.UniqueIdentifier).MustExec()
// Encrypt some data
plaintext := []byte("Hello, KMIP!")
encrypted := client.Encrypt(resp.UniqueIdentifier).
WithCryptographicParameters(kmip.AES_GCM).
Data(plaintext).
MustExec()
fmt.Printf("Encrypted data length: %d bytes\n", len(encrypted.Data))
}
import (
"os"
"time"
"github.com/google/uuid"
"github.com/ovh/kmip-go"
"github.com/ovh/kmip-go/kmipclient"
"github.com/ovh/kmip-go/ttlv"
)
// Connect with comprehensive options
client, err := kmipclient.Dial(
"eu-west-rbx.okms.ovh.net:5696",
// TLS Configuration
kmipclient.WithRootCAFile("ca.pem"), // Custom CA certificate
kmipclient.WithClientCertFiles("cert.pem", "key.pem"), // Client certificates
kmipclient.WithClientCertPEM(certPEM, keyPEM), // Client certs from PEM data
kmipclient.WithServerName("kmip.example.com"), // Server name for TLS
kmipclient.WithTlsConfig(tlsConfig), // Custom TLS config
// Protocol Version Configuration
kmipclient.WithKmipVersions(kmip.V1_4, kmip.V1_3), // Supported versions
kmipclient.EnforceVersion(kmip.V1_4), // Enforce specific version
// Middleware
kmipclient.WithMiddlewares(
kmipclient.CorrelationValueMiddleware(uuid.NewString),
kmipclient.DebugMiddleware(os.Stdout, ttlv.MarshalXML),
kmipclient.TimeoutMiddleware(30*time.Second),
),
)
// AES Keys
aes128 := client.Create().AES(128, kmip.CryptographicUsageEncrypt|kmip.CryptographicUsageDecrypt)
aes256 := client.Create().AES(256, kmip.CryptographicUsageEncrypt|kmip.CryptographicUsageDecrypt)
// Other symmetric algorithms
tdes := client.Create().TDES(192, kmip.CryptographicUsageEncrypt)
skipjack := client.Create().Skipjack(kmip.CryptographicUsageEncrypt) // 80-bit key
// With attributes
key := client.Create().
AES(256, kmip.CryptographicUsageEncrypt|kmip.CryptographicUsageDecrypt).
WithName("my-encryption-key").
WithAttribute(kmip.AttributeNameDescription, "Production encryption key").
WithUsageLimit(1000000, kmip.UsageLimitsUnitByte).
MustExec()
// RSA Key Pairs
rsaKeyPair := client.CreateKeyPair().
RSA(2048, kmip.CryptographicUsageSign, kmip.CryptographicUsageVerify).
WithName("my-rsa-keypair").
MustExec()
// ECDSA Key Pairs
ecdsaKeyPair := client.CreateKeyPair().
ECDSA(kmip.RecommendedCurveP_256, kmip.CryptographicUsageSign, kmip.CryptographicUsageVerify).
WithName("my-ecdsa-keypair").
MustExec()
// Access individual keys
fmt.Printf("Private Key ID: %s\n", ecdsaKeyPair.PrivateKeyUniqueIdentifier)
fmt.Printf("Public Key ID: %s\n", ecdsaKeyPair.PublicKeyUniqueIdentifier
// Register existing cryptographic material
registered := client.Register().
Object(existingKeyObject).
WithName("imported-object").
MustExec()
// Register with specific attributes
cert := client.Register().
Certificate(kmip.CertificateTypeX_509, x509Cert).
WithName("server-certificate").
WithAttribute(kmip.AttributeNameCertificateType, kmip.CertificateTypeX_509).
MustExec()
// Basic encryption
plaintext := []byte("sensitive data")
encrypted := client.Encrypt(keyID).
WithCryptographicParameters(kmip.CryptographicParameters{ /* parameters */ }).
Data(plaintext).
MustExec()
// Encryption with specific parameters
encrypted := client.Encrypt(keyID).
WithCryptographicParameters(kmip.AES_GCM).
WithIvCounterNonce(iv).
WithAAD(additionalData).
Data(plaintext).
MustExec()
// Decryption
decrypted := client.Decrypt(keyID).
WithCryptographicParameters(kmip.AES_GCM).
WithIvCounterNonce(encrypted.IVCounterNonce).
WithAAD(additionalData).
WithAuthTag(encrypted.AuthenticatedEncryptionTag).
Data(encrypted.Data).
MustExec()
fmt.Printf("Decrypted: %s\n", decrypted.Data)
// Sign data
data := []byte("document to sign")
signature := client.Sign(privateKeyID).
WithCryptographicParameters(kmip.CryptographicParameters{ /* parameters */ }).
Data(data).
MustExec()
// Sign pre-hashed data
hashedData := sha256.Sum256(data)
signature = client.Sign(privateKeyID).
WithCryptographicParameters(kmip.CryptographicParameters{ /* parameters */ }).
DigestedData(hashedData[:]).
MustExec()
// Verify signature
verified := client.SignatureVerify(publicKeyID).
WithCryptographicParameters(kmip.CryptographicParameters{ /* parameters */ }).
Data(data).
Signature(signature.SignatureData).
MustExec()
fmt.Printf("Signature valid: %t\n", verified.ValidityIndicator == kmip.ValidityIndicatorValid)
// Get a crypto.Signer for use with standard Go crypto packages
signer, err := client.Signer(ctx, privateKeyID, publicKeyID)
if err != nil {
log.Fatal(err)
}
// Use with crypto packages
hash := sha256.Sum256(data)
signature, err := signer.Sign(rand.Reader, hash[:], crypto.SHA256)
if err != nil {
log.Fatal(err)
}
// Use with x509 certificate signing
template := &x509.Certificate{/*...*/}
certDER, err := x509.CreateCertificate(rand.Reader, template, caCert, signer.Public(), signer)
// Activate a key
client.Activate(keyID).MustExec()
// Check key state
attrs := client.GetAttributes(keyID, kmip.AttributeNameState).MustExec()
for _, attr := range attrs.Attribute {
if attr.AttributeName == kmip.AttributeNameState {
fmt.Printf("Key state: %v\n", attr.AttributeValue)
}
}
// Revoke a key
client.Revoke(keyID).
WithRevocationReasonCode(kmip.RevocationReasonCodeKeyCompromise).
WithRevocationMessage("Security incident detected").
MustExec()
// Archive and recover
client.Archive(keyID).MustExec()
client.Recover(keyID).MustExec()
// Destroy key (irreversible)
client.Destroy(keyID).MustExec()
// Get all attributes
allAttrs := client.GetAttributes(keyID).MustExec()
// Get specific attributes
specificAttrs := client.GetAttributes(keyID,
kmip.AttributeNameState,
kmip.AttributeNameCryptographicUsageMask,
kmip.AttributeNameCryptographicLength,
).MustExec()
// Get attribute list (names only)
attrList := client.GetAttributeList(keyID).MustExec()
// Add attributes
client.AddAttribute(keyID, kmip.AttributeNameDescription, "Updated description").MustExec()
// Modify attributes
client.ModifyAttribute(keyID, kmip.AttributeNameName, kmip.Name{
NameType: kmip.NameTypeUninterpretedTextString,
NameValue: "updated-key-name",
}).MustExec()
// Delete attributes
client.DeleteAttribute(keyID, kmip.AttributeNameDescription).MustExec()
// Find keys by name
keys := client.Locate().
WithName("production-key").
MustExec()
// Complex search criteria
keys = client.Locate().
WithObjectType(kmip.ObjectTypeSymmetricKey).
WithAttribute(kmip.AttributeNameCryptographicAlgorithm, kmip.CryptographicAlgorithmAES).
WithAttribute(kmip.AttributeNameCryptographicLength, int32(256)).
WithUsageLimit(1000000, kmip.UsageLimitsUnitByte).
MustExec()
for _, keyID := range keys.UniqueIdentifier {
fmt.Printf("Found key: %s\n", keyID)
}
// Hight-Level batch builder
result := client.Create().
AES(256, kmip.CryptographicUsageEncrypt|kmip.CryptographicUsageDecrypt).
WithName("batch-key").
Then(func(client *kmipclient.Client) kmipclient.PayloadBuilder {
// Use ID returned from previous operation
return client.Activate("")
}).
Then(func(client *kmipclient.Client) kmipclient.PayloadBuilder {
// Use ID returned from previous operation
return client.GetAttributes("", kmip.AttributeNameState)
}).
MustExec()
// Manual batch creation
createReq1 := &payloads.CreateRequestPayload{ /* ... */ }
createReq2 := &payloads.ActivateRequestPayload{ /* ... */ }
activateReq := &payloads.GetAttributesRequestPayload{ /* ... */ }
result, err = client.Batch(ctx, createReq1, createReq2, activateReq)
if err != nil {
log.Fatal(err)
}
// Process batch results
for i, resp := range result {
if err := resp.Err(); err != nil {
fmt.Printf("Operation %d failed: %s - %s\n", i+1, resp.ResultStatus, resp.ResultReason)
continue
}
switch payload := resp.ResponsePayload.(type) {
case *payloads.CreateResponsePayload:
fmt.Printf("Created key %d: %s\n", i+1, payload.UniqueIdentifier)
case *payloads.ActivateResponsePayload:
fmt.Printf("Activated key: %s\n", payload.UniqueIdentifier)
}
}
// Direct payload construction for maximum control
request := payloads.CreateRequestPayload{
ObjectType: kmip.ObjectTypeSymmetricKey,
TemplateAttribute: kmip.TemplateAttribute{
Attribute: []kmip.Attribute{
{
AttributeName: kmip.AttributeNameCryptographicAlgorithm,
AttributeValue: kmip.CryptographicAlgorithmAES,
},
{
AttributeName: kmip.AttributeNameCryptographicLength,
AttributeValue: int32(256),
},
{
AttributeName: kmip.AttributeNameCryptographicUsageMask,
AttributeValue: kmip.CryptographicUsageEncrypt | kmip.CryptographicUsageDecrypt,
},
},
},
}
// Send request
response, err := client.Request(ctx, &request)
if err != nil {
log.Fatal(err)
}
keyID := response.(*payloads.CreateResponsePayload).UniqueIdentifier
package main
import (
"context"
"crypto/tls"
"log"
"net"
"github.com/ovh/kmip-go"
"github.com/ovh/kmip-go/kmipserver"
)
// Implement the RequestHandler interface
type MyKMIPHandler struct {
// Your key management backend
}
func (h *MyKMIPHandler) HandleRequest(ctx context.Context, req *kmip.RequestMessage) *kmip.ResponseMessage {
// Process KMIP request and return response
// Implement your key management logic here
return &kmip.ResponseMessage{
Header: kmip.ResponseHeader{
ProtocolVersion: req.Header.ProtocolVersion,
BatchCount: req.Header.BatchCount,
},
BatchItem: []kmip.ResponseBatchItem{
// Process each batch item
},
}
}
func main() {
// Setup TLS
cert, err := tls.LoadX509KeyPair("server.crt", "server.key")
if err != nil {
log.Fatal(err)
}
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
ClientAuth: tls.RequireAndVerifyClientCert,
}
// Create listener
listener, err := tls.Listen("tcp", ":5696", tlsConfig)
if err != nil {
log.Fatal(err)
}
// Create and start server
handler := &MyKMIPHandler{}
server := kmipserver.NewServer(listener, handler)
log.Println("Starting KMIP server on :5696")
if err := server.Serve(); err != nil {
log.Fatal(err)
}
}
// Rate limiting middleware
func RateLimitMiddleware(limiter *rate.Limiter) kmipclient.Middleware {
return func(next kmipclient.Next, ctx context.Context, req *kmip.RequestMessage) (*kmip.ResponseMessage, error) {
// Wait for rate limit
if err := limiter.Wait(ctx); err != nil {
return nil, fmt.Errorf("rate limit exceeded: %w", err)
}
return next(ctx, req)
}
}
// Retry middleware
func RetryMiddleware(maxRetries int) kmipclient.Middleware {
return func(next kmipclient.Next, ctx context.Context, req *kmip.RequestMessage) (*kmip.ResponseMessage, error) {
var lastErr error
for i := 0; i <= maxRetries; i++ {
resp, err := next(ctx, req)
if err == nil {
return resp, nil
}
lastErr = err
// Exponential backoff
if i < maxRetries {
backoff := time.Duration(1<<uint(i)) * time.Second
select {
case <-time.After(backoff):
case <-ctx.Done():
return nil, ctx.Err()
}
}
}
return nil, fmt.Errorf("request failed after %d retries: %w", maxRetries, lastErr)
}
}
// Use middleware
client, err := kmipclient.Dial(
"server:5696",
kmipclient.WithMiddlewares(
RateLimitMiddleware(rate.NewLimiter(10, 1)),
RetryMiddleware(3),
),
)
// Comprehensive error handling
resp, err := client.Create().AES(256, kmip.CryptographicUsageEncrypt).Exec()
if err != nil {
// Network or connection errors
var netErr net.Error
if errors.As(err, &netErr) {
log.Printf("Network error: %v (timeout: %t, temp: %t)",
netErr, netErr.Timeout(), netErr.Temporary())
return
}
// TLS errors
var tlsErr tls.RecordHeaderError
if errors.As(err, &tlsErr) {
log.Printf("TLS error: %v", tlsErr)
return
}
// KMIP protocol errors
log.Printf("KMIP operation failed: %v", err)
return
}
// Batch operation error handling
results, err := client.Batch(ctx, req1, req2, req3)
if err != nil {
log.Printf("Batch request failed: %v", err)
return
}
// Check individual results
for i, result := range results {
if err := result.Err(); err != nil {
log.Printf("Operation %d failed: %v", i, err)
continue
}
// Process successful result
switch payload := result.ResponsePayload.(type) {
case *payloads.CreateResponsePayload:
log.Printf("Created key: %s", payload.UniqueIdentifier)
case *payloads.GetResponsePayload:
log.Printf("Retrieved object type: %s", payload.ObjectType)
}
}
// Or check all the batch item responses for error at once
responses, err := results.Unwrap()
if err != nil {
log.Printf("Batch response has some errors: %v", err)
return
}
// Marshal to different formats
request := &payloads.CreateRequestPayload{...}
// Binary TTLV (native KMIP format)
binaryData := ttlv.MarshalTTLV(request)
// XML format (human-readable)
xmlData := ttlv.MarshalXML(request)
// JSON format
jsonData := ttlv.MarshalJSON(request)
// Text format (debugging)
textData := ttlv.MarshalText(request)
// Unmarshal from TTLV
var decoded payloads.CreateRequestPayload
err := ttlv.UnmarshalTTLV(binaryData, &decoded)
if err != nil {
log.Fatal(err)
}
// From files
client, err := kmipclient.Dial(
"server:5696",
kmipclient.WithClientCertFiles("cert.pem", "key.pem"),
)
// From PEM data
client, err := kmipclient.Dial(
"server:5696",
kmipclient.WithClientCertPEM(certPEM, keyPEM),
)
// Multiple certificates
client, err := kmipclient.Dial(
"server:5696",
kmipclient.WithClientCertFiles("cert1.pem", "key1.pem"),
kmipclient.WithClientCertFiles("cert2.pem", "key2.pem"),
)
Can be handled with a custom client middleware which inserts the credentials in the requests headers.
// Basic authentication
auth := kmip.Authentication{
Credential: kmip.Credential{
CredentialType: kmip.CredentialTypeUsernameAndPassword,
CredentialValue: kmip.CredentialValue{
UserPassword: &kmip.CredentialValueUserPassword{
Username: "admin",
Password: "secret",
},
},
},
}
// Add to request headers manually or use middleware
Can be handled with a custom client middleware which inserts the credentials in the requests headers.
// Device-based authentication
deviceAuth := kmip.Authentication{
Credential: kmip.Credential{
CredentialType: kmip.CredentialTypeDevice,
CredentialValue: kmip.CredentialValue{
Device: &kmip.CredentialValueDevice{
DeviceSerialNumber: "SN123456789",
DeviceIdentifier: "device-001",
NetworkIdentifier: "192.168.1.100",
},
},
},
}
For comprehensive examples, see the examples directory:
- examples/encrypt_decrypt.go - Encryption/decryption workflows
- examples/sign_verify.go - Digital signature operations
- examples/batches.go - Batch processing examples
This library implements the OASIS KMIP (Key Management Interoperability Protocol) specifications:
Legend:
- N/A : Not Applicable
- β : Fully compatible
- β : Not implemented
- π§ : Work in progress / Partially compatible
- π : Deprecated
v1.0 | v1.1 | v1.2 | v1.3 | v1.4 | |
---|---|---|---|---|---|
Request Message | β | β | β | β | β |
Response Message | β | β | β | β | β |
Operation | v1.0 | v1.1 | v1.2 | v1.3 | v1.4 |
---|---|---|---|---|---|
Create | β | β | β | β | β |
Create Key Pair | β | β | β | β | β |
Register | β | β | β | β | β |
Re-key | β | β | β | β | β |
DeriveKey | β | β | β | β | β |
Certify | β | β | β | β | β |
Re-certify | β | β | β | β | β |
Locate | β | β | β | β | β |
Check | β | β | β | β | β |
Get | β | β | β | β | β |
Get Attributes | β | β | β | β | β |
Get Attribute List | β | β | β | β | β |
Add Attribute | β | β | β | β | β |
Modify Attribute | β | β | β | β | β |
Delete Attribute | β | β | β | β | β |
Obtain Lease | β | β | β | β | β |
Get Usage Allocation | β | β | β | β | β |
Activate | β | β | β | β | β |
Revoke | β | β | β | β | β |
Destroy | β | β | β | β | β |
Archive | β | β | β | β | β |
Recover | β | β | β | β | β |
Validate | β | β | β | β | β |
Query | β | β | β | β | β |
Cancel | β | β | β | β | β |
Poll | β | β | β | β | β |
Notify | β | β | β | β | β |
Put | β | β | β | β | β |
Discover | N/A | β | β | β | β |
Re-key Key Pair | N/A | β | β | β | β |
Encrypt | N/A | N/A | β | β | β |
Decrypt | N/A | N/A | β | β | β |
Sign | N/A | N/A | β | β | β |
Signature Verify | N/A | N/A | β | β | β |
MAC | N/A | N/A | β | β | β |
MAC Verify | N/A | N/A | β | β | β |
RNG Retrieve | N/A | N/A | β | β | β |
RNG Seed | N/A | N/A | β | β | β |
Hash | N/A | N/A | β | β | β |
Create Split Key | N/A | N/A | β | β | β |
Join Split Key | N/A | N/A | β | β | β |
Export | N/A | N/A | N/A | N/A | β |
Import | N/A | N/A | N/A | N/A | β |
Object | v1.0 | v1.1 | v1.2 | v1.3 | v1.4 |
---|---|---|---|---|---|
Certificate | β | β | β | β | β |
Symmetric Key | β | β | β | β | β |
Public Key | β | β | β | β | β |
Private Key | β | β | β | β | β |
Split Key | β | β | β | β | β |
Template | β | β | β | π | π |
Secret Data | β | β | β | β | β |
Opaque Object | β | β | β | β | β |
PGP Key | N/A | N/A | β | β | β |
Object | v1.0 | v1.1 | v1.2 | v1.3 | v1.4 |
---|---|---|---|---|---|
Attribute | β | β | β | β | β |
Β Credential | β | β | β | β | β |
Β Key Block | β | β | β | β | β |
Key Value | β | β | β | β | β |
Key Wrapping Data | β | β | β | β | β |
Key Wrapping Specification | β | β | β | β | β |
Transparent Key Structures | π§ | π§ | π§ | π§ | π§ |
Template-Attribute Structures | β | β | β | β | β |
Extension Information | N/A | β | β | β | β |
Data | N/A | N/A | β | β | β |
Data Length | N/A | N/A | β | β | β |
Signature Data | N/A | N/A | β | β | β |
MAC Data | N/A | N/A | β | β | β |
Nonce | N/A | N/A | β | β | β |
Correlation Value | N/A | N/A | N/A | β | β |
Init Indicator | N/A | N/A | N/A | β | β |
Final Indicator | N/A | N/A | N/A | β | β |
RNG Parameter | N/A | N/A | N/A | β | β |
Profile Information | N/A | N/A | N/A | β | β |
Validation Information | N/A | N/A | N/A | β | β |
Capability Information | N/A | N/A | N/A | β | β |
Authenticated Encryption Additional Data | N/A | N/A | N/A | N/A | β |
Authenticated Encryption Tag | N/A | N/A | N/A | N/A | β |
Object | v1.0 | v1.1 | v1.2 | v1.3 | v1.4 |
---|---|---|---|---|---|
Symmetric Key | β | β | β | β | β |
DSA Private/Public Key | β | β | β | β | β |
RSA Private/Public Key | β | β | β | β | β |
DH Private/Public Key | β | β | β | β | β |
ECDSA Private/Public Key | β | β | β | π | π |
ECDH Private/Public Key | β | β | β | π | π |
ECMQV Private/Public | β | β | β | π | π |
EC Private/Public | N/A | N/A | N/A | β | β |
Attribute | v1.0 | v1.1 | v1.2 | v1.3 | v1.4 |
---|---|---|---|---|---|
Unique Identifier | β | β | β | β | β |
Name | β | β | β | β | β |
Object Type | β | β | β | β | β |
Cryptographic Algorithm | β | β | β | β | β |
Cryptographic Length | β | β | β | β | β |
Cryptographic Parameters | β | β | β | β | β |
Cryptographic Domain Parameters | β | β | β | β | β |
Certificate Type | β | β | β | β | β |
Certificate Identifier | β | π | π | π | π |
Certificate Subject | β | π | π | π | π |
Certificate Issuer | β | π | π | π | π |
Digest | β | β | β | β | β |
Operation Policy Name | β | β | β | π | π |
Cryptographic Usage Mask | β | β | β | β | β |
Lease Time | β | β | β | β | β |
Usage Limits | β | β | β | β | β |
State | β | β | β | β | β |
Initial Date | β | β | β | β | β |
Activation Date | β | β | β | β | β |
Process Start Date | β | β | β | β | β |
Protect Stop Date | β | β | β | β | β |
Deactivation Date | β | β | β | β | β |
Destroy Date | β | β | β | β | β |
Compromise Occurrence Date | β | β | β | β | β |
Compromise Date | β | β | β | β | β |
Revocation Reason | β | β | β | β | β |
Archive Date | β | β | β | β | β |
Object Group | β | β | β | β | β |
Link | β | β | β | β | β |
Application Specific Information | β | β | β | β | β |
Contact Information | β | β | β | β | β |
Last Change Date | β | β | β | β | β |
Custom Attribute | β | β | β | β | β |
Certificate Length | N/A | β | β | β | β |
X.509 Certificate Identifier | N/A | β | β | β | β |
X.509 Certificate Subject | N/A | β | β | β | β |
X.509 Certificate Issuer | N/A | β | β | β | β |
Digital Signature Algorithm | N/A | β | β | β | β |
Fresh | N/A | β | β | β | β |
Alternative Name | N/A | N/A | β | β | β |
Key Value Present | N/A | N/A | β | β | β |
Key Value Location | N/A | N/A | β | β | β |
Original Creation Date | N/A | N/A | β | β | β |
Random Number Generator | N/A | N/A | N/A | β | β |
PKCS#12 Friendly Name | N/A | N/A | N/A | N/A | β |
Description | N/A | N/A | N/A | N/A | β |
Comment | N/A | N/A | N/A | N/A | β |
Sensitive | N/A | N/A | N/A | N/A | β |
Always Sensitive | N/A | N/A | N/A | N/A | β |
Extractable | N/A | N/A | N/A | N/A | β |
Never Extractable | N/A | N/A | N/A | N/A | β |
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change. In any case, please follow Contribution Guidelines
Connection Problems
# Verify server connectivity
telnet your-kmip-server 5696
# Check TLS certificate issues
openssl s_client -connect your-kmip-server:5696 -cert cert.pem -key key.pem
Authentication Failures
- Ensure client certificates are valid and not expired
- Verify the server accepts your certificate chain
- Check that the username/password credentials are correct, if used
- Verify the certificate key usage allows client authentication
Protocol Version Issues
// Force a specific KMIP version
client, err := kmipclient.Dial(
"server:5696",
kmipclient.EnforceVersion(kmip.V1_4),
)
Debug Logging
// Enable debug logging to see TTLV messages
client, err := kmipclient.Dial(
"server:5696",
kmipclient.WithMiddlewares(
kmipclient.DebugMiddleware(os.Stdout, ttlv.MarshalXML),
),
)
# Clone repository
git clone https://github.com/ovh/kmip-go.git
cd kmip-go
# Install dependencies
go mod download
# Run all tests
go test -race ./...
# Run integration tests (requires KMIP server)
go test -race -tags=integration ./...
# Format code
go fmt ./...
# Run linter (requires golangci-lint)
golangci-lint run
# Build examples
go build ./examples/...
This project is licensed under the Apache License 2.0. See the LICENSE file for details.
- Documentation: Go Reference
- Issues: GitHub Issues
- OVHcloud KMS: Documentation
- KMIP Standard:
This library is developed and maintained by OVHcloud, with contributions from the open source community. It is designed to work seamlessly with OVHcloud KMS but is compatible with any KMIP-compliant key management system.
Note: This library is primarily developed and tested against OVHcloud KMS. While it aims for full KMIP compliance, some features may work differently with other KMIP implementations. Please report any compatibility issues.