Skip to content

kitsuneislife/keyring

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Keyring Banner

Tests TypeScript Node

Complete data encryption system with envelope encryption, auditing, security policies, and KMS integration. Implements security best practices for storing encrypted content in databases without risk of discovery.

Keyring implements a practical, secure, and applicable plan for storing encrypted content in a database without discovery risk. The system covers principles, recommended architecture (envelope encryption + KMS), storage schema, defense-in-depth strategies, and ready-to-use examples in Node.js/TypeScript.

✨ Key Features

Envelope Encryption: Each data has a unique DEK, encrypted by a KEK
AES-256-GCM: Authenticated encryption (confidentiality + integrity)
Complete Auditing: Logs all operations without exposing sensitive data
Security Policies: Rate limiting, access control, automatic rotation
KMS Integration: Support for AWS KMS, GCP KMS, Azure Key Vault
Anomaly Detection: Identifies attack attempts
Production Ready: Complete tests and documentation

🚀 Quick Start

Installation

npm install
npm run build

Basic Usage

import { Keyring, RSAKeyProvider } from './src';

// Generate key pair (in production, use KMS)
const { publicKey, privateKey } = RSAKeyProvider.generateKeyPair();
const provider = new RSAKeyProvider(publicKey, privateKey);

// Create Keyring instance
const keyring = new Keyring({ keyProvider: provider });

// Encrypt
const encrypted = await keyring.encrypt('Sensitive data');

// Save to database
// await db.save({ id: '123', ...encrypted });

// Decrypt
const decrypted = await keyring.decrypt(encrypted);
console.log(decrypted.data.toString('utf8')); // "Sensitive data"

📚 Documentation

🧪 Tests

# All tests (4 suites, 31 tests)
npm test

# Unit tests only
npm run test:unit

# Integration tests only
npm run test:integration

# Run examples
npm run examples

Test Results:

✓ DEK Generator Tests                      ✓ PASSED
✓ Data Encryption Tests                    ✓ PASSED
✓ Key Wrapping Tests                       ✓ PASSED
✓ Integration Tests                        ✓ PASSED

Total: 4/4 test suites passed
🎉 All tests passed! System is ready for production.

📦 Project Structure

src/
├── index.ts                    # Entry point, exports everything
├── keyring.ts                  # Main system class
├── types/
│   └── index.ts               # TypeScript type definitions
├── crypto/
│   ├── dek-generator.ts       # DEK and IV generation
│   ├── data-encryption.ts     # AES-256-GCM encryption
│   └── key-wrapping.ts        # Envelope encryption (RSA/KMS)
├── audit/
│   └── audit-logger.ts        # Audit system
├── policies/
│   └── security-policies.ts   # Security policies
├── examples/
│   └── usage-examples.ts      # 7 practical examples
└── tests/
    ├── dek-generator.test.ts
    ├── data-encryption.test.ts
    ├── key-wrapping.test.ts
    ├── integration.test.ts
    └── run-all-tests.ts

🔒 Security Principles

  1. Key Principles

Encrypt on the client (or in an application layer you control) before sending to DB — never rely solely on database encryption.

Envelope encryption: each file has a unique Data Encryption Key (DEK); the DEK is then encrypted (wrapped) by a Key Encryption Key (KEK) maintained in KMS/HSM.

Authenticity + integrity: use authenticated modes (AES-GCM, ChaCha20-Poly1305) to detect tampering.

Unique IV/nonce per encryption: use random IVs/nonce and store them with the ciphertext.

Don't leak sensitive metadata: original names, types, sizes, timestamps can reveal information — minimize or encrypt them too.

Minimum privilege and auditing for who can request keys/decrypt.

