Production-grade NestJS encryption module. Encrypt sensitive data (emails, PII, tokens) with AES-256-GCM + Google Cloud KMS (AWS/Azure coming soon). Local mode for development.
- Features
- Providers
- Installation
- Quick Start
- Configuration
- How It Works
- Multi-Tenant Architecture
- Observability
- Security Best Practices
- Testing with Example
- Troubleshooting
- Production Deployment
- Infrastructure (OpenTofu)
- Development
- Resources
- Envelope Encryption: AES-256-GCM local encryption with optional KMS key wrapping
- Zero-Trust DEK: Data Encryption Keys zeroed from memory after each operation
- DEK Caching: Unwrapped DEKs cached in-memory (5 min TTL) to skip KMS on repeated reads
- Multi-Tenant: Automatic tenant/user-level key isolation
- Fast: ~10-20ms per operation (90% local, minimal KMS calls)
- Observable: Pino logging + OpenTelemetry instrumentation
- Production-Ready: Full TypeScript, CI/CD validated
nestjs-cipher supports multiple KMS providers. Choose based on your deployment environment:
| Provider | Use Case | Setup | Key Rotation | Compliance |
|---|---|---|---|---|
| LOCAL | Development & testing | None | Manual | None |
| GCP_KMS | Production (recommended) | Medium | Auto (90d) | SOC 2, ISO 27001, PCI-DSS |
LOCAL — In-memory keys; no persistence. Dev and CI/CD only.
GCP_KMS — Enterprise-grade key management with audit logging, auto-rotation, and multi-region support. Note: GCP Cloud KMS is a paid service.
Coming Soon: AWS KMS, Azure Key Vault
pnpm install @ankkho/nestjs-cipherRequirements:
- Node.js 20.0.0 LTS or higher
- pnpm 10.32.0+
All environment variables via NestJS ConfigService:
import { ConfigModule, ConfigService } from '@nestjs/config';
import { CipherModule, Providers } from '@ankkho/nestjs-cipher';
@Module({
imports: [
ConfigModule.forRoot(),
CipherModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
provider: Providers.GCP_KMS,
gcp: {
projectId: config.getOrThrow('GCP_KMS_PROJECT_ID'),
keyRing: config.getOrThrow('GCP_KMS_KEY_RING'),
location: config.getOrThrow('GCP_KMS_LOCATION'),
},
}),
}),
],
})
export class AppModule {}Environment: .env
GCP_KMS_PROJECT_ID=my-project
GCP_KMS_LOCATION=us-central1
GCP_KMS_KEY_RING=pii-ringimport { CipherModule, Providers } from '@ankkho/nestjs-cipher';
@Module({
imports: [CipherModule.forRoot({ provider: Providers.LOCAL })],
})
export class AppModule {}import { CipherService } from '@ankkho/nestjs-cipher';
@Injectable()
export class UserService {
constructor(private cipher: CipherService) {}
async createUser(email: string, tenantId: string) {
const encrypted = await this.cipher.encrypt(email, { tenantId });
await db.users.create({ email_encrypted: encrypted });
}
async getUser(userId: string) {
const stored = await db.users.findOne(userId);
const email = await this.cipher.decrypt(stored.email_encrypted, {
tenantId: stored.tenant_id,
});
return { ...stored, email };
}
}Credentials: Uses Application Default Credentials (ADC).
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account-key.json
# OR
gcloud auth application-default loginPermissions: Service account requires roles/cloudkms.cryptographer.
No setup required. Keys stored in-memory only.
1. Generate random 32-byte DEK
2. Encrypt plaintext locally (AES-256-GCM)
3. Wrap DEK with KMS
4. Zero DEK from memory
5. Return: { v, ciphertext, wrappedDek, iv, tag }
Requirements:
- At least one of
tenantIdoruserIdrequired - Same context for encrypt & decrypt
wrappedDeksafe to store (encrypted by KMS)- DEK never persisted; zeroed after each operation
Payload:
{
"v": 1,
"ciphertext": "...",
"wrappedDek": "...",
"iv": "...",
"tag": "..."
}Versioning: Use v field for algorithm migrations. Decrypt old v:1 → re-encrypt to v:2 during background jobs.
Each tenant gets a distinct KMS key:
tenantId: 'org-100' → .../cryptoKeys/tenant-org-100
userId: 'usr-42' → .../cryptoKeys/user-usr-42
Result: Tenant A cannot decrypt Tenant B's data.
Envelope Encryption Benefits:
- Generate random DEK per operation
- Encrypt data locally (AES-256-GCM)
- Wrap DEK once with KMS
- Single KMS call per operation → cost-effective at scale
OpenTelemetry spans: nestjs-cipher.encrypt, nestjs-cipher.decrypt
Attributes:
cipher.provider— KMS provider (e.g.,GCP_KMS)cipher.context.type—tenantorusercipher.payload.version— Payload version
Setup: Automatic if OTel SDK is configured.
- ✅ Store credentials in secure vault; never commit keys
- ✅ Grant service account least privilege (
roles/cloudkms.cryptographeronly) - ✅ Enable automatic key rotation (90 days recommended)
- ✅ Monitor Cloud Audit Logs for unauthorized access
- ✅ Use TLS for all communication
pnpm build:example && pnpm exampleFull setup with infrastructure provisioning:
cd example/tofu-gcp && source .env.gcp && pnpm build && pnpm example:gcpSee example/tofu-gcp/README.md for details.
| Issue | Solution |
|---|---|
| Module fails at startup | Check credentials are set and have correct KMS permissions |
| Decryption fails | Verify same tenantId/userId context used for encrypt & decrypt |
| High latency | Check network connectivity to KMS provider; DEK caching is built-in (5 min TTL) |
| Credential validation errors | Ensure GOOGLE_APPLICATION_CREDENTIALS is set or gcloud auth application-default login run |
- Use
Providers.GCP_KMS(not Local) - Store credentials in secure vault (GCP Secret Manager, Vault, etc.)
- Grant service account
roles/cloudkms.cryptographeronly - Enable Cloud Audit Logs for monitoring
- Set up alerts for KMS API errors and quota
- Create keys in multiple regions for failover
- Rotate credentials immediately if compromised
Environments:
dev,test,stage,prod.
GCP KMS infrastructure is provisioned with OpenTofu.
Provider: GCP KMS.
- Node.js 20.0.0 LTS or higher
- pnpm 10.32.0+
# Install dependencies
pnpm install
# Build library
pnpm build
# Build example
pnpm build:example
# Run example (compiled code)
pnpm example
# Run tests
pnpm test
# Lint and format
pnpm lint:fix
# Type check
pnpm typecheckSee .github/README.md for CI/CD and repository best practices.
- Contributing — Contribution guidelines
- Release Process — Automated release workflow
- Security Policy — Security & reporting
- Example — Working sample
- Infrastructure (OpenTofu) — GCP KMS setup
MIT