@voideddev/enc-server
v0.2.5
Published
Server-side encryption, hashing and obfuscation with map-based character substitution library
Downloads
87
Maintainers
Readme
voideddev Enc-Server Library
A comprehensive server-side encryption and obfuscation library that provides a complete pipeline for securing sensitive data with compression, encryption, and character-level obfuscation.
⚡ Powered by Rust - All cryptographic operations run through native Rust bindings for maximum performance and security.
🚀 Features
- Native Rust Core: All crypto operations powered by Rust for blazing-fast performance
- Multi-layer Security: Compression → Encryption → Obfuscation pipeline
- Flexible Key Management: Support for custom keys, key rotation, and key derivation
- Temperature-based Obfuscation: Configurable complexity levels (0.0 to 1.0)
- Multiple Compression Algorithms: Brotli, Gzip, or automatic selection
- AEAD Encryption: XChaCha20-Poly1305 (preferred) with AES-256-GCM fallback
- Deterministic Maps: Seeded random generation for reproducible obfuscation
- Comprehensive Statistics: Built-in metrics and performance tracking
📦 Installation
npm install @voideddev/enc-serverPlatform Support
This package includes prebuilt native binaries for:
- ✅ Windows x64 (win32-x64-msvc)
- ✅ Linux x64 (linux-x64-gnu)
For macOS users: The package will attempt to build from source during installation. This requires Rust to be installed.
🔧 Core Components
1. Encryption Module
Handles all cryptographic operations with AEAD (Authenticated Encryption with Associated Data).
import {
generateKey,
encrypt,
decrypt,
deriveKeyHkdf,
deriveKeyPbkdf2,
type EncryptResult,
} from "@voideddev/enc-server";
// Generate a random 256-bit key
const key = generateKey();
// Encrypt data (requires Buffer input)
const dataBuffer = Buffer.from("secret message", "utf-8");
const encrypted = encrypt(dataBuffer, key);
// Decrypt data
const decrypted = decrypt(encrypted, key);
console.log(decrypted.toString("utf-8")); // "secret message"
// Derive key using HKDF (for deterministic keys from secrets)
const derivedKey = deriveKeyHkdf(
Buffer.from("my-secret", "utf-8"), // input key material
Buffer.from("my-salt", "utf-8"), // salt (or null)
Buffer.from("my-context", "utf-8") // info/context
);
// Derive key using PBKDF2 (for password-based key derivation)
const passwordKey = deriveKeyPbkdf2(
Buffer.from("user-password", "utf-8"),
Buffer.from("random-salt", "utf-8"),
100000 // iterations
);Key Functions:
| Function | Description |
|----------|-------------|
| generateKey() | Creates cryptographically secure 256-bit key (returns Buffer) |
| encrypt(data, key, algorithm?) | Encrypts Buffer with AEAD (XChaCha20-Poly1305 or AES-256-GCM) |
| decrypt(result, key) | Decrypts EncryptResult back to Buffer |
| deriveKeyHkdf(ikm, salt, info) | HKDF-based key derivation (all params are Buffers) |
| deriveKeyPbkdf2(password, salt, iterations) | PBKDF2-based key derivation |
encrypt Response (EncryptResult):
{
encrypted: Buffer, // Encrypted ciphertext
algorithm: "xchacha20-poly1305" | "aes-256-gcm", // Algorithm used
nonce: Buffer, // Random nonce/IV
tag: Buffer // Authentication tag
}2. Hashing Functions
Individual hashing functions for data integrity and verification. All functions are synchronous.
import {
hash,
hashWithSalt,
compareHashes,
generateHmac,
verifyHmac,
hashPbkdf2,
verifyPbkdf2,
fingerprint,
safetyNumbers,
generateSalt,
} from "@voideddev/enc-server";
// Basic hashing
const hashResult = hash(Buffer.from("data", "utf-8"), "sha256");
// Returns: "3a6eb0790f39ac87c94f3856b2dd2c5d110e6811602261a9a923d3bb23adc8b7"
// Salted hashing
const salt = generateSalt(16);
const saltedHash = hashWithSalt(Buffer.from("data", "utf-8"), salt, "sha256");
// Timing-safe hash comparison
const isEqual = compareHashes(Buffer.from(hash1), Buffer.from(hash2));
// HMAC for message authentication
const hmacKey = generateSalt(32);
const hmac = generateHmac(Buffer.from("message", "utf-8"), hmacKey, "sha256");
const isValid = verifyHmac(Buffer.from("message", "utf-8"), hmac, hmacKey, "sha256");
// PBKDF2 for password hashing (high iteration count)
const passwordHash = hashPbkdf2(
Buffer.from("password", "utf-8"),
salt,
100000 // iterations
);
const passwordValid = verifyPbkdf2(
Buffer.from("password", "utf-8"),
passwordHash,
salt,
100000
);
// Generate fingerprint (short hash for display)
const fp = fingerprint(Buffer.from("data", "utf-8"), 8);
// Returns: "3a6eb079"
// Generate safety numbers (Signal-style verification)
const numbers = safetyNumbers(Buffer.from("public-key", "utf-8"), 5);
// Returns: "12345 67890 12345 67890"Hash Functions Reference:
| Function | Parameters | Returns |
|----------|------------|---------|
| hash(data, algorithm?) | Buffer, 'sha256' | 'sha512' | string |
| hashWithSalt(data, salt, algorithm?) | Buffer, Buffer, algorithm | string |
| compareHashes(a, b) | Buffer, Buffer | boolean |
| generateHmac(data, key, algorithm?) | Buffer, Buffer, algorithm | string |
| verifyHmac(data, hmac, key, algorithm?) | Buffer, string, Buffer, algorithm | boolean |
| hashPbkdf2(data, salt, iterations) | Buffer, Buffer, number | string |
| verifyPbkdf2(data, hash, salt, iterations) | Buffer, string, Buffer, number | boolean |
| fingerprint(data, length?) | Buffer, number | string |
| safetyNumbers(data, groupSize?) | Buffer, number | string |
3. Compression Module
Provides compression with Brotli or Gzip. All functions are synchronous.
import { compress, decompress, type CompressionResult } from "@voideddev/enc-server";
// Compress data
const data = Buffer.from("Hello World! ".repeat(100), "utf-8");
const compressed = compress(data, "brotli", 6); // algorithm, level
console.log(compressed.originalSize); // 1300
console.log(compressed.compressedSize); // ~50
console.log(compressed.compressionRatio); // ~0.04
console.log(compressed.algorithm); // "brotli"
// Decompress
const decompressed = decompress(compressed.compressed, "brotli");compress Response (CompressionResult):
{
compressed: Buffer, // Compressed data
algorithm: "brotli" | "gzip" | "none",
originalSize: number,
compressedSize: number,
compressionRatio: number // compressedSize / originalSize
}4. Obfuscation Module
Character-level obfuscation using temperature-based maps. Seed is required for deterministic map generation.
import {
generateMap,
obfuscate,
deobfuscate,
analyzeMap,
getExpansionRatio,
type ObfuscationMap,
type ObfuscationResult,
type MapAnalysis,
} from "@voideddev/enc-server";
// Generate obfuscation map (seed is REQUIRED)
const map = generateMap(
0.5, // temperature (0.0 - 1.0)
"my-seed" // seed for deterministic generation
);
// Obfuscate text
const result = obfuscate(
"Hello World",
map,
"selection-seed", // optional: seed for mapping selection
"round-robin" // strategy: 'random' | 'round-robin'
);
console.log(result.obfuscated); // obfuscated string
console.log(result.expansionRatio); // e.g., 3.5
console.log(result.mappingsUsed); // number of mappings applied
// Deobfuscate
const original = deobfuscate(result.obfuscated, map);
console.log(original); // "Hello World"
// Analyze map characteristics
const analysis = analyzeMap(map);
console.log(analysis.temperature); // 0.5
console.log(analysis.totalMappings); // total mapping count
console.log(analysis.averageMappingsPerChar); // avg per character
console.log(analysis.expansionRatio); // expected expansion
console.log(analysis.computeScore); // computational cost (0-100)
console.log(analysis.entropy); // entropy increase
// Get expansion ratio
const ratio = getExpansionRatio(map);obfuscate Response (ObfuscationResult):
{
obfuscated: string,
originalLength: number,
obfuscatedLength: number,
expansionRatio: number,
uniqueCharsObfuscated: number,
mappingsUsed: number
}Temperature Profiles:
| Temperature | Complexity | Use Case | |-------------|------------|----------| | 0.0 - 0.2 | Minimal | Performance-critical, light obfuscation | | 0.3 - 0.5 | Medium | Balanced security and performance | | 0.6 - 0.8 | High | Enhanced security | | 0.9 - 1.0 | Extreme | Maximum obfuscation |
5. Full Pipeline (Recommended)
The encryptWithMap function provides a complete pipeline: compress → encrypt → obfuscate.
import {
generateKey,
encryptWithMap,
decryptWithMap,
decryptWithMapString,
type EncryptWithMapOptions,
type EncryptWithMapResult,
} from "@voideddev/enc-server";
// Generate key
const key = generateKey();
// Full pipeline encrypt
const result = encryptWithMap("sensitive data", {
key,
temperature: 0.5, // obfuscation temperature
seed: "my-deterministic-seed", // REQUIRED for map generation
compressionAlgorithm: "brotli",
compressionLevel: 6,
});
console.log(result.data); // obfuscated string
console.log(result.map); // ObfuscationMap (store this!)
console.log(result.originalSize); // original byte size
console.log(result.compressedSize); // after compression
console.log(result.encryptedSize); // after encryption
console.log(result.compressionUsed); // "brotli" | "gzip" | "none"
// Full pipeline decrypt (returns Buffer)
const decryptedBuffer = decryptWithMap(result.data, result.map, key);
// Full pipeline decrypt (returns string)
const decryptedString = decryptWithMapString(result.data, result.map, key);
console.log(decryptedString); // "sensitive data"Reusing Maps:
// Generate a map once
const map = generateMap(0.5, "my-seed");
// Reuse it for multiple encryptions
const result1 = encryptWithMap("data 1", { key, map });
const result2 = encryptWithMap("data 2", { key, map });encryptWithMap Options (EncryptWithMapOptions):
{
key: Buffer, // REQUIRED: encryption key
temperature?: number, // 0.0 - 1.0, default 0.5
seed?: string, // Required if map not provided
map?: ObfuscationMap, // Optional: reuse existing map
compressionAlgorithm?: "brotli" | "gzip",
compressionLevel?: number // 1-11 for brotli, 1-9 for gzip
}encryptWithMap Response (EncryptWithMapResult):
{
data: string, // Final obfuscated data
map: ObfuscationMap, // Map used (store with data!)
originalSize: number,
compressedSize: number,
encryptedSize: number,
compressionUsed: "brotli" | "gzip" | "none"
}6. VoidedService Class
High-level service class for easy integration.
import { VoidedService } from "@voideddev/enc-server";
// Create service with options
const service = new VoidedService({
encryptionKey: generateKey(), // optional, auto-generated if not provided
temperature: 0.5,
seed: "my-seed", // REQUIRED for obfuscateOnly
compressionAlgorithm: "brotli",
});
// Get the key (useful if auto-generated)
const key = service.getKey();
// Full pipeline encrypt
const encrypted = service.encrypt("sensitive data");
console.log(encrypted.data); // obfuscated string
console.log(encrypted.map); // store this!
// Full pipeline decrypt
const decrypted = service.decrypt(encrypted.data, encrypted.map);
console.log(decrypted); // "sensitive data"
// Obfuscation only (no encryption) - requires seed in constructor
const { obfuscated, map } = service.obfuscateOnly("text to obfuscate");
const original = service.deobfuscateOnly(obfuscated, map);VoidedServiceOptions:
{
encryptionKey?: Buffer, // Auto-generated if not provided
temperature?: number, // Default: 0.5
seed?: string, // Required for obfuscateOnly
compressionAlgorithm?: "brotli" | "gzip" // Default: "brotli"
}7. Key Manager
In-memory key management with rotation support. Note: Keys are lost on restart - implement persistence for production.
import { KeyManager, type StoredKey } from "@voideddev/enc-server";
// Create key manager with initial key
const km = new KeyManager(initialKey);
// Or let it generate a key
const km2 = new KeyManager();
// Generate and activate new key
const newKey = km.generateAndActivateKey();
// Add external key
km.addKey(externalKey, true); // true = make active
// Get active key
const active = km.activeKey;
console.log(active.id); // key ID
console.log(active.key); // Buffer
console.log(active.createdAt); // Date
// Rotate to new key
const rotated = km.rotateKey();
// Get key by ID
const specificKey = km.getKey("key-id");
// Export for persistence (you need to implement storage)
const exportedData = km.toJSON();
// Store exportedData in your database/secure storage8. Re-encryption for Key Rotation
import { reEncryptWithNewKey } from "@voideddev/enc-server";
// Re-encrypt data with a new key
const reEncrypted = reEncryptWithNewKey(
encryptedResult.data,
encryptedResult.map,
oldKey,
newKey,
{
regenerateMap: false, // Keep same map
temperature: 0.5, // New map temperature if regenerating
}
);9. Utility Functions
import {
randomBytes,
generateSalt,
secureWipe,
base64Encode,
base64Decode,
hexEncode,
hexDecode,
} from "@voideddev/enc-server";
// Generate random bytes
const bytes = randomBytes(32);
// Generate salt
const salt = generateSalt(16); // default: 16 bytes
// Securely wipe sensitive data from memory
secureWipe(sensitiveBuffer);
// Encoding utilities
const b64 = base64Encode(buffer);
const decoded = base64Decode(b64);
const hex = hexEncode(buffer);
const decodedHex = hexDecode(hex);10. Streaming Utilities
For large data processing:
import {
createCompressionStream,
createDecompressionStream,
createEncryptionStream,
createDecryptionStream,
createObfuscateStream,
createDeobfuscateStream,
createChunker,
createLineSplitter,
} from "@voideddev/enc-server";
// Create streaming transforms
const compressionStream = createCompressionStream("brotli");
const decompressionStream = createDecompressionStream("brotli");
const encryptionStream = createEncryptionStream(key);
const decryptionStream = createDecryptionStream(key);
const obfuscateStream = createObfuscateStream(map, seed);
const deobfuscateStream = createDeobfuscateStream(map);11. Statistics Tracker
import { StatsTracker, type Metric } from "@voideddev/enc-server";
const stats = StatsTracker.instance;
// Add metrics
stats.add({
label: "encryption-operation",
originalSize: 1000,
compressedSize: 800,
obfuscatedSize: 1200,
expansionRatio: 1.2,
computeUnits: 50,
algorithm: "brotli",
temperature: 0.5,
durationMs: 150,
});
// Get summary
const summary = stats.summary;
// Print formatted summary
stats.printSummary();
// Export to JSON file
stats.dumpToJson("encryption-stats.json");12. Limits and Validation
import {
SERVER_MAX_UPLOAD_BYTES,
SERVER_MAX_UPLOAD_HUMAN,
STREAMING_THRESHOLD_BYTES,
VOI_SERVER_FILE_TOO_LARGE,
VOI_STREAMING_REQUIRED,
assertWithinServerUploadLimit,
shouldStream,
createByteLimitGuard,
} from "@voideddev/enc-server";
// Check if data is within limits
assertWithinServerUploadLimit(data.length); // throws if too large
// Check if streaming should be used
if (shouldStream(data.length)) {
// Use streaming API
}
// Create a byte limit guard transform
const guard = createByteLimitGuard(maxBytes);13. Benchmarking
import {
benchmarkAll,
benchmarkCompression,
benchmarkEncryption,
benchmarkObfuscation,
benchmarkHashing,
benchmarkPipeline,
type OpBenchmarkResult,
} from "@voideddev/enc-server";
// Run all benchmarks
const results = await benchmarkAll();
// Run specific benchmarks
const compressionBench = await benchmarkCompression();
const encryptionBench = await benchmarkEncryption();
const obfuscationBench = await benchmarkObfuscation();
const hashingBench = await benchmarkHashing();
const pipelineBench = await benchmarkPipeline();🔒 Security Considerations
Key Management
- Never hardcode keys in your application
- Use environment variables or secure key stores
- Implement proper key rotation policies
- KeyManager is in-memory only - implement persistence for production
- Use
deriveKeyHkdf()orderiveKeyPbkdf2()for deterministic keys from secrets
Hashing vs Encryption vs HMAC
| Type | Purpose | Reversible |
|------|---------|------------|
| Hashing (hash) | Data integrity, fingerprinting | No |
| Salted Hashing (hashWithSalt) | Secure storage | No |
| PBKDF2 (hashPbkdf2) | Password hashing | No |
| HMAC (generateHmac) | Message authentication | No |
| Encryption (encrypt) | Data confidentiality | Yes |
Temperature Settings
| Range | Performance | Security | Use Case | |-------|-------------|----------|----------| | 0.0-0.3 | Fastest | Basic | High throughput, light obfuscation | | 0.4-0.6 | Balanced | Good | General purpose | | 0.7-1.0 | Slower | Maximum | High security requirements |
Map Security
- Maps should be treated as sensitive data
- Store maps securely alongside encrypted data
- Use deterministic seeds for reproducible obfuscation
- Consider regenerating maps periodically
📊 Performance Guidelines
Size Thresholds
- Small data (< 100 bytes): Skip compression
- Medium data (100-1KB): Use lower temperatures (0.0-0.3)
- Large data (> 1KB): Full pipeline with auto-compression
- Very large data (> 1GB): Use streaming APIs
Memory Usage
- Higher temperatures increase memory usage
- Monitor expansion ratios for large datasets
- Use streaming for very large files
🧪 Complete API Reference
Encryption
| Function | Signature |
|----------|-----------|
| generateKey() | () => Buffer |
| encrypt(data, key, algorithm?) | (Buffer, Buffer, Algorithm?) => EncryptResult |
| decrypt(encrypted, key) | (EncryptResult, Buffer) => Buffer |
| deriveKeyHkdf(ikm, salt, info) | (Buffer, Buffer \| null, Buffer) => Buffer |
| deriveKeyPbkdf2(password, salt, iterations) | (Buffer, Buffer, number) => Buffer |
Hashing
| Function | Signature |
|----------|-----------|
| hash(data, algorithm?) | (Buffer, Algorithm?) => string |
| hashWithSalt(data, salt, algorithm?) | (Buffer, Buffer, Algorithm?) => string |
| compareHashes(a, b) | (Buffer, Buffer) => boolean |
| generateHmac(data, key, algorithm?) | (Buffer, Buffer, Algorithm?) => string |
| verifyHmac(data, hmac, key, algorithm?) | (Buffer, string, Buffer, Algorithm?) => boolean |
| hashPbkdf2(data, salt, iterations) | (Buffer, Buffer, number) => string |
| verifyPbkdf2(data, hash, salt, iterations) | (Buffer, string, Buffer, number) => boolean |
| fingerprint(data, length?) | (Buffer, number?) => string |
| safetyNumbers(data, groupSize?) | (Buffer, number?) => string |
Compression
| Function | Signature |
|----------|-----------|
| compress(data, algorithm?, level?) | (Buffer, Algorithm?, number?) => CompressionResult |
| decompress(data, algorithm) | (Buffer, Algorithm) => Buffer |
Obfuscation
| Function | Signature |
|----------|-----------|
| generateMap(temperature?, seed, charset?) | (number?, string, string?) => ObfuscationMap |
| obfuscate(text, map, seed?, strategy?) | (string, ObfuscationMap, string?, Strategy?) => ObfuscationResult |
| deobfuscate(text, map) | (string, ObfuscationMap) => string |
| analyzeMap(map) | (ObfuscationMap) => MapAnalysis |
| getExpansionRatio(map) | (ObfuscationMap) => number |
Pipeline
| Function | Signature |
|----------|-----------|
| encryptWithMap(data, options) | (string \| Buffer, EncryptWithMapOptions) => EncryptWithMapResult |
| decryptWithMap(data, map, key) | (string, ObfuscationMap, Buffer) => Buffer |
| decryptWithMapString(data, map, key) | (string, ObfuscationMap, Buffer) => string |
Utility
| Function | Signature |
|----------|-----------|
| randomBytes(length) | (number) => Buffer |
| generateSalt(length?) | (number?) => Buffer |
| secureWipe(buffer) | (Buffer) => void |
| base64Encode(data) | (Buffer) => string |
| base64Decode(encoded) | (string) => Buffer |
| hexEncode(data) | (Buffer) => string |
| hexDecode(encoded) | (string) => Buffer |
Classes
| Class | Description |
|-------|-------------|
| VoidedService | High-level encryption service |
| KeyManager | In-memory key management with rotation |
| StatsTracker | Performance metrics collection |
| SigningService | Digital signatures (Node.js crypto) |
Types
type EncryptResult = {
encrypted: Buffer;
algorithm: "xchacha20-poly1305" | "aes-256-gcm";
nonce: Buffer;
tag: Buffer;
};
type CompressionResult = {
compressed: Buffer;
algorithm: "gzip" | "brotli" | "none";
originalSize: number;
compressedSize: number;
compressionRatio: number;
};
type ObfuscationMap = Record<string, string[]>;
type ObfuscationResult = {
obfuscated: string;
originalLength: number;
obfuscatedLength: number;
expansionRatio: number;
uniqueCharsObfuscated: number;
mappingsUsed: number;
};
type MapAnalysis = {
temperature: number;
totalMappings: number;
averageMappingsPerChar: number;
averageMappingLength: number;
expansionRatio: number;
computeScore: number;
entropy: number;
};
type EncryptWithMapOptions = {
key: Buffer;
temperature?: number;
seed?: string;
map?: ObfuscationMap;
compressionAlgorithm?: "brotli" | "gzip";
compressionLevel?: number;
};
type EncryptWithMapResult = {
data: string;
map: ObfuscationMap;
originalSize: number;
compressedSize: number;
encryptedSize: number;
compressionUsed: "brotli" | "gzip" | "none";
};
type VoidedServiceOptions = {
encryptionKey?: Buffer;
temperature?: number;
seed?: string;
compressionAlgorithm?: "brotli" | "gzip";
};
type StoredKey = {
id: string;
key: Buffer;
createdAt: Date;
};🤝 Contributing
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
📄 License
MIT License - see LICENSE file for details.
🆘 Support
For issues, questions, or contributions, please open an issue on the GitHub repository.
