Getting Started
This guide will walk you through setting up the Key Management Service and making your first API calls. You’ll learn how to generate encryption keys, encrypt data, and verify encrypted credentials.@nestjs/graphql - GraphQL integration@nestjs/apollo - Apollo Server driver@prisma/client - Database ORM@nestjs/config - Configuration management@nestjs/schedule - Cron job schedulingDATABASE_URL="postgresql://user:password@localhost:5432/kms_db"
# Optional: Customize key rotation and retention policies
ENCRYPTION_KEY_ROTATION_DAYS=30
ENCRYPTION_KEY_RETENTION_DAYS=90
MAX_ENCRYPTED_DATA_SIZE=2048
Key Configuration Options:
ENCRYPTION_KEY_ROTATION_DAYS- How long before keys expire (default: 30 days)ENCRYPTION_KEY_RETENTION_DAYS- How long to keep deprecated keys (default: 90 days)MAX_ENCRYPTED_DATA_SIZE- Maximum size of encrypted data in bytes (default: 2048)
User - User accounts with encrypted credentialsClientEncryptionKey - RSA key pairs with rotation metadataEncryptionMetric - Operation metrics for monitoringThe GraphQL Playground is automatically enabled in development mode, allowing you to explore the API and test queries interactively.
Now let’s generate an encryption key for a device. Open the GraphQL Playground at
http://localhost:3000/graphql and run:mutation {
generateClientEncryptionKey(
input: {
deviceId: "device_123"
appVersion: "1.0.0"
}
) {
keyId
publicKey
}
}
{
"data": {
"generateClientEncryptionKey": {
"keyId": "key_1709514240000_a1b2c3d4e5f6g7h8i9j0",
"publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...\n-----END PUBLIC KEY-----\n"
}
}
}
The
keyId is unique and includes a timestamp plus random bytes. Store this keyId and publicKey in your client application - you’ll need them for encryption operations.With the public key from step 5, you can now encrypt sensitive data on your client. Here’s how the encryption works:
import * as crypto from 'crypto';
function encryptData(data: string, publicKey: string): string {
const buffer = Buffer.from(data, 'utf-8');
const encrypted = crypto.publicEncrypt(
{
key: publicKey,
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
},
buffer,
);
return encrypted.toString('base64');
}
// Encrypt a passcode
const publicKey = "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n";
const encryptedPasscode = encryptData("123456", publicKey);
Security Best Practice: Always encrypt sensitive data (passcodes, PINs, tokens) on the client side before sending to any server. The private key never leaves the KMS server.
mutation {
setUserPasscode(
input: {
encryptedPasscode: "base64_encrypted_data_here"
keyId: "key_1709514240000_a1b2c3d4e5f6g7h8i9j0"
passwordAuthType: PASSCODE
}
)
}
keyIdmutation {
verifyUserPasscode(
input: {
encryptedPasscode: "base64_encrypted_data_here"
keyId: "key_1709514240000_a1b2c3d4e5f6g7h8i9j0"
passwordAuthType: PASSCODE
}
)
}
Old keys are retained for 90 days (configurable) so data encrypted with them can still be decrypted during the transition period.
Complete Example Flow
Here’s a complete TypeScript example showing the entire flow:Complete client example
Available Operations
The service provides these GraphQL operations:Mutations
| Operation | Description |
|---|---|
generateClientEncryptionKey | Generate a new RSA key pair for a device |
rotateClientEncryptionKey | Rotate keys for a device (deprecates old keys) |
encryptDataLikeClient | Test encryption with a public key (utility) |
setUserPasscode | Set a user’s encrypted passcode |
verifyUserPasscode | Verify a user’s encrypted passcode |
setTransactionPin | Set a user’s encrypted transaction PIN |
verifyTransactionPin | Verify a user’s encrypted transaction PIN |
Queries
| Operation | Description |
|---|---|
getEncryptionMetricsSummary | Get operation metrics for a time window |
Next Steps
API Reference
Explore detailed API documentation with all parameters and responses
Security Guide
Learn about security best practices and encryption standards
Key Rotation
Understand automatic key lifecycle management
Monitoring
Set up metrics collection and alerting
Troubleshooting
Key Generation Fails
Decryption Fails
- Verify the
keyIdmatches the one used for encryption - Check if the key has expired (keys expire after 30 days by default)
- Ensure encrypted data is properly base64 encoded
Database Connection Issues
Verify yourDATABASE_URL in .env:
Support
For issues or questions:- Check the API Reference for detailed documentation
- Review Security Best Practices
- File an issue on GitHub