TrustWeave KMS Documentation
Version: 1.0
Last Updated: 2025-01-27
Overview
TrustWeave Key Management Service (KMS) provides a unified, type-safe interface for cryptographic key operations across multiple cloud providers and hardware security modules (HSMs).
Quick Links
- Quick Start Guide - Get started in 5 minutes
- Plugin Configuration Guide - Complete configuration reference
Key Features
- Type-Safe API**: Result-based error handling with sealed classes
- Simple Factory API**:
KeyManagementServicesfactory hides ServiceLoader complexity - Instance Caching**: Automatic caching of KMS instances for optimal performance
- Multiple Providers**: AWS, Azure, Google, HashiCorp, IBM, InMemory, and more
- SPI Auto-Discovery**: Automatic plugin discovery via Java ServiceLoader
- Thread-Safe**: All implementations are thread-safe
- Comprehensive Testing**: Contract tests, edge case tests, performance tests
- Production-Ready**: FIPS 140-3 Level 3 validated options available
Supported Plugins
| Plugin | Provider Name | Status | FIPS 140-3 |
|---|---|---|---|
| AWS KMS | aws |
✅ Production | ✅ Level 3 |
| Azure Key Vault | azure |
✅ Production | ✅ Level 2 |
| Google Cloud KMS | google-cloud-kms |
✅ Production | ✅ Level 3 |
| HashiCorp Vault | vault |
✅ Production | ⚠️ Depends on backend |
| IBM Key Protect | ibm |
✅ Production | ✅ Level 4 |
| InMemory | inmemory |
✅ Development/Testing | ❌ No |
Quick Example
Using KeyManagementServices Factory (Recommended)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import org.trustweave.kms.*
// Simple factory API - no ServiceLoader needed!
val kms = KeyManagementServices.create("inmemory")
// Generate a key
val result = kms.generateKey(Algorithm.Ed25519)
when (result) {
is GenerateKeyResult.Success -> {
val keyId = result.keyHandle.id
// Sign data
val sign = kms.sign(keyId, "Hello, World!".toByteArray())
when (sign) {
is SignResult.Success -> println("Signed: ${sign.signature.size} bytes")
is SignResult.Failure -> println("Error: ${sign.reason}")
}
}
is GenerateKeyResult.Failure -> println("Error: ${result.reason}")
}
Direct Instantiation (Alternative)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.trustweave.kms.inmemory.*
import org.trustweave.kms.*
// Direct instantiation (for InMemory only)
val kms = InMemoryKeyManagementService()
// Generate a key
val result = kms.generateKey(Algorithm.Ed25519)
when (result) {
is GenerateKeyResult.Success -> {
val keyId = result.keyHandle.id
// Sign data
val sign = kms.sign(keyId, "Hello, World!".toByteArray())
when (sign) {
is SignResult.Success -> println("Signed: ${sign.signature.size} bytes")
is SignResult.Failure -> println("Error: ${sign.reason}")
}
}
is GenerateKeyResult.Failure -> println("Error: ${result.reason}")
}
Documentation Structure
Getting Started
- Quick Start Guide - Examples for all plugins
- Plugin Configuration Guide - Complete configuration reference
Plugin-Specific Documentation
- AWS KMS - AWS KMS plugin
- Azure Key Vault - Azure Key Vault plugin
- Google Cloud KMS - Google Cloud KMS plugin
- HashiCorp Vault - HashiCorp Vault plugin
- IBM Key Protect - IBM Key Protect plugin
- InMemory KMS - InMemory KMS plugin
Developer Resources
- Creating Plugins Guide - Implement custom KMS plugins
Core Concepts
Result-Based API
All operations return sealed Result types for type-safe error handling:
1
2
3
4
5
6
7
8
sealed class GenerateKeyResult {
data class Success(val keyHandle: KeyHandle) : GenerateKeyResult()
sealed class Failure : GenerateKeyResult() {
data class UnsupportedAlgorithm(val algorithm: Algorithm) : Failure()
data class InvalidOptions(val reason: String) : Failure()
data class Error(val algorithm: Algorithm, val reason: String, val cause: Throwable?) : Failure()
}
}
Type-Safe Constants
Use KmsOptionKeys constants instead of magic strings. Cross-provider keys live in org.trustweave.kms.KmsOptionKeys (KEY_ID, KEY_NAME, NAME, DESCRIPTION, EXPORTABLE, EXTRACTABLE). Provider-specific keys live in plugin modules: AwsKmsOptionKeys (REGION, TAGS, ALIAS, ENABLE_AUTOMATIC_ROTATION, …), GcpKmsOptionKeys (KEY_RING, LABELS), HashiCorpKmsOptionKeys (ALLOW_PLAINTEXT_BACKUP).
1
2
3
4
5
6
7
8
import org.trustweave.kms.KmsOptionKeys
import org.trustweave.awskms.AwsKmsOptionKeys
val options = mapOf(
KmsOptionKeys.KEY_ID to "my-key-id",
KmsOptionKeys.DESCRIPTION to "My key",
AwsKmsOptionKeys.TAGS to mapOf("env" to "prod")
)
Algorithm Support
All plugins support a common set of algorithms:
- Ed25519 - Modern EdDSA signature scheme
- secp256k1 - Blockchain-compatible curve
- P-256, P-384, P-521 - NIST standard curves
- RSA-2048 (⚠️ Legacy, deprecated)
- RSA-3072, RSA-4096 - Recommended RSA sizes
Architecture
Core Components
KeyManagementService- Main interface for all KMS operationsAlgorithm- Sealed class hierarchy for type-safe algorithmsKeyHandle- Represents a key with metadata- Result Types - Sealed classes for operation results
- SPI - Service Provider Interface for plugin discovery
Plugin Structure
Each plugin implements:
KeyManagementServiceinterfaceKeyManagementServiceProviderfor SPI discovery- Configuration class with builder pattern
- Algorithm mapping utilities
Best Practices
1. Use Type-Safe Constants
1
2
3
4
5
// ✅ Good
options[KmsOptionKeys.KEY_ID] = "my-key"
// ❌ Bad
options["keyId"] = "my-key"
2. Handle All Result Cases
1
2
3
4
5
6
when (val result = kms.generateKey(algorithm)) {
is GenerateKeyResult.Success -> { /* ... */ }
is GenerateKeyResult.Failure.UnsupportedAlgorithm -> { /* ... */ }
is GenerateKeyResult.Failure.InvalidOptions -> { /* ... */ }
is GenerateKeyResult.Failure.Error -> { /* ... */ }
}
3. Use Environment Variables for Secrets
1
2
3
4
5
6
7
// ✅ Good
val config = AwsKmsConfig.fromEnvironment()
// ❌ Bad
val config = AwsKmsConfig.builder()
.accessKeyId("AKIA...") // Don't hard-code!
.build()
4. Leverage Instance Caching
KeyManagementServices automatically caches KMS instances. Calling create() with the same provider and configuration returns the cached instance, avoiding expensive client initialization:
1
2
3
4
5
6
7
8
import org.trustweave.kms.*
// First call creates and caches instance
val kms1 = KeyManagementServices.create("aws", mapOf("region" to "us-east-1"))
// Same configuration returns cached instance
val kms2 = KeyManagementServices.create("aws", mapOf("region" to "us-east-1"))
// kms1 === kms2 (same instance)
Note: This is different from provider-level caching (like AWS KMS cacheTtlSeconds). Instance caching is at the factory level and caches the entire KMS client instance.
Requirements
- Java: 8 or higher
- Kotlin: 1.9+ (for coroutines support)
- Dependencies: Varies by plugin (see Plugin Configuration Guide)
License
See the main TrustWeave LICENSE file.
Last Updated: 2025-01-27