@byronzeet/amava-crypto
v0.3.0
Published
High-performance SOC2-compliant encryption library with AWS KMS integration, batch processing, and intelligent caching
Downloads
630
Maintainers
Readme
@byronzeet/amava-crypto
High-performance SOC2-compliant encryption library with AWS KMS integration, batch processing, and intelligent caching.
Features
- 🔐 SOC2 Compliant Encryption: AES-GCM envelope encryption with AWS KMS
- ⚡ Batch Processing: Up to 70% performance improvement with batch decryption
- 🚀 Intelligent Caching: Multi-tier data key caching with automatic warming
- 📊 Performance Monitoring: Built-in benchmarking and metrics collection
- 🔄 Deterministic Hashing: Consistent hash generation for encrypted data
- 🛡️ Type Safety: Full TypeScript support with comprehensive type definitions
Performance Improvements
Based on comprehensive benchmarking, this library delivers:
- 37.6% average speed improvement with batch processing
- 67.3% reduction in AWS KMS calls through intelligent caching
- 60.9% efficiency gain in high-volume operations
Installation
npm install @byronzeet/amava-cryptoQuick Start
Basic Usage
import { AmavaCrypto } from '@byronzeet/amava-crypto';
const crypto = new AmavaCrypto({
region: 'us-east-1',
keyId: 'your-kms-key-id'
});
// Encrypt text
const encrypted = await crypto.encryptText('sensitive data', {
tenantId: 'property-uuid',
table: 'users',
column: 'email',
rowId: '123'
});
// Decrypt text
const decrypted = await crypto.decryptText(encrypted.ciphertext, {
tenantId: 'property-uuid',
table: 'users',
column: 'email',
rowId: '123'
});The canonical encryption context
Every encryption call MUST pass the full canonical context — {tenantId, table,
column, rowId} with non-empty values. Encryption throws if any of the four is
missing, undefined, null, or empty; there is no way to mint ciphertext with
an incomplete binding.
Key order in your object literal does not matter: the library serializes
the context in a fixed canonical order before using it as AAD, so
{rowId, table, column, tenantId} and {tenantId, table, column, rowId}
produce identical envelopes. Decryption applies the same normalization and has
no completeness guard — it accepts whatever context shape reproduces the
stored AAD, which keeps envelopes written by older library versions readable.
There is deliberately no API that decrypts without a caller-supplied context.
The AAD binding is the integrity guarantee; see docs/adr/0001 for rationale.
Batch Processing (Recommended for High Performance)
import { BatchDecryptItem } from '@byronzeet/amava-crypto';
const items: BatchDecryptItem[] = [
{
ciphertext: 'encrypted_data_1',
context: { tenantId: 'property-uuid', table: 'users', column: 'email', rowId: '1' }
},
{
ciphertext: 'encrypted_data_2',
context: { tenantId: 'property-uuid', table: 'users', column: 'email', rowId: '2' }
}
// ... more items
];
const result = await crypto.decryptBatch(items, {
concurrencyPerGroup: 10,
collectMetrics: true
});
console.log(`Processed ${result.metrics.successCount} items`);
console.log(`KMS calls: ${result.metrics.kmsCallCount}`);
console.log(`Cache hits: ${result.metrics.cacheHitCount}`);Cache Management
// Warm cache with frequently used keys
await crypto.warmCache(['key1', 'key2', 'key3'], {
concurrency: 5,
priority: 'frequency'
});
// Configure tiered TTL for optimal performance
crypto.configureTieredTtl({
frequentAccessTtl: 600000, // 10 minutes for frequent keys
recentAccessTtl: 300000, // 5 minutes for recent keys
standardTtl: 180000, // 3 minutes for standard keys
frequentAccessThreshold: 5, // 5+ hits = frequent
recentAccessThreshold: 60000 // 1 minute = recent
});
// Get cache statistics
const stats = crypto.getCacheStats();
console.log(`Local cache: ${stats.local.size}/${stats.local.maxSize}`);
console.log(`Shared cache: ${stats.shared.size}/${stats.shared.maxSize}`);Configuration Options
AmavaCrypto Constructor
interface AmavaCryptoConfig {
region: string; // AWS region
keyId: string; // KMS key ID
kmsClient?: KMSClient; // Optional custom KMS client
useSharedCache?: boolean; // Enable shared caching (default: true)
dataKeyCacheTtlMs?: number; // Cache TTL in ms (default: 300000)
hooks?: CryptoHooks; // Event hooks for monitoring
}Batch Processing Options
interface BatchDecryptOptions {
concurrencyPerGroup?: number; // Parallel operations per key group
failFast?: boolean; // Stop on first error
collectMetrics?: boolean; // Gather performance metrics
}Performance Benchmarking
Run performance benchmarks to measure improvements:
npm run benchmarkThis generates a detailed report showing:
- Speed improvements vs individual operations
- KMS call reduction percentages
- Cache hit rates and efficiency gains
- Scaling benefits with larger datasets
API Reference
Core Methods
encryptText(plaintext: string, context: EncryptionContext): Promise<EncryptionResult>
Encrypts text with the provided context.
decryptText(ciphertext: string, context: EncryptionContext): Promise<string>
Decrypts text with the provided context.
decryptBatch(items: BatchDecryptItem[], options?: BatchDecryptOptions): Promise<BatchDecryptResult>
Efficiently decrypts multiple items in batches.
generateDeterministicHash(data: string): string
Generates a consistent hash for the given data.
Cache Management
warmCache(keys: string[], options?: CacheWarmingOptions): Promise<CacheWarmResult>
Proactively loads data keys into cache.
intelligentCacheWarmup(tierConfig?: CacheTierConfig): Promise<IntelligentWarmupResult>
Automatically warms cache based on usage patterns.
getCacheStats(): CacheStats
Returns current cache statistics.
clearCache(): void
Clears all cached data keys.
Configuration
configureTieredTtl(config: CacheTierConfig): void
Sets up tiered TTL for different access patterns.
Types
Core Types
interface EncryptionContext {
tenantId?: string; // REQUIRED for encryption (guard-enforced); optional in the type only so decryption can reproduce legacy stored AADs
table: string;
column: string;
rowId?: string; // REQUIRED for encryption (guard-enforced), same caveat
}
interface EncryptionResult {
ciphertext: string;
hash: string;
}
interface BatchDecryptItem {
ciphertext: string;
context: EncryptionContext;
}
interface BatchDecryptResult {
results: Map<number, string>;
errors: Map<number, Error>;
metrics: BatchDecryptMetrics;
}Performance Types
interface BatchDecryptMetrics {
totalDuration: number;
successCount: number;
errorCount: number;
keyGroupCount: number;
kmsCallCount: number;
cacheHitCount: number;
}
interface CacheStats {
local: {
size: number;
maxSize: number;
hitRate: number;
};
shared: {
size: number;
maxSize: number;
hitRate: number;
};
}Best Practices
1. Use Batch Processing for Multiple Items
// ❌ Inefficient - individual calls
for (const item of items) {
await crypto.decryptText(item.ciphertext, item.context);
}
// ✅ Efficient - batch processing
const result = await crypto.decryptBatch(items);2. Enable Shared Caching
// ✅ Recommended configuration
const crypto = new AmavaCrypto({
region: 'us-east-1',
keyId: 'your-key-id',
useSharedCache: true, // Share cache across instances
dataKeyCacheTtlMs: 300000 // 5 minute TTL
});3. Warm Cache for Predictable Workloads
// ✅ Warm cache during application startup
const frequentKeys = await getFrequentlyUsedKeys();
await crypto.warmCache(frequentKeys, {
concurrency: 10,
priority: 'frequency'
});4. Monitor Performance
// ✅ Collect metrics for optimization
const result = await crypto.decryptBatch(items, {
collectMetrics: true
});
if (result.metrics.cacheHitCount / items.length < 0.5) {
console.warn('Low cache hit rate - consider cache warming');
}Migration from v0.1.x
Breaking Changes
decryptBatchnow returns aBatchDecryptResultobject instead of an array- Cache configuration moved to constructor options
- Some internal method signatures changed
Migration Steps
- Update batch processing calls:
// v0.1.x
const results = await crypto.decryptBatch(items);
// v0.2.0
const { results, metrics } = await crypto.decryptBatch(items);- Update cache configuration:
// v0.1.x
crypto.setCacheTtl(300000);
// v0.2.0
const crypto = new AmavaCrypto({
// ... other options
dataKeyCacheTtlMs: 300000
});Contributing
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Run
npm testandnpm run benchmark - Submit a pull request
License
MIT License - see LICENSE file for details.
Support
For issues and questions:
- GitHub Issues: Create an issue
- Email: [email protected]
Performance tested and optimized for production workloads 🚀
