@vvlad1973/crypto
v2.4.0
Published
A JavaScript class for encrypting and decrypting text using specified cryptographic parameters (algorithm, password, etc.)
Maintainers
Readme
@vvlad1973/crypto
A TypeScript library for encrypting and decrypting text using AES-256-CTR encryption with PBKDF2 key derivation.
This library uses Node.js native crypto module for secure encryption operations.
Features
- AES-256-CTR encryption for reversible data (e.g. PII)
- One-way password hashing with
scrypt(OWASP-recommended, memory-hard) - PBKDF2 key derivation with configurable parameters
- Support for both number and Buffer initialization vectors
- TypeScript support with full type definitions
- Dual API: constructor with options object or separate parameters
- UUID v4 generation utility
- Zero external dependencies (uses native Node.js crypto)
Installation
npm install @vvlad1973/cryptoUsage
Importing
import Crypto, { CryptoOptions, isCrypto } from '@vvlad1973/crypto';Basic Usage
import Crypto from '@vvlad1973/crypto';
const password = 'your-password';
const salt = 'your-salt';
// Create an instance using separate parameters
const crypto = new Crypto(password, salt);
// Encrypt a text
const plainText = 'Hello, World!';
const encryptedText = crypto.encrypt(plainText);
console.log('Encrypted:', encryptedText);
// Decrypt the text
const decryptedText = crypto.decrypt(encryptedText);
console.log('Decrypted:', decryptedText);Using Options Object
import Crypto, { CryptoOptions } from '@vvlad1973/crypto';
const options: CryptoOptions = {
password: 'your-password',
salt: 'your-salt',
algorithm: 'SHA512',
iterations: 1000,
keyLength: 32,
iv: 5
};
const crypto = new Crypto(options);
const encrypted = crypto.encrypt('Secret message');
const decrypted = crypto.decrypt(encrypted);Using Buffer IV
import Crypto from '@vvlad1973/crypto';
import { randomBytes } from 'crypto';
// Generate a random 16-byte initialization vector
const ivBuffer = randomBytes(16);
const crypto = new Crypto({
password: 'your-password',
salt: 'your-salt',
iv: ivBuffer
});
const encrypted = crypto.encrypt('Secret message');Generating UUIDs
import Crypto from '@vvlad1973/crypto';
// Generate a UUID v4
const uuid = Crypto.getUUID();
console.log(uuid); // e.g., '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'Type Guard
import Crypto, { isCrypto } from '@vvlad1973/crypto';
const crypto = new Crypto('password', 'salt');
if (isCrypto(crypto)) {
// TypeScript knows crypto has encrypt/decrypt methods
const encrypted = crypto.encrypt('text');
}Password Hashing
The Crypto class encrypts recoverable data. For passwords, which must never be
recoverable, use the standalone hashPassword / verifyPassword functions. They are
built on Node.js native scrypt (a memory-hard, OWASP-recommended KDF), generate a
fresh per-record salt on every call, and compare in constant time.
import { hashPassword, verifyPassword } from '@vvlad1973/crypto';
// On registration / password change — store the returned string as-is:
const stored = await hashPassword('correct horse battery staple');
// e.g. 'scrypt$1$N=131072,r=8,p=1$<saltHex>$<hashHex>'
// On login:
const ok = await verifyPassword('correct horse battery staple', stored); // true
const no = await verifyPassword('wrong password', stored); // falseThe stored value is a single self-describing string that carries the algorithm, a
format version, the scrypt parameters and the salt — so the cost profile can change
over time without any storage migration, and the value is distinguishable from other
schemes (legacy bcrypt $2a$…, a future argon2id$…, etc.).
To trade strength for speed (for example in a test suite), lower the cost parameters:
const cheap = await hashPassword('pw', { params: { N: 16384 } });The reversible
encrypt/decryptcipher and thehashPassword/verifyPasswordfunctions are not interchangeable: use the cipher for data you must read back, and the password functions for secrets that must stay one-way.
API
Constructor
Using separate parameters
new Crypto(
password: string,
salt: string,
algorithm?: string,
iterations?: number,
keyLength?: number,
iv?: number | Buffer
)Using options object
new Crypto(options: CryptoOptions)CryptoOptions interface:
interface CryptoOptions {
password: string; // Password for key derivation
salt: string; // Salt for key derivation
algorithm?: string; // Hash algorithm (default: 'SHA512')
iterations?: number; // PBKDF2 iterations (default: 1000)
keyLength?: number; // Key length in bytes (default: 32)
iv?: number | Buffer; // Initialization vector (default: random 16 bytes)
}Parameters:
password- The password used for PBKDF2 key derivationsalt- The salt used for PBKDF2 key derivationalgorithm- Hash algorithm for PBKDF2 (default:'SHA512')iterations- Number of PBKDF2 iterations (default:1000)keyLength- Derived key length in bytes (default:32for AES-256)iv- Initialization vector: either a number (converted to 16-byte Buffer) or a Buffer directly (default: random 16 bytes)
Instance Methods
encrypt(text: string): string
Encrypts the given text using AES-256-CTR encryption.
text- The plain text to encrypt- Returns: The encrypted text as a hexadecimal string
decrypt(text: string): string
Decrypts the given encrypted text using AES-256-CTR decryption.
text- The encrypted text as a hexadecimal string- Returns: The decrypted plain text
Static Methods
Crypto.getUUID(): string
Generates a random UUID v4 string using Node.js native crypto.
- Returns: A UUID v4 string (e.g.,
'9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d')
Utility Functions
isCrypto(object: any): object is Crypto
Type guard function to check if an object is an instance of Crypto.
object- The object to check- Returns:
trueif the object is a Crypto instance,falseotherwise
Password Functions
hashPassword(plain: string, options?: HashPasswordOptions): Promise<string>
Hashes a plaintext password with scrypt for storage. A fresh 16-byte salt is
generated per call.
plain- The plaintext password to hashoptions.params- Optional scrypt parameter overrides (N,r,p,keyLength); omitted fields fall back toDEFAULT_SCRYPT_PARAMS- Returns: The self-describing stored hash
scrypt$1$<params>$<saltHex>$<hashHex>
verifyPassword(plain: string, stored: string): Promise<boolean>
Verifies a candidate password against a value produced by hashPassword, comparing in
constant time. A structurally invalid or non-scrypt stored value yields false
rather than throwing.
plain- The candidate plaintext passwordstored- The stored hash string- Returns:
truewhen the password matches,falseotherwise
DEFAULT_SCRYPT_PARAMS
The default OWASP scrypt profile: { N: 131072, r: 8, p: 1, keyLength: 32 }
(about 128 MiB and 100-250 ms per hash on a modern CPU).
Testing
This library uses Vitest for testing with comprehensive coverage requirements.
Run all tests
npm testRun tests in watch mode
npm run test:watchRun tests with UI
npm run test:uiGenerate coverage report
npm run test:coverageCoverage Requirements
- Lines: 90%
- Functions: 85%
- Branches: 90%
- Statements: 90%
Current coverage: 100% across all metrics
Building
To build the TypeScript project:
npm run buildThis will compile TypeScript files to the dist directory with type definitions.
Documentation
To generate TypeDoc documentation:
npm run docDocumentation will be generated in the docs directory.
License
This project is licensed under the MIT License with Commercial Use - see the LICENSE file for details.
Author
Vladislav Vnukovskiy [email protected]
