kmip-go

June 3, 2026 Β· View on GitHub

Go Reference license test Go Report Card

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 protocol specification.

πŸš€ Features

  • 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
  • HTTPS Transport: Optional KMIP-over-HTTPS with TTLV, XML, or JSON wire formats (opt-in sub-package)
  • 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

πŸ“š Table of Contents

πŸ“¦ Installation

go get github.com/ovh/kmip-go@latest

πŸƒ Quick Start

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))
}

πŸ”§ Client API

Connection and Configuration

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

	// Message size limit (default: 1 MB, < 0 disables)
	kmipclient.WithMaxMessageSize(2 * 1024 * 1024),         // 2 MB limit

	// Middleware
	kmipclient.WithMiddlewares(
		kmipclient.CorrelationValueMiddleware(uuid.NewString),
		kmipclient.DebugMiddleware(os.Stdout, ttlv.MarshalXML),
		kmipclient.TimeoutMiddleware(30*time.Second),
	),
)

HTTP Transport

By default the client speaks KMIP's native TTLV-over-TLS stream protocol. For servers that expose KMIP over HTTPS, opt into the HTTP transport via the kmipclient/kmiphttp sub-package. Importing kmipclient alone does not link net/http; only callers that use kmiphttp pay that cost.

import (
	"github.com/ovh/kmip-go/kmipclient"
	"github.com/ovh/kmip-go/kmipclient/kmiphttp"
)

Requests are POSTed to https://<addr><path>; the standard TLS options apply unchanged. The scheme is hard-coded to https: pass a bare host:port (no http:// or https:// prefix), since HTTPS is implicit and a scheme prefix is rejected at Dial time.

client, err := kmipclient.Dial(
	"kms.example.com:5696",
	kmiphttp.WithTransport("/kmip"),
	kmipclient.WithClientCertFiles("cert.pem", "key.pem"),
)

The default wire format is binary TTLV; pick XML or JSON with kmiphttp.WithWireFormat:

client, err := kmipclient.Dial(
	"kms.example.com:5696",
	kmiphttp.WithTransport("/kmip",
		kmiphttp.WithWireFormat(kmiphttp.WireJSON),
	),
	kmipclient.WithClientCertFiles("cert.pem", "key.pem"),
)

Non-2xx responses are returned as a typed *kmiphttp.Error carrying StatusCode and a bounded Body excerpt β€” use errors.As rather than matching on the error string. See the API docs for kmiphttp.WithHeader (custom headers) and kmiphttp.WithClient (supplying your own *http.Client).

Key Creation and Management

Symmetric Keys

// 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()

Asymmetric Key Pairs

// 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

Object Registration

// 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()

Cryptographic Operations

Encryption and Decryption

// 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)

Digital Signatures

// 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)

Go crypto.Signer Interface

// 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)

Key Lifecycle Management

Key States and Activation

// 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()

Attribute Management

// 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()

Key Discovery

// 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)
}

Batch Operations

// 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)
	}
}

Low-Level Operations

// 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

πŸ–₯️ Server API

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).
		WithMaxMessageSize(2 * 1024 * 1024) // 2 MB limit (default: 1 MB, < 0 disables limit)

	log.Println("Starting KMIP server on :5696")
	if err := server.Serve(); err != nil {
		log.Fatal(err)
	}
}

πŸš€ Advanced Features

Custom Middleware

// 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),
	),
)

Error Handling Patterns

// 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
}

Working with TTLV Encoding

// 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)
}

πŸ” Authentication

Client Certificate Authentication

// 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"),
)

Username/Password Authentication

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

Device Authentication

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",
			},
		},
	},
}

πŸ’‘ Examples

For comprehensive examples, see the examples directory:

πŸ“‹ Implementation Status

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

Messages

v1.0v1.1v1.2v1.3v1.4
Request Messageβœ…βœ…βœ…βœ…βœ…
Response Messageβœ…βœ…βœ…βœ…βœ…

Operations

Operationv1.0v1.1v1.2v1.3v1.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❌❌❌❌❌
DiscoverN/Aβœ…βœ…βœ…βœ…
Re-key Key PairN/Aβœ…βœ…βœ…βœ…
EncryptN/AN/Aβœ…βœ…βœ…
DecryptN/AN/Aβœ…βœ…βœ…
SignN/AN/Aβœ…βœ…βœ…
Signature VerifyN/AN/Aβœ…βœ…βœ…
MACN/AN/A❌❌❌
MAC VerifyN/AN/A❌❌❌
RNG RetrieveN/AN/A❌❌❌
RNG SeedN/AN/A❌❌❌
HashN/AN/A❌❌❌
Create Split KeyN/AN/A❌❌❌
Join Split KeyN/AN/A❌❌❌
ExportN/AN/AN/AN/Aβœ…
ImportN/AN/AN/AN/Aβœ…

