Skip to main content

@happyvertical/encryption

Unified encryption and cryptography operations with adapter-based architecture supporting PGP, NaCl, and Node.js crypto.

Tests License TypeScript

Featuresโ€‹

  • ๐Ÿ” Multiple Encryption Methods: PGP/OpenPGP, NaCl/libsodium, Node.js crypto
  • ๐Ÿ“ Text, Files & Buffers: Encrypt any data format with a unified API
  • ๐Ÿ“ง Email Integration: Specialized PGP/MIME email encryption
  • ๐Ÿ”‘ Key Management: Generate, import, export, and manage encryption keys
  • โœ๏ธ Digital Signatures: Sign and verify data with RSA, ECDSA, and EdDSA
  • ๐ŸŽฏ Type-Safe: Full TypeScript support with comprehensive type definitions
  • โšก High Performance: Fast NaCl encryption, efficient streaming for large files
  • ๐Ÿงช Well-Tested: 209 tests covering all adapters and use cases

Installationโ€‹

npm install @happyvertical/encryption
# or
pnpm add @happyvertical/encryption
# or
yarn add @happyvertical/encryption

Claude Code Contextโ€‹

Install Claude Code context files for AI-assisted development:

npx have-encryption-context

This copies the package's AGENT.md documentation and metadata.json metadata to your project's .claude/ directory, enabling Claude to provide better assistance when working with this package.

Quick Startโ€‹

PGP Encryptionโ€‹

import { getEncryption } from '@happyvertical/encryption';

// Create PGP encryption instance
const pgp = await getEncryption({ type: 'pgp' });

// Generate keypair
const keypair = await pgp.generateKeyPair({
name: 'Alice',
email: 'alice@example.com',
passphrase: 'secure-passphrase',
type: 'rsa',
keySize: 4096
});

// Initialize with keys
const encryption = await getEncryption({
type: 'pgp',
publicKey: keypair.publicKey,
privateKey: keypair.privateKey,
passphrase: 'secure-passphrase'
});

// Encrypt and decrypt text
const encrypted = await encryption.encryptText('Secret message');
const decrypted = await encryption.decryptText(encrypted);

// Encrypt and decrypt files
await encryption.encryptFile('document.pdf', 'document.pdf.pgp');
await encryption.decryptFile('document.pdf.pgp', 'document.pdf');

NaCl Encryption (Fast & Modern)โ€‹

import { getEncryption } from '@happyvertical/encryption';

// Generate keypair
const nacl = await getEncryption({ type: 'nacl' });
const keypair = await nacl.generateKeyPair();

// Symmetric encryption (secretbox)
const encryption = await getEncryption({
type: 'nacl',
secretKey: keypair.secretKey
});

const encrypted = await encryption.encryptText('Secret message');
const decrypted = await encryption.decryptText(encrypted);

// Encrypt files (very fast!)
await encryption.encryptFile('data.json', 'data.json.enc');
await encryption.decryptFile('data.json.enc', 'data.json');

Node.js Crypto (AES & RSA)โ€‹

import { getEncryption } from '@happyvertical/encryption';

// AES-256-GCM encryption
const aes = await getEncryption({
type: 'node',
algorithm: 'aes-256-gcm',
keyDerivation: {
password: 'user-password',
salt: 'unique-salt',
iterations: 100000
}
});

const encrypted = await aes.encryptText('Secret message');
const decrypted = await aes.decryptText(encrypted);

// RSA encryption
const rsa = await getEncryption({
type: 'node',
algorithm: 'rsa-oaep'
});

const keypair = await rsa.generateKeyPair({
type: 'rsa',
keySize: 2048
});

const rsaEncryption = await getEncryption({
type: 'node',
algorithm: 'rsa-oaep',
publicKey: keypair.publicKey,
privateKey: keypair.privateKey
});

const encrypted = await rsaEncryption.encryptText('Small message');
const decrypted = await rsaEncryption.decryptText(encrypted);

Common Use Casesโ€‹

Email Encryption (PGP/MIME)โ€‹

import { getEncryption } from '@happyvertical/encryption';

