npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ankkho/nestjs-cipher

v1.1.1

Published

Production-grade NestJS encryption module for PII protection with AES-256-GCM and KMS

Readme

nestjs-cipher

TypeScript NestJS Node.js pnpm License

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.

Table of Contents

Features

  • 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

Providers

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

Installation

pnpm install @ankkho/nestjs-cipher

Requirements:

  • Node.js 22.x.x higher
  • pnpm 11.0.0+

Quick Start

⭐ ConfigService (Recommended)

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-ring

LocalProvider (Development Only)

import { CipherModule, Providers } from '@ankkho/nestjs-cipher';

@Module({
  imports: [CipherModule.forRoot({ provider: Providers.LOCAL })],
})
export class AppModule {}

⚠️ In-memory keys only. Not for production.

Use Service

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 };
  }
}

Configuration

GCP KMS

Credentials: Uses Application Default Credentials (ADC).

export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account-key.json
# OR
gcloud auth application-default login

Permissions: Service account requires roles/cloudkms.cryptographer.

Local (Development)

No setup required. Keys stored in-memory only.

How It Works

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 tenantId or userId required
  • Same context for encrypt & decrypt
  • wrappedDek safe 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.

Multi-Tenant Architecture

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

Observability

OpenTelemetry spans: nestjs-cipher.encrypt, nestjs-cipher.decrypt

Attributes:

  • cipher.provider — KMS provider (e.g., GCP_KMS)
  • cipher.context.typetenant or user
  • cipher.payload.version — Payload version

Setup: Automatic if OTel SDK is configured.

Security Best Practices

  1. ✅ Store credentials in secure vault; never commit keys
  2. ✅ Grant service account least privilege (roles/cloudkms.cryptographer only)
  3. ✅ Enable automatic key rotation (90 days recommended)
  4. ✅ Monitor Cloud Audit Logs for unauthorized access
  5. ✅ Use TLS for all communication

Testing with Example

LocalProvider (Development)

pnpm build:example && pnpm example

GCP KMS with OpenTofu (Production)

Full setup with infrastructure provisioning:

cd example/tofu-gcp && source .env.gcp && pnpm build && pnpm example:gcp

See example/tofu-gcp for details.

Troubleshooting

| 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 |

Production Deployment

  • Use Providers.GCP_KMS (not Local)
  • Store credentials in secure vault (GCP Secret Manager, Vault, etc.)
  • Grant service account roles/cloudkms.cryptographer only
  • 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

Infrastructure (OpenTofu)

Environments: dev, test, stage, prod.

GCP KMS infrastructure is provisioned with OpenTofu.

Provider: GCP KMS.

Development

Requirements

  • Node.js 20.0.0 LTS or higher
  • pnpm 10.32.0+

Commands

# 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 typecheck

Resources

License

MIT