Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/iamnasirudeen/key-management/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Key Management Service uses asymmetric RSA encryption to protect sensitive data. Each client device receives a unique RSA key pair consisting of a public key for encryption and a private key for decryption.
The service uses RSA-2048 encryption with PKCS1_OAEP_PADDING for optimal security and compatibility.

RSA Key Pair Generation

Technical Specifications

Keys are generated using Node.js’s native crypto module with the following configuration:
const { publicKey, privateKey } = await generateKeyPairAsync('rsa', {
  modulusLength: 2048,
  publicKeyEncoding: {
    type: 'spki',
    format: 'pem',
  },
  privateKeyEncoding: {
    type: 'pkcs8',
    format: 'pem',
  },
});
Reference: crypto.ts:19-29

Key Generation Parameters

ParameterValueDescription
AlgorithmRSAAsymmetric encryption algorithm
Modulus Length2048 bitsKey size providing strong security
Public Key TypeSPKISubject Public Key Info format
Private Key TypePKCS8Private Key Information Syntax Standard
FormatPEMPrivacy-Enhanced Mail encoding

Public and Private Key Usage

Public Key (Client-Side)

The public key is distributed to client applications and used to encrypt sensitive data before transmission:
export 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');
}
Reference: crypto.ts:44-59
Key Features:
  • Encrypted data is returned as a base64-encoded string
  • Uses PKCS1_OAEP_PADDING for enhanced security
  • Public keys can be safely shared with clients
  • Each encryption produces different ciphertext (non-deterministic)

Private Key (Server-Side Only)

The private key remains secure on the server and is used to decrypt data encrypted with the corresponding public key:
export function decryptData(encryptedData: string, privateKey: string): string {
  const buffer = Buffer.from(encryptedData, 'base64');
  const decrypted = crypto.privateDecrypt(
    {
      key: privateKey,
      padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
    },
    buffer,
  );
  
  return decrypted.toString('utf-8');
}
Reference: crypto.ts:68-83
Private keys are never exposed to client applications. They are stored securely in the database and only accessed server-side for decryption operations.

Key Storage and Management

Database Schema

Each encryption key is stored with comprehensive metadata:
await prismaService.clientEncryptionKey.create({
  data: {
    id: keyId,                    // Unique identifier
    deviceId,                     // Associated device
    appVersion,                   // Client app version
    publicKey,                    // PEM-encoded public key
    privateKey,                   // PEM-encoded private key (encrypted at rest)
    expiresAt: expirationDate,    // Automatic expiration
    createdAt: new Date(),
  },
});
Reference: encryption.service.ts:68-78

Key Identification

Each key pair receives a unique identifier combining timestamp and randomness:
const keyId = `key_${Date.now()}_${crypto.randomBytes(12).toString('hex')}`;
This ensures:
  • Globally unique identifiers
  • Chronological ordering
  • Cryptographic randomness to prevent prediction

Key Lifecycle

When a client requests an encryption key, the service:
  1. Checks for existing valid keys for the device
  2. If a valid key exists, returns it (avoiding unnecessary generation)
  3. Otherwise, generates a new RSA-2048 key pair
  4. Stores both keys in the database with expiration date
  5. Returns the public key and keyId to the client
Reference: encryption.service.ts:34-86
During the key’s lifetime:
  • Client: Uses public key to encrypt sensitive data (passcodes, PINs, etc.)
  • Server: Uses private key to decrypt received data
  • Validation: Each decryption checks if the key has expired
  • Monitoring: All operations are logged for security auditing
Keys automatically expire after a configured period (default: 30 days):
const expirationDate = new Date();
expirationDate.setDate(
  expirationDate.getDate() + this.keyRotationIntervalDays
);
Expired keys are rejected during decryption operations.Reference: encryption.service.ts:63-66
Expired or problematic keys are marked as deprecated:
  • Prevents use in new operations
  • Retained for a grace period (default: 90 days)
  • Eventually deleted from the database
Reference: key-rotation.tasks.ts:28-70

Encryption Workflow

Security Considerations

Private Key Security: Private keys are stored in the database and must be protected with:
  • Database-level encryption at rest
  • Restricted access controls
  • Secure network connections (TLS)
  • Regular security audits

Best Practices

  1. Never expose private keys: Private keys should never be transmitted to clients or logged
  2. Validate key expiration: Always check if a key has expired before use
  3. Use key rotation: Regular rotation limits the impact of potential key compromise
  4. Monitor key usage: Track encryption/decryption operations for anomalies
  5. Limit data size: Enforce maximum encrypted data size to prevent resource exhaustion

Key Rotation

Learn about automated key rotation and lifecycle management

Security Measures

Explore security features including rate limiting and validation