Managed Objects

Objectv1.0v1.1v1.2v1.3v1.4
Certificateβœ…βœ…βœ…βœ…βœ…
Symmetric Keyβœ…βœ…βœ…βœ…βœ…
Public Keyβœ…βœ…βœ…βœ…βœ…
Private Keyβœ…βœ…βœ…βœ…βœ…
Split Keyβœ…βœ…βœ…βœ…βœ…
Templateβœ…βœ…βœ…πŸ’€πŸ’€
Secret Dataβœ…βœ…βœ…βœ…βœ…
Opaque Objectβœ…βœ…βœ…βœ…βœ…
PGP KeyN/AN/Aβœ…βœ…βœ…

Base Objects

Objectv1.0v1.1v1.2v1.3v1.4
Attributeβœ…βœ…βœ…βœ…βœ…
Β Credentialβœ…βœ…βœ…βœ…βœ…
Β Key Blockβœ…βœ…βœ…βœ…βœ…
Key Valueβœ…βœ…βœ…βœ…βœ…
Key Wrapping Dataβœ…βœ…βœ…βœ…βœ…
Key Wrapping Specificationβœ…βœ…βœ…βœ…βœ…
Transparent Key Structures🚧🚧🚧🚧🚧
Template-Attribute Structuresβœ…βœ…βœ…βœ…βœ…
Extension InformationN/Aβœ…βœ…βœ…βœ…
DataN/AN/Aβœ…βœ…βœ…
Data LengthN/AN/A❌❌❌
Signature DataN/AN/Aβœ…βœ…βœ…
MAC DataN/AN/A❌❌❌
NonceN/AN/Aβœ…βœ…βœ…
Correlation ValueN/AN/AN/Aβœ…βœ…
Init IndicatorN/AN/AN/Aβœ…βœ…
Final IndicatorN/AN/AN/Aβœ…βœ…
RNG ParameterN/AN/AN/Aβœ…βœ…
Profile InformationN/AN/AN/Aβœ…βœ…
Validation InformationN/AN/AN/Aβœ…βœ…
Capability InformationN/AN/AN/Aβœ…βœ…
Authenticated Encryption Additional DataN/AN/AN/AN/Aβœ…
Authenticated Encryption TagN/AN/AN/AN/Aβœ…

Transparent Key Structures

Objectv1.0v1.1v1.2v1.3v1.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/PublicN/AN/AN/Aβœ…βœ…

Attributes

Attributev1.0v1.1v1.2v1.3v1.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 LengthN/Aβœ…βœ…βœ…βœ…
X.509 Certificate IdentifierN/Aβœ…βœ…βœ…βœ…
X.509 Certificate SubjectN/Aβœ…βœ…βœ…βœ…
X.509 Certificate IssuerN/Aβœ…βœ…βœ…βœ…
Digital Signature AlgorithmN/Aβœ…βœ…βœ…βœ…
FreshN/Aβœ…βœ…βœ…βœ…
Alternative NameN/AN/Aβœ…βœ…βœ…
Key Value PresentN/AN/Aβœ…βœ…βœ…
Key Value LocationN/AN/Aβœ…βœ…βœ…
Original Creation DateN/AN/Aβœ…βœ…βœ…
Random Number GeneratorN/AN/AN/Aβœ…βœ…
PKCS#12 Friendly NameN/AN/AN/AN/Aβœ…
DescriptionN/AN/AN/AN/Aβœ…
CommentN/AN/AN/AN/Aβœ…
SensitiveN/AN/AN/AN/Aβœ…
Always SensitiveN/AN/AN/AN/Aβœ…
ExtractableN/AN/AN/AN/Aβœ…
Never ExtractableN/AN/AN/AN/Aβœ…

πŸ› οΈ Contributing

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

πŸ”§ Troubleshooting

Common Issues

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),
	),
)

πŸ› οΈ Development

Building and Testing

# 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 ./...

Code Quality

# Format code
go fmt ./...

# Run linter (requires golangci-lint)
golangci-lint run

# Build examples
go build ./examples/...

πŸ“„ License

This project is licensed under the Apache License 2.0. See the LICENSE file for details.

πŸ†˜ Support

πŸ™ Acknowledgments

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.