const pgp = await getEncryption({
type: 'pgp',
publicKey: recipientPublicKey,
privateKey: myPrivateKey,
passphrase: 'my-passphrase'
});

// Encrypt email message
const encryptedEmail = await pgp.encryptEmail({
from: { address: 'sender@example.com' },
to: [{ address: 'recipient@example.com' }],
subject: 'Confidential Information',
text: 'Secret message content',
attachments: [
{ filename: 'document.pdf', content: pdfBuffer }
]
}, {
sign: true,
armor: true
});

// Send with your email provider
// await mailbox.send(encryptedEmail);

Database Field Encryptionโ€‹

import { getEncryption } from '@happyvertical/encryption';

const encryption = await getEncryption({
type: 'node',
algorithm: 'aes-256-gcm',
keyDerivation: {
password: process.env.DB_ENCRYPTION_PASSWORD,
salt: 'db-encryption-salt',
iterations: 100000
}
});

// Encrypt sensitive fields
async function saveUser(user) {
const encryptedSSN = await encryption.encryptText(user.ssn);
const encryptedCreditCard = await encryption.encryptText(user.creditCard);

await db.insert('users', {
id: user.id,
name: user.name, // Plain text
ssn: encryptedSSN,
credit_card: encryptedCreditCard
});
}

// Decrypt when retrieving
async function getUser(id) {
const row = await db.selectOne('users', { where: { id } });

return {
id: row.id,
name: row.name,
ssn: await encryption.decryptText(row.ssn),
creditCard: await encryption.decryptText(row.credit_card)
};
}

File Backup Encryptionโ€‹

import { getEncryption } from '@happyvertical/encryption';

const encryption = await getEncryption({
type: 'nacl',
secretKey: backupSecretKey
});

// Encrypt backup files
await encryption.encryptFile(
'/data/backup-2024-01.tar.gz',
'/encrypted-backups/backup-2024-01.tar.gz.enc'
);

// Decrypt when needed
await encryption.decryptFile(
'/encrypted-backups/backup-2024-01.tar.gz.enc',
'/restored/backup-2024-01.tar.gz'
);

Digital Signaturesโ€‹

import { getEncryption } from '@happyvertical/encryption';

const pgp = await getEncryption({
type: 'pgp',
privateKey: myPrivateKey,
passphrase: 'my-passphrase'
});

// Sign message
const message = 'Important announcement';
const signature = await pgp.sign(message, {
detached: true,
armor: true
});

// Verify signature
const valid = await pgp.verify(message, signature, {
publicKey: signerPublicKey
});

if (valid) {
console.log('โœ“ Signature verified - message is authentic');
} else {
console.log('โœ— Invalid signature - message may be tampered');
}

API Overviewโ€‹

Factory Functionโ€‹

function getEncryption(options: GetEncryptionOptions): Promise<Encryption>

Encryption Interfaceโ€‹

All adapters implement this unified interface:

interface Encryption {
// Text operations
encryptText(text: string, options?: EncryptOptions): Promise<string>;
decryptText(encrypted: string, options?: DecryptOptions): Promise<string>;

// File operations
encryptFile(inputPath: string, outputPath: string, options?: EncryptOptions): Promise<void>;
decryptFile(inputPath: string, outputPath: string, options?: DecryptOptions): Promise<void>;

// Buffer operations
encryptBuffer(buffer: Buffer, options?: EncryptOptions): Promise<Buffer>;
decryptBuffer(buffer: Buffer, options?: DecryptOptions): Promise<Buffer>;

// Key management
generateKeyPair(options?: KeyPairOptions): Promise<KeyPair>;
importKey(key: string | Buffer, options?: ImportKeyOptions): Promise<Key>;
exportKey(key: Key, options?: ExportKeyOptions): Promise<string | Buffer>;

// Signing (optional)
sign?(data: string | Buffer, options?: SignOptions): Promise<string | Buffer>;
verify?(data: string | Buffer, signature: string | Buffer, options?: VerifyOptions): Promise<boolean>;

// Email operations (PGP only)
encryptEmail?(message: EmailMessage, options?: EncryptEmailOptions): Promise<EmailMessage>;
decryptEmail?(message: EmailMessage, options?: DecryptEmailOptions): Promise<DecryptedEmail>;

// Adapter info
getCapabilities(): Promise<EncryptionCapabilities>;
getAdapter(): AdapterType;
}

Adapter Comparisonโ€‹

FeaturePGPNaClNode Crypto
Text Encryptionโœ…โœ…โœ…
File Encryptionโœ…โœ…โœ…
Email Encryptionโœ…โŒโŒ
Digital Signaturesโœ…โœ…โœ…
Multiple Recipientsโœ…โŒโŒ
SymmetricโŒโœ…โœ…
Asymmetricโœ…โœ…โœ…
SpeedMediumFastFast
Key SizeLargeSmallMedium
Best ForEmail, compatibilityPerformance, modern appsStandard algorithms, built-in

When to Use Each Adapterโ€‹

PGP/OpenPGP - Best for:

  • Email encryption (PGP/MIME standard)
  • Multi-recipient scenarios
  • Compatibility with existing PGP infrastructure
  • Long-term archival

NaCl/libsodium - Best for:

  • High-performance applications
  • Modern cryptography
  • File encryption
  • API token encryption
  • Real-time data encryption

Node.js Crypto - Best for:

  • Standard algorithms (AES, RSA)
  • No external dependencies needed
  • Password-based encryption (PBKDF2)
  • Enterprise requirements (FIPS compliance)

Security Considerationsโ€‹

Key Storageโ€‹

โŒ DO NOT:

  • Store private keys in plain text
  • Commit keys to version control
  • Log keys or passphrases
  • Transmit keys over insecure channels

โœ… DO:

  • Use environment variables for keys
  • Encrypt private keys with strong passphrases
  • Use hardware security modules (HSMs) for production
  • Implement key rotation policies
  • Use key derivation for password-based encryption

Best Practicesโ€‹

  1. Key Length:

    • RSA: Minimum 2048 bits (4096 recommended)
    • AES: 256 bits
    • ECC: curve25519 or P-384
  2. Algorithms:

    • โœ… Prefer: AES-256-GCM, RSA-OAEP, ECDH, NaCl
    • โŒ Avoid: DES, 3DES, MD5, SHA1
  3. Key Derivation:

    • PBKDF2: Minimum 100,000 iterations
    • Use unique salts per encryption
    • Consider Argon2 for new applications
  4. Encrypted Data Integrity:

    • Use authenticated encryption (GCM, Poly1305)
    • Always verify signatures before trusting data
    • Implement replay protection

Testingโ€‹

Run the test suite:

npm test

Run tests for a specific adapter:

npm test -- test/unit/pgp.test.ts
npm test -- test/unit/nacl.test.ts
npm test -- test/unit/node.test.ts

Run file operations tests:

npm test -- test/unit/file-operations.test.ts

Performance Benchmarksโ€‹

Approximate performance for 100KB data:

AdapterEncryptionDecryptionKey Generation
PGP (RSA 4096)~200ms~100ms~3000ms
NaCl (secretbox)~2ms~2ms~1ms
AES-256-GCM~5ms~5msN/A
RSA-OAEP 2048~50ms~100ms~500ms

Benchmarks run on M1 MacBook Pro. Your results may vary.

Documentationโ€‹

  • AGENT.md - Comprehensive developer guide with detailed API reference, architecture, and implementation phases
  • API Types - TypeScript type definitions
  • Error Handling - Custom error classes

Examplesโ€‹

See the test directory for comprehensive examples:

Contributingโ€‹

Contributions are welcome! Please see the root CONTRIBUTING.md for guidelines.

Developmentโ€‹

# Install dependencies
pnpm install

# Run tests
npm test

# Run tests in watch mode
npm test -- --watch

# Build package
npm run build

# Lint and format
npm run lint
npm run format

Licenseโ€‹

MIT License - see LICENSE for details.

Supportโ€‹


Built with โค๏ธ by HappyVertical