Defense layers: TLS in transit, TDE in database as extra layer (doesn't replace client-applied encryption).

🏗️ Architecture

Encryption Flow

1. Generate DEK → crypto.randomBytes(32)
2. Encrypt data → AES-256-GCM with DEK
3. Wrap DEK → KEK (via KMS) encrypts the DEK
4. Store → DB stores: ciphertext + iv + authTag + wrappedKey

Decryption Flow

1. Fetch from DB → ciphertext + iv + authTag + wrappedKey
2. Unwrap DEK → KEK (via KMS) decrypts the DEK
3. Decrypt data → AES-256-GCM with DEK
4. Validate integrity → Verifies authTag (detects tampering)

Diagram

┌─────────────────────────────────────────────────────────────┐
│                     Application                             │
└─────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────┐
│                      Keyring                                │
│  ┌──────────────┐  ┌──────────────┐  ┌─────────────────┐  │
│  │  Encryption  │  │   Policies   │  │     Audit       │  │
│  └──────────────┘  └──────────────┘  └─────────────────┘  │
└─────────────────────────────────────────────────────────────┘
              │                              │
              ▼                              ▼
┌─────────────────────────┐    ┌─────────────────────────────┐
│   Key Provider (KMS)    │    │    Audit Database          │
│  - Wrap/Unwrap DEKs     │    │    - Persisted logs        │
│  - Managed KEK          │    │    - Alerts                │
└─────────────────────────┘    └─────────────────────────────┘
              │
              ▼
┌─────────────────────────────────────────────────────────────┐
│              Main Database                                  │
│  - ciphertext (encrypted data)                             │
│  - wrapped_key (encrypted DEK)                             │
│  - iv, auth_tag (encryption metadata)                      │
└─────────────────────────────────────────────────────────────┘
  1. Recommended architecture (summary)

Generate random DEK (e.g., 32 bytes).

Encrypt the file with DEK using AES-256-GCM (or ChaCha20-Poly1305). Store ciphertext, iv, auth_tag.

Use KMS (AWS KMS / GCP KMS / Azure Key Vault) or HSM to wrap (encrypt) the DEK with the managed KEK. The DB stores only the encrypted DEK (wrapped_key).

Store in DB: {wrapped_key, key_id, version, iv, auth_tag, ciphertext, minimal_metadata}.

For reading: app requests KMS to unwrap the DEK (verifying permissions), then decrypts the content in memory/stream and provides to the user.

Implement KEK rotation and DEK versioning.

💾 Storage Schema

Recommended Table (SQL)

CREATE TABLE encrypted_files (
  id UUID PRIMARY KEY,
  ciphertext TEXT NOT NULL,          -- Base64
  iv TEXT NOT NULL,                  -- Base64
  auth_tag TEXT NOT NULL,            -- Base64
  wrapped_key TEXT NOT NULL,         -- Base64
  key_id TEXT NOT NULL,              -- Identifies which KEK to use
  key_version TEXT NOT NULL,         -- Key version
  metadata_enc TEXT,                 -- Base64 (optional)
  created_at TIMESTAMP NOT NULL,
  INDEX idx_key_id (key_id)
);

Document Example (NoSQL)

{
  "id": "file-123",
  "ciphertext": "<bytes base64…>",
  "iv": "<base64 iv>",
  "auth_tag": "<base64 tag>",
  "wrapped_key": "<base64 wrapped DEK>",
  "key_id": "projects/.../keys/production-kek/v1",
  "key_version": "v1",
  "mime_type_enc": "<optional: encrypted mime type or null>",
  "metadata_enc": "<optional: encrypted metadata>",
  "created_at": "2025-11-03T12:00:00Z"
}

Never store the DEK in plain text.

key_id identifies which KEK/KMS to use for unwrap.

✅ Security Checklist

Do

  • ✅ Use KMS in production (AWS KMS, GCP KMS, Azure Key Vault)
  • ✅ Enable auditing and persist logs in secure database
  • ✅ Configure rate limiting to prevent abuse
  • ✅ Rotate keys regularly (90 days)
  • ✅ Monitor anomalies continuously
  • ✅ Use TLS for data in transit
  • ✅ Enable TDE in database as extra layer

Don't

  • ❌ Don't use RSAKeyProvider in production (dev/testing only)
  • ❌ Don't log DEKs, plaintexts or sensitive data
  • ❌ Don't store DEKs without wrapping
  • ❌ Don't expose private keys
  • ❌ Don't ignore authentication failures
  • ❌ Don't share Keyring instances between security contexts

📋 Usage Examples

1. Basic Encryption

const encrypted = await keyring.encrypt('Sensitive data');
// Save to DB: encrypted.ciphertext, encrypted.wrappedKey, etc.

2. With Sensitive Metadata

const encrypted = await keyring.encrypt(fileBuffer, {
  metadata: {
    originalName: 'confidential-document.pdf',
    mimeType: 'application/pdf',
    size: fileBuffer.length,
  }
});

3. AWS KMS Integration

import { KMSClient, EncryptCommand, DecryptCommand } from '@aws-sdk/client-kms';
import { KMSKeyProvider } from './src';

const kmsClient = new KMSClient({ region: 'us-east-1' });

const provider = new KMSKeyProvider(
  'arn:aws:kms:us-east-1:123456789:key/abc-def',
  async (dek, keyId) => {
    const result = await kmsClient.send(new EncryptCommand({
      KeyId: keyId,
      Plaintext: dek,
    }));
    return Buffer.from(result.CiphertextBlob);
  },
  async (wrappedKey, keyId) => {
    const result = await kmsClient.send(new DecryptCommand({
      KeyId: keyId,
      CiphertextBlob: wrappedKey,
    }));
    return Buffer.from(result.Plaintext);
  }
);

const keyring = new Keyring({ keyProvider: provider });

4. With Auditing and Policies

import { 
  configureGlobalAuditLogger,
  SecurityPolicyManager,
  RECOMMENDED_POLICIES 
} from './src';

// Configure auditing
configureGlobalAuditLogger({
  persistLog: async (log) => await db.auditLogs.insert(log),
  alertCallback: async (log) => {
    if (!log.success) await notifySecurityTeam(log);
  }
});

// Configure policies
const policyManager = new SecurityPolicyManager(
  RECOMMENDED_POLICIES.rateLimitPolicy,
  RECOMMENDED_POLICIES.accessControlPolicy,
  RECOMMENDED_POLICIES.rotationPolicy
);

const keyring = new Keyring({ keyProvider, policyManager });

5. Key Rotation

const newProvider = new RSAKeyProvider(newPublicKey, newPrivateKey);

for (const record of await db.encryptedData.findAll()) {
  const reencrypted = await keyring.rotateKey(record, newProvider);
  await db.encryptedData.update(record.id, reencrypted);
}

🔍 Anomaly Detection

The system automatically detects attack attempts:

// Check for anomalies (10+ failures in 5 minutes)
const hasAnomalies = keyring.hasAnomalies(5, 10);

if (hasAnomalies) {
  console.log('⚠ Possible attack detected!');
  // Alert security team
  // Block suspicious IP
  // Review audit logs
}

📊 Statistics and Monitoring

const stats = keyring.getAuditStats();
console.log({
  total: stats.total,
  byOperation: stats.byOperation,
  successRate: stats.successRate,
  failures: stats.failures
});

const recentLogs = keyring.getRecentLogs(100);

🔄 Key Rotation

The system supports automatic key rotation based on policies:

// Check if rotation is needed
if (keyring.shouldRotateKey()) {
  // Perform rotation
  await rotateAllKeys();
  policyManager.markKeyRotation();
}

🌐 Integration with Your System

Keyring exports all necessary functions for integration:

// In your database system
import { EncryptedData, Keyring } from '@keyring/secure-encryption';

export async function saveEncryptedFile(
  userId: string, 
  data: Buffer,
  keyring: Keyring
): Promise<string> {
  const encrypted = await keyring.encrypt(data);
  const id = generateId();
  
  await db.files.insert({
    id,
    userId,
    ...encrypted,
  });
  
  return id;
}

export async function getDecryptedFile(
  id: string,
  keyring: Keyring
): Promise<Buffer> {
  const record = await db.files.findById(id);
  const decrypted = await keyring.decrypt(record);
  return decrypted.data;
}

🛡️ What if DB is Compromised?

If envelope encryption is used correctly, an attacker with access only to the database will only see ciphertext and wrapped_key — without the KEK (KMS), decryption is infeasible.

Extra protections:

  • KMS with policy that refuses unwrap if called from suspicious IP/role
  • MFA sessions
  • Limit number of unwraps per time
  • KEK revocation/rotation process and DEK rewrap (re-encrypt)

🤝 Contributing

This project was created following security best practices. To contribute:

  1. Fork the repository
  2. Create a branch for your feature
  3. Run the tests: npm test
  4. Commit your changes
  5. Open a Pull Request

📄 License

MIT

🙋 Support

For questions or issues:


⚠️ Important Warnings:

  1. RSAKeyProvider is for development/testing only. Use KMS in production.
  2. Never log DEKs, private keys, or decrypted data.
  3. Configure rate limiting and auditing before using in production.
  4. Implement key rotation every 90 days.
  5. Monitor anomalies and authentication failures continuously.

Developed with focus on security and compliance 🔐

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors