Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A golang KMIP client and server library, supporting KMIP v1.0 to v1.4.

License

NotificationsYou must be signed in to change notification settings

ovh/kmip-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

55 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Go ReferencelicensetestGo 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.SeeKMIP 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
  • 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 againstOVHcloud KMS

📚 Table of Contents

📦 Installation

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

🏃 Quick Start

package mainimport ("fmt""log""github.com/ovh/kmip-go""github.com/ovh/kmip-go/kmipclient")funcmain() {// Connect to KMIP serverclient,err:=kmipclient.Dial("your-kmip-server:5696",kmipclient.WithClientCertFiles("cert.pem","key.pem"),)iferr!=nil {log.Fatal(err)}deferclient.Close()// Create an AES keyresp:=client.Create().AES(256,kmip.CryptographicUsageEncrypt|kmip.CryptographicUsageDecrypt).WithName("my-encryption-key").MustExec()fmt.Printf("Created AES key: %s\n",resp.UniqueIdentifier)// Activate the keyclient.Activate(resp.UniqueIdentifier).MustExec()// Encrypt some dataplaintext:= []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 optionsclient,err:=kmipclient.Dial("eu-west-rbx.okms.ovh.net:5696",// TLS Configurationkmipclient.WithRootCAFile("ca.pem"),// Custom CA certificatekmipclient.WithClientCertFiles("cert.pem","key.pem"),// Client certificateskmipclient.WithClientCertPEM(certPEM,keyPEM),// Client certs from PEM datakmipclient.WithServerName("kmip.example.com"),// Server name for TLSkmipclient.WithTlsConfig(tlsConfig),// Custom TLS config// Protocol Version Configurationkmipclient.WithKmipVersions(kmip.V1_4,kmip.V1_3),// Supported versionskmipclient.EnforceVersion(kmip.V1_4),// Enforce specific version// Middlewarekmipclient.WithMiddlewares(kmipclient.CorrelationValueMiddleware(uuid.NewString),kmipclient.DebugMiddleware(os.Stdout,ttlv.MarshalXML),kmipclient.TimeoutMiddleware(30*time.Second),),)

Key Creation and Management

Symmetric Keys

// AES Keysaes128:=client.Create().AES(128,kmip.CryptographicUsageEncrypt|kmip.CryptographicUsageDecrypt)aes256:=client.Create().AES(256,kmip.CryptographicUsageEncrypt|kmip.CryptographicUsageDecrypt)// Other symmetric algorithmstdes:=client.Create().TDES(192,kmip.CryptographicUsageEncrypt)skipjack:=client.Create().Skipjack(kmip.CryptographicUsageEncrypt)// 80-bit key// With attributeskey:=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 PairsrsaKeyPair:=client.CreateKeyPair().RSA(2048,kmip.CryptographicUsageSign,kmip.CryptographicUsageVerify).WithName("my-rsa-keypair").MustExec()// ECDSA Key PairsecdsaKeyPair:=client.CreateKeyPair().ECDSA(kmip.RecommendedCurveP_256,kmip.CryptographicUsageSign,kmip.CryptographicUsageVerify).WithName("my-ecdsa-keypair").MustExec()// Access individual keysfmt.Printf("Private Key ID: %s\n",ecdsaKeyPair.PrivateKeyUniqueIdentifier)fmt.Printf("Public Key ID: %s\n", ecdsaKeyPair.PublicKeyUniqueIdentifier

Object Registration

// Register existing cryptographic materialregistered:=client.Register().Object(existingKeyObject).WithName("imported-object").MustExec()// Register with specific attributescert:=client.Register().Certificate(kmip.CertificateTypeX_509,x509Cert).WithName("server-certificate").WithAttribute(kmip.AttributeNameCertificateType,kmip.CertificateTypeX_509).MustExec()

Cryptographic Operations

Encryption and Decryption

// Basic encryptionplaintext:= []byte("sensitive data")encrypted:=client.Encrypt(keyID).WithCryptographicParameters(kmip.CryptographicParameters{/* parameters */ }).Data(plaintext).MustExec()// Encryption with specific parametersencrypted:=client.Encrypt(keyID).WithCryptographicParameters(kmip.AES_GCM).WithIvCounterNonce(iv).WithAAD(additionalData).Data(plaintext).MustExec()// Decryptiondecrypted:=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 datadata:= []byte("document to sign")signature:=client.Sign(privateKeyID).WithCryptographicParameters(kmip.CryptographicParameters{/* parameters */ }).Data(data).MustExec()// Sign pre-hashed datahashedData:=sha256.Sum256(data)signature=client.Sign(privateKeyID).WithCryptographicParameters(kmip.CryptographicParameters{/* parameters */ }).DigestedData(hashedData[:]).MustExec()// Verify signatureverified:=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 packagessigner,err:=client.Signer(ctx,privateKeyID,publicKeyID)iferr!=nil {log.Fatal(err)}// Use with crypto packageshash:=sha256.Sum256(data)signature,err:=signer.Sign(rand.Reader,hash[:],crypto.SHA256)iferr!=nil {log.Fatal(err)}// Use with x509 certificate signingtemplate:=&x509.Certificate{/*...*/}certDER,err:=x509.CreateCertificate(rand.Reader,template,caCert,signer.Public(),signer)

Key Lifecycle Management

Key States and Activation

// Activate a keyclient.Activate(keyID).MustExec()// Check key stateattrs:=client.GetAttributes(keyID,kmip.AttributeNameState).MustExec()for_,attr:=rangeattrs.Attribute {ifattr.AttributeName==kmip.AttributeNameState {fmt.Printf("Key state: %v\n",attr.AttributeValue)}}// Revoke a keyclient.Revoke(keyID).WithRevocationReasonCode(kmip.RevocationReasonCodeKeyCompromise).WithRevocationMessage("Security incident detected").MustExec()// Archive and recoverclient.Archive(keyID).MustExec()client.Recover(keyID).MustExec()// Destroy key (irreversible)client.Destroy(keyID).MustExec()

Attribute Management

// Get all attributesallAttrs:=client.GetAttributes(keyID).MustExec()// Get specific attributesspecificAttrs:=client.GetAttributes(keyID,kmip.AttributeNameState,kmip.AttributeNameCryptographicUsageMask,kmip.AttributeNameCryptographicLength,).MustExec()// Get attribute list (names only)attrList:=client.GetAttributeList(keyID).MustExec()// Add attributesclient.AddAttribute(keyID,kmip.AttributeNameDescription,"Updated description").MustExec()// Modify attributesclient.ModifyAttribute(keyID,kmip.AttributeNameName, kmip.Name{NameType:kmip.NameTypeUninterpretedTextString,NameValue:"updated-key-name",}).MustExec()// Delete attributesclient.DeleteAttribute(keyID,kmip.AttributeNameDescription).MustExec()

Key Discovery

// Find keys by namekeys:=client.Locate().WithName("production-key").MustExec()// Complex search criteriakeys=client.Locate().WithObjectType(kmip.ObjectTypeSymmetricKey).WithAttribute(kmip.AttributeNameCryptographicAlgorithm,kmip.CryptographicAlgorithmAES).WithAttribute(kmip.AttributeNameCryptographicLength,int32(256)).WithUsageLimit(1000000,kmip.UsageLimitsUnitByte).MustExec()for_,keyID:=rangekeys.UniqueIdentifier {fmt.Printf("Found key: %s\n",keyID)}

Batch Operations

// Hight-Level batch builderresult:=client.Create().AES(256,kmip.CryptographicUsageEncrypt|kmip.CryptographicUsageDecrypt).WithName("batch-key").Then(func(client*kmipclient.Client) kmipclient.PayloadBuilder {// Use ID returned from previous operationreturnclient.Activate("")}).Then(func(client*kmipclient.Client) kmipclient.PayloadBuilder {// Use ID returned from previous operationreturnclient.GetAttributes("",kmip.AttributeNameState)}).MustExec()// Manual batch creationcreateReq1:=&payloads.CreateRequestPayload{/* ... */ }createReq2:=&payloads.ActivateRequestPayload{/* ... */ }activateReq:=&payloads.GetAttributesRequestPayload{/* ... */ }result,err=client.Batch(ctx,createReq1,createReq2,activateReq)iferr!=nil {log.Fatal(err)}// Process batch resultsfori,resp:=rangeresult {iferr:=resp.Err();err!=nil {fmt.Printf("Operation %d failed: %s - %s\n",i+1,resp.ResultStatus,resp.ResultReason)continue}switchpayload:=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 controlrequest:= 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 requestresponse,err:=client.Request(ctx,&request)iferr!=nil {log.Fatal(err)}keyID:=response.(*payloads.CreateResponsePayload).UniqueIdentifier

🖥️ Server API

package mainimport ("context""crypto/tls""log""net""github.com/ovh/kmip-go""github.com/ovh/kmip-go/kmipserver")// Implement the RequestHandler interfacetypeMyKMIPHandlerstruct {// 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 herereturn&kmip.ResponseMessage{Header: kmip.ResponseHeader{ProtocolVersion:req.Header.ProtocolVersion,BatchCount:req.Header.BatchCount,},BatchItem: []kmip.ResponseBatchItem{// Process each batch item},}}funcmain() {// Setup TLScert,err:=tls.LoadX509KeyPair("server.crt","server.key")iferr!=nil {log.Fatal(err)}tlsConfig:=&tls.Config{Certificates: []tls.Certificate{cert},ClientAuth:tls.RequireAndVerifyClientCert,}// Create listenerlistener,err:=tls.Listen("tcp",":5696",tlsConfig)iferr!=nil {log.Fatal(err)}// Create and start serverhandler:=&MyKMIPHandler{}server:=kmipserver.NewServer(listener,handler)log.Println("Starting KMIP server on :5696")iferr:=server.Serve();err!=nil {log.Fatal(err)}}

🚀 Advanced Features

Custom Middleware

// Rate limiting middlewarefuncRateLimitMiddleware(limiter*rate.Limiter) kmipclient.Middleware {returnfunc(next kmipclient.Next,ctx context.Context,req*kmip.RequestMessage) (*kmip.ResponseMessage,error) {// Wait for rate limitiferr:=limiter.Wait(ctx);err!=nil {returnnil,fmt.Errorf("rate limit exceeded: %w",err)}returnnext(ctx,req)}}// Retry middlewarefuncRetryMiddleware(maxRetriesint) kmipclient.Middleware {returnfunc(next kmipclient.Next,ctx context.Context,req*kmip.RequestMessage) (*kmip.ResponseMessage,error) {varlastErrerrorfori:=0;i<=maxRetries;i++ {resp,err:=next(ctx,req)iferr==nil {returnresp,nil}lastErr=err// Exponential backoffifi<maxRetries {backoff:=time.Duration(1<<uint(i))*time.Secondselect {case<-time.After(backoff):case<-ctx.Done():returnnil,ctx.Err()}}}returnnil,fmt.Errorf("request failed after %d retries: %w",maxRetries,lastErr)}}// Use middlewareclient,err:=kmipclient.Dial("server:5696",kmipclient.WithMiddlewares(RateLimitMiddleware(rate.NewLimiter(10,1)),RetryMiddleware(3),),)

Error Handling Patterns

// Comprehensive error handlingresp,err:=client.Create().AES(256,kmip.CryptographicUsageEncrypt).Exec()iferr!=nil {// Network or connection errorsvarnetErr net.Erroriferrors.As(err,&netErr) {log.Printf("Network error: %v (timeout: %t, temp: %t)",netErr,netErr.Timeout(),netErr.Temporary())return}// TLS errorsvartlsErr tls.RecordHeaderErroriferrors.As(err,&tlsErr) {log.Printf("TLS error: %v",tlsErr)return}// KMIP protocol errorslog.Printf("KMIP operation failed: %v",err)return}// Batch operation error handlingresults,err:=client.Batch(ctx,req1,req2,req3)iferr!=nil {log.Printf("Batch request failed: %v",err)return}// Check individual resultsfori,result:=rangeresults {iferr:=result.Err();err!=nil {log.Printf("Operation %d failed: %v",i,err)continue}// Process successful resultswitchpayload:=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 onceresponses,err:=results.Unwrap()iferr!=nil {log.Printf("Batch response has some errors: %v",err)return}

Working with TTLV Encoding

// Marshal to different formatsrequest:=&payloads.CreateRequestPayload{...}// Binary TTLV (native KMIP format)binaryData:=ttlv.MarshalTTLV(request)// XML format (human-readable)xmlData:=ttlv.MarshalXML(request)// JSON formatjsonData:=ttlv.MarshalJSON(request)// Text format (debugging)textData:=ttlv.MarshalText(request)// Unmarshal from TTLVvardecoded payloads.CreateRequestPayloaderr:=ttlv.UnmarshalTTLV(binaryData,&decoded)iferr!=nil {log.Fatal(err)}

🔐 Authentication

Client Certificate Authentication

// From filesclient,err:=kmipclient.Dial("server:5696",kmipclient.WithClientCertFiles("cert.pem","key.pem"),)// From PEM dataclient,err:=kmipclient.Dial("server:5696",kmipclient.WithClientCertPEM(certPEM,keyPEM),)// Multiple certificatesclient,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 authenticationauth:= 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 authenticationdeviceAuth:= 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 theexamples 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 followContribution Guidelines

🔧 Troubleshooting

Common Issues

Connection Problems

# Verify server connectivitytelnet your-kmip-server 5696# Check TLS certificate issuesopenssl 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 versionclient,err:=kmipclient.Dial("server:5696",kmipclient.EnforceVersion(kmip.V1_4),)

Debug Logging

// Enable debug logging to see TTLV messagesclient,err:=kmipclient.Dial("server:5696",kmipclient.WithMiddlewares(kmipclient.DebugMiddleware(os.Stdout,ttlv.MarshalXML),),)

🛠️ Development

Building and Testing

# Clone repositorygit clone https://github.com/ovh/kmip-go.gitcd kmip-go# Install dependenciesgo mod download# Run all testsgotest -race ./...# Run integration tests (requires KMIP server)gotest -race -tags=integration ./...

Code Quality

# Format codego fmt ./...# Run linter (requires golangci-lint)golangci-lint run# Build examplesgo build ./examples/...

📄 License

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

🆘 Support

🙏 Acknowledgments

This library is developed and maintained byOVHcloud, 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 againstOVHcloud KMS. While it aims for full KMIP compliance, some features may work differently with other KMIP implementations. Please report any compatibility issues.

About

A golang KMIP client and server library, supporting KMIP v1.0 to v1.4.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Contributors5

Languages


[8]ページ先頭

©2009-2025 Movatter.jp