A cryptography algorithms library


Keywords
security, crypto, cipher, Hash, MD5, SHA1, SHA-1, SHA2, SHA-2, SHA3, SHA-3, SHA256, SHA-256, RC4, Rabbit, AES, DES, 3DES, TripleDES, PBKDF2, HMAC, HEX, Base64, Base64url, blowfish, encryption, es6, frontend, javascript, js, nodejs, typescript, web
License
MIT
Install
npm install crypto-es@2.0.3

Documentation

npm version License: MIT TypeScript

A modern JavaScript/TypeScript cryptography library offering a comprehensive collection of hash functions, ciphers, encoders, and key derivation functions. Pure TypeScript implementation with full ES6 module support and CommonJS compatibility.

✨ Features

  • 🚀 Modern Implementation - Pure TypeScript with full type definitions
  • 📦 Dual Module Support - ESM and CommonJS outputs for maximum compatibility
  • 🌳 Tree-Shakeable - Import only what you need for optimal bundle size
  • 🔄 Streaming API - Process large data efficiently with progressive hashing/encryption
  • 🔐 Comprehensive Algorithms - Hash functions, symmetric ciphers, KDFs, and more
  • 💪 Zero Dependencies - No external dependencies for lightweight integration
  • High Performance - Optimized implementations with streaming support
  • 🛡️ Battle-Tested - Extensive test suite with known test vectors

📦 Installation

# Using npm
npm install crypto-es

# Using yarn
yarn add crypto-es

# Using pnpm
pnpm add crypto-es

🚀 Quick Start

Basic Hashing

import { MD5, SHA256, SHA512 } from 'crypto-es';

// Simple hashing
const hash1 = MD5('Hello World').toString();
// d41d8cd98f00b204e9800998ecf8427e

const hash2 = SHA256('Hello World').toString();
// a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b3f8b4c5cdcdcd9d0

const hash3 = SHA512('Hello World').toString();
// 2c74fd17edafd80e8447b0d46741ee243b7eb74dd2149a0ab1b9246fb30382f27e853d8585719e0e67cbda0daa8f51671064615d645ae27acb15bfb1447f459b

Basic Encryption

import { AES, DES, TripleDES } from 'crypto-es';

// AES encryption
const encrypted = AES.encrypt('Secret Message', 'secret key').toString();
const decrypted = AES.decrypt(encrypted, 'secret key').toString();

// DES encryption
const desEncrypted = DES.encrypt('Secret Message', 'secret key').toString();
const desDecrypted = DES.decrypt(desEncrypted, 'secret key').toString();

Encoding/Decoding

import { Base64, Hex, UTF8 } from 'crypto-es';

// Base64 encoding
const base64 = Base64.stringify(UTF8.parse('Hello World'));
// SGVsbG8gV29ybGQ=

// Hex encoding
const hex = Hex.stringify(UTF8.parse('Hello World'));
// 48656c6c6f20576f726c64

📚 Complete Algorithm Reference

Hash Functions

Algorithm Description Output Size Usage
MD5 Legacy hash function 128 bits Legacy compatibility only
SHA1 SHA-1 hash function 160 bits Legacy systems
SHA224 SHA-2 family 224 bits Moderate security
SHA256 SHA-2 family 256 bits Recommended
SHA384 SHA-2 family 384 bits High security
SHA512 SHA-2 family 512 bits Maximum security
SHA3 Latest SHA-3 standard 224-512 bits Modern applications
RIPEMD160 RIPEMD family 160 bits Specialized use

Symmetric Ciphers

Algorithm Key Size Block Size Description
AES 128/192/256 bits 128 bits Industry standard
DES 56 bits 64 bits Legacy only
TripleDES 168 bits 64 bits Legacy upgrade from DES
Rabbit 128 bits Stream High-performance stream cipher
RC4 Variable Stream Legacy stream cipher
Blowfish 32-448 bits 64 bits Variable key length

Key Derivation Functions

Algorithm Description Usage
PBKDF2 Password-Based KDF v2 Recommended for passwords
EvpKDF OpenSSL EVP KDF OpenSSL compatibility

Encoders

Encoder Description
Base64 Standard Base64 encoding
Base64url URL-safe Base64 encoding
Hex Hexadecimal encoding
UTF8 UTF-8 text encoding
UTF16 UTF-16 text encoding
Latin1 Latin-1 text encoding

Cipher Modes

Mode Description IV Required
CBC Cipher Block Chaining (default) Yes
ECB Electronic Codebook No
CFB Cipher Feedback Yes
OFB Output Feedback Yes
CTR Counter Yes

Padding Schemes

Padding Description
PKCS7 PKCS#7 padding (default)
AnsiX923 ANSI X9.23 padding
ISO10126 ISO 10126 padding
ISO97971 ISO/IEC 9797-1 padding
ZeroPadding Zero byte padding
NoPadding No padding

📖 Detailed Usage Guide

Hash Algorithms

MD5

import { MD5, HmacMD5 } from 'crypto-es';

// Basic hashing
const hash = MD5('message').toString();

// HMAC-MD5
const hmac = HmacMD5('message', 'secret key').toString();

// Progressive hashing
const hasher = MD5Algo.create();
hasher.update('message part 1');
hasher.update('message part 2');
const progressiveHash = hasher.finalize().toString();

SHA1

import { SHA1, HmacSHA1, SHA1Algo } from 'crypto-es';

// Basic hashing
const hash = SHA1('message').toString();

// HMAC-SHA1
const hmac = HmacSHA1('message', 'secret key').toString();

// Progressive hashing
const hasher = SHA1Algo.create();
hasher.update('large data chunk 1');
hasher.update('large data chunk 2');
const result = hasher.finalize().toString();

SHA224

import { SHA224, HmacSHA224 } from 'crypto-es';

// Basic hashing
const hash = SHA224('message').toString();

// HMAC-SHA224
const hmac = HmacSHA224('message', 'secret key').toString();

SHA256

import { SHA256, HmacSHA256, SHA256Algo } from 'crypto-es';

// Basic hashing
const hash = SHA256('message').toString();

// HMAC-SHA256 (commonly used for API authentication)
const hmac = HmacSHA256('message', 'secret key').toString();

// Progressive hashing for large files
const hasher = SHA256Algo.create();
hasher.update('chunk1');
hasher.update('chunk2');
hasher.update('chunk3');
const fileHash = hasher.finalize().toString();

// Different output formats
import { Hex, Base64 } from 'crypto-es';
const hashHex = SHA256('message').toString(Hex);
const hashBase64 = SHA256('message').toString(Base64);

SHA384

import { SHA384, HmacSHA384 } from 'crypto-es';

// Basic hashing
const hash = SHA384('message').toString();

// HMAC-SHA384
const hmac = HmacSHA384('message', 'secret key').toString();

SHA512

import { SHA512, HmacSHA512, SHA512Algo } from 'crypto-es';

// Basic hashing
const hash = SHA512('message').toString();

// HMAC-SHA512
const hmac = HmacSHA512('message', 'secret key').toString();

// Progressive hashing with typed arrays
import { WordArray } from 'crypto-es';
const hasher = SHA512Algo.create();
const data1 = WordArray.create(new Uint8Array([1, 2, 3, 4]));
const data2 = WordArray.create(new Uint8Array([5, 6, 7, 8]));
hasher.update(data1);
hasher.update(data2);
const result = hasher.finalize();

SHA3

import { SHA3 } from 'crypto-es';

// SHA3-256 (default)
const hash256 = SHA3('message').toString();

// SHA3-224
const hash224 = SHA3('message', { outputLength: 224 }).toString();

// SHA3-384
const hash384 = SHA3('message', { outputLength: 384 }).toString();

// SHA3-512
const hash512 = SHA3('message', { outputLength: 512 }).toString();

RIPEMD160

import { RIPEMD160, HmacRIPEMD160 } from 'crypto-es';

// Basic hashing
const hash = RIPEMD160('message').toString();

// HMAC-RIPEMD160
const hmac = HmacRIPEMD160('message', 'secret key').toString();

Symmetric Encryption

AES

import { AES, ECB, CBC, CFB, OFB, CTR, NoPadding, PKCS7 } from 'crypto-es';

// Simple encryption with password
const encrypted = AES.encrypt('Secret Message', 'password').toString();
const decrypted = AES.decrypt(encrypted, 'password').toString(UTF8);

// AES with specific key size (128/192/256 bits)
import { PBKDF2, WordArray } from 'crypto-es';
const key128 = PBKDF2('password', 'salt', { keySize: 128/32 });
const key192 = PBKDF2('password', 'salt', { keySize: 192/32 });
const key256 = PBKDF2('password', 'salt', { keySize: 256/32 });

// Encryption with different modes
const encrypted1 = AES.encrypt('message', key256, { mode: ECB }).toString();
const encrypted2 = AES.encrypt('message', key256, { mode: CBC }).toString();
const encrypted3 = AES.encrypt('message', key256, { mode: CFB }).toString();
const encrypted4 = AES.encrypt('message', key256, { mode: OFB }).toString();
const encrypted5 = AES.encrypt('message', key256, { mode: CTR }).toString();

// Custom IV (Initialization Vector)
const iv = WordArray.random(128/8);
const encrypted = AES.encrypt('message', key256, { iv: iv }).toString();

// Different padding schemes
const encrypted6 = AES.encrypt('message', key256, { padding: PKCS7 }).toString();
const encrypted7 = AES.encrypt('message', key256, { padding: NoPadding }).toString();

// Streaming encryption for large data
import { AESAlgo } from 'crypto-es';
const key = PBKDF2('password', 'salt', { keySize: 256/32 });
const iv = WordArray.random(128/8);
const aes = AESAlgo.createEncryptor(key, { iv: iv });

const part1 = aes.process('part 1 of data');
const part2 = aes.process('part 2 of data');
const part3 = aes.process('part 3 of data');
const encrypted = part1.concat(part2).concat(part3).concat(aes.finalize());

DES

import { DES, DESAlgo } from 'crypto-es';

// Simple DES encryption
const encrypted = DES.encrypt('Message', 'password').toString();
const decrypted = DES.decrypt(encrypted, 'password').toString(UTF8);

// DES with custom options
import { ECB, NoPadding } from 'crypto-es';
const encrypted = DES.encrypt('Message', 'password', {
  mode: ECB,
  padding: NoPadding
}).toString();

// Streaming DES
const des = DESAlgo.createEncryptor('password');
const encrypted = des.finalize('Message').toString();

TripleDES

import { TripleDES, TripleDESAlgo } from 'crypto-es';

// Simple 3DES encryption
const encrypted = TripleDES.encrypt('Message', 'password').toString();
const decrypted = TripleDES.decrypt(encrypted, 'password').toString(UTF8);

// 3DES with 192-bit key
import { PBKDF2 } from 'crypto-es';
const key = PBKDF2('password', 'salt', { keySize: 192/32 });
const encrypted = TripleDES.encrypt('Message', key).toString();

// Streaming 3DES
const cipher = TripleDESAlgo.createEncryptor(key);
const encrypted = cipher.finalize('Message').toString();

Rabbit

import { Rabbit, RabbitAlgo } from 'crypto-es';

// Simple Rabbit encryption
const encrypted = Rabbit.encrypt('Message', 'password').toString();
const decrypted = Rabbit.decrypt(encrypted, 'password').toString(UTF8);

// Rabbit with IV
import { WordArray } from 'crypto-es';
const key = WordArray.random(128/8);
const iv = WordArray.random(64/8);
const encrypted = Rabbit.encrypt('Message', key, { iv: iv }).toString();

// Streaming Rabbit
const cipher = RabbitAlgo.createEncryptor(key, { iv: iv });
const encrypted = cipher.finalize('Message').toString();

RC4

import { RC4, RC4Drop } from 'crypto-es';

// Simple RC4 encryption
const encrypted = RC4.encrypt('Message', 'password').toString();
const decrypted = RC4.decrypt(encrypted, 'password').toString(UTF8);

// RC4Drop (more secure variant)
const encrypted = RC4Drop.encrypt('Message', 'password').toString();
const decrypted = RC4Drop.decrypt(encrypted, 'password').toString(UTF8);

// RC4 with custom drop value
import { RC4DropAlgo } from 'crypto-es';
const cipher = RC4DropAlgo.createEncryptor('password', { drop: 3072/4 });
const encrypted = cipher.finalize('Message').toString();

Blowfish

import { Blowfish, BlowfishAlgo } from 'crypto-es';

// Simple Blowfish encryption
const encrypted = Blowfish.encrypt('Message', 'password').toString();
const decrypted = Blowfish.decrypt(encrypted, 'password').toString(UTF8);

// Blowfish with variable key length (32-448 bits)
import { PBKDF2 } from 'crypto-es';
const key128 = PBKDF2('password', 'salt', { keySize: 128/32 });
const key256 = PBKDF2('password', 'salt', { keySize: 256/32 });
const key448 = PBKDF2('password', 'salt', { keySize: 448/32 });

const encrypted1 = Blowfish.encrypt('Message', key128).toString();
const encrypted2 = Blowfish.encrypt('Message', key256).toString();
const encrypted3 = Blowfish.encrypt('Message', key448).toString();

Key Derivation Functions

PBKDF2

import { PBKDF2, SHA256Algo, SHA512Algo } from 'crypto-es';

// Basic PBKDF2 with default settings (SHA1, 1 iteration)
const key = PBKDF2('password', 'salt');

// PBKDF2 with custom settings
const key256 = PBKDF2('password', 'salt', {
  keySize: 256/32,        // 256-bit key
  iterations: 10000,      // 10,000 iterations
  hasher: SHA256Algo     // SHA256 hasher
});

const key512 = PBKDF2('password', 'salt', {
  keySize: 512/32,        // 512-bit key
  iterations: 100000,     // 100,000 iterations
  hasher: SHA512Algo     // SHA512 hasher
});

// Use for AES encryption
import { AES } from 'crypto-es';
const derivedKey = PBKDF2('mypassword', 'mysalt', {
  keySize: 256/32,
  iterations: 10000
});
const encrypted = AES.encrypt('Secret', derivedKey).toString();

EvpKDF

import { EvpKDF, MD5Algo, SHA256Algo } from 'crypto-es';

// Basic EvpKDF
const key = EvpKDF('password', 'salt');

// EvpKDF with custom settings
const key256 = EvpKDF('password', 'salt', {
  keySize: 256/32,
  iterations: 1000,
  hasher: SHA256Algo
});

// Compatible with OpenSSL EVP_BytesToKey
const opensslKey = EvpKDF('password', 'salt', {
  keySize: 256/32,
  ivSize: 128/32,
  hasher: MD5Algo
});

Encoders

Base64

import { Base64, UTF8, WordArray } from 'crypto-es';

// Encode string to Base64
const encoded = Base64.stringify(UTF8.parse('Hello World'));
// SGVsbG8gV29ybGQ=

// Decode Base64 to string
const decoded = UTF8.stringify(Base64.parse('SGVsbG8gV29ybGQ='));
// Hello World

// Base64 with WordArray
const wordArray = WordArray.create([0x48656c6c, 0x6f20576f, 0x726c6400], 11);
const base64 = Base64.stringify(wordArray);

Base64url

import { Base64url, UTF8 } from 'crypto-es';

// URL-safe Base64 encoding (no padding, - and _ instead of + and /)
const encoded = Base64url.stringify(UTF8.parse('Hello World??'));
// SGVsbG8gV29ybGQ_Pw

// Decode Base64url
const decoded = UTF8.stringify(Base64url.parse('SGVsbG8gV29ybGQ_Pw'));
// Hello World??

Hex

import { Hex, UTF8, WordArray } from 'crypto-es';

// Encode string to Hex
const encoded = Hex.stringify(UTF8.parse('Hello World'));
// 48656c6c6f20576f726c64

// Decode Hex to string
const decoded = UTF8.stringify(Hex.parse('48656c6c6f20576f726c64'));
// Hello World

// Hex with WordArray
const wordArray = WordArray.create([0x48656c6c, 0x6f20576f, 0x726c6400], 11);
const hex = Hex.stringify(wordArray);
// 48656c6c6f20576f726c64

UTF8

import { UTF8, WordArray } from 'crypto-es';

// Parse UTF8 string to WordArray
const wordArray = UTF8.parse('Hello World 你好世界');

// Stringify WordArray to UTF8
const utf8String = UTF8.stringify(wordArray);

// Handle special characters
const emoji = UTF8.parse('😀🎉🚀');
const back = UTF8.stringify(emoji);

UTF16

import { UTF16, UTF16BE, UTF16LE } from 'crypto-es';

// UTF16 Big Endian
const encodedBE = UTF16BE.stringify(UTF16BE.parse('Hello'));

// UTF16 Little Endian
const encodedLE = UTF16LE.stringify(UTF16LE.parse('Hello'));

// Auto-detect endianness
const encoded = UTF16.stringify(UTF16.parse('Hello'));

Latin1

import { Latin1 } from 'crypto-es';

// Parse Latin1 string to WordArray
const wordArray = Latin1.parse('Hello World');

// Stringify WordArray to Latin1
const latin1String = Latin1.stringify(wordArray);

Cipher Modes

CBC

import { AES, CBC, PKCS7 } from 'crypto-es';

// CBC mode (default)
const encrypted = AES.encrypt('message', 'password', {
  mode: CBC,
  padding: PKCS7
}).toString();

ECB

import { AES, ECB } from 'crypto-es';

// ECB mode (not recommended for security)
const encrypted = AES.encrypt('message', 'password', {
  mode: ECB
}).toString();

CFB

import { AES, CFB } from 'crypto-es';

// CFB mode
const encrypted = AES.encrypt('message', 'password', {
  mode: CFB
}).toString();

OFB

import { AES, OFB } from 'crypto-es';

// OFB mode
const encrypted = AES.encrypt('message', 'password', {
  mode: OFB
}).toString();

CTR

import { AES, CTR } from 'crypto-es';

// CTR mode
const encrypted = AES.encrypt('message', 'password', {
  mode: CTR
}).toString();

Padding Schemes

PKCS7

import { AES, PKCS7 } from 'crypto-es';

// PKCS7 padding (default)
const encrypted = AES.encrypt('message', 'password', {
  padding: PKCS7
}).toString();

AnsiX923

import { AES, AnsiX923 } from 'crypto-es';

// ANSI X9.23 padding
const encrypted = AES.encrypt('message', 'password', {
  padding: AnsiX923
}).toString();

ISO10126

import { AES, ISO10126 } from 'crypto-es';

// ISO 10126 padding
const encrypted = AES.encrypt('message', 'password', {
  padding: ISO10126
}).toString();

ISO97971

import { AES, ISO97971 } from 'crypto-es';

// ISO/IEC 9797-1 padding
const encrypted = AES.encrypt('message', 'password', {
  padding: ISO97971
}).toString();

ZeroPadding

import { AES, ZeroPadding } from 'crypto-es';

// Zero padding
const encrypted = AES.encrypt('message', 'password', {
  padding: ZeroPadding
}).toString();

NoPadding

import { AES, NoPadding, WordArray } from 'crypto-es';

// No padding (message must be multiple of block size)
const message = WordArray.create([0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff]);
const encrypted = AES.encrypt(message, 'password', {
  padding: NoPadding
}).toString();

🔧 Advanced Topics

Working with WordArray

import { WordArray, UTF8, Hex, Base64 } from 'crypto-es';

// Create WordArray from different sources
const wa1 = WordArray.create([0x12345678, 0x9abcdef0]);
const wa2 = WordArray.random(16); // 16 random bytes
const wa3 = UTF8.parse('Hello World');
const wa4 = Hex.parse('48656c6c6f');
const wa5 = Base64.parse('SGVsbG8=');

// Concatenate WordArrays
const combined = wa1.concat(wa2).concat(wa3);

// Clone WordArray
const cloned = wa1.clone();

// Get bytes
const bytes = wa1.sigBytes;

// Convert to different formats
const hex = wa1.toString(Hex);
const base64 = wa1.toString(Base64);
const utf8 = wa1.toString(UTF8);

Streaming Large Files

import { SHA256Algo, AESAlgo, WordArray } from 'crypto-es';

// Hash large file in chunks
async function hashLargeFile(file: File): Promise<string> {
  const hasher = SHA256Algo.create();
  const chunkSize = 1024 * 1024; // 1MB chunks
  
  for (let offset = 0; offset < file.size; offset += chunkSize) {
    const chunk = file.slice(offset, offset + chunkSize);
    const arrayBuffer = await chunk.arrayBuffer();
    const wordArray = WordArray.create(arrayBuffer);
    hasher.update(wordArray);
  }
  
  return hasher.finalize().toString();
}

// Encrypt large data stream
function encryptStream(key: WordArray, iv: WordArray) {
  const cipher = AESAlgo.createEncryptor(key, { iv });
  
  return {
    process: (chunk: string) => cipher.process(chunk),
    finalize: () => cipher.finalize()
  };
}

Custom Cipher Configuration

import { AES, CBC, PKCS7, SerializableCipher, OpenSSLFormatter } from 'crypto-es';

// Create custom cipher configuration
const cipherParams = {
  mode: CBC,
  padding: PKCS7,
  format: OpenSSLFormatter,
  blockSize: 128/32,
  formatter: OpenSSLFormatter
};

// Use with encryption
const encrypted = AES.encrypt('message', 'password', cipherParams);

// Serialize/deserialize encrypted data
const serialized = encrypted.toString();
const deserialized = SerializableCipher.parse(serialized);

HMAC for API Authentication

import { HmacSHA256, Hex } from 'crypto-es';

// Create API signature
function createApiSignature(
  method: string,
  path: string,
  body: string,
  secret: string
): string {
  const message = `${method}\n${path}\n${body}`;
  return HmacSHA256(message, secret).toString(Hex);
}

// Verify webhook signature
function verifyWebhookSignature(
  payload: string,
  signature: string,
  secret: string
): boolean {
  const expectedSignature = HmacSHA256(payload, secret).toString(Hex);
  return signature === expectedSignature;
}

Password Storage Best Practices

import { PBKDF2, SHA256Algo, WordArray, Hex } from 'crypto-es';

// Hash password for storage
function hashPassword(password: string): { hash: string; salt: string } {
  const salt = WordArray.random(128/8);
  const hash = PBKDF2(password, salt, {
    keySize: 256/32,
    iterations: 100000,
    hasher: SHA256Algo
  });
  
  return {
    hash: hash.toString(Hex),
    salt: salt.toString(Hex)
  };
}

// Verify password
function verifyPassword(
  password: string,
  storedHash: string,
  storedSalt: string
): boolean {
  const salt = Hex.parse(storedSalt);
  const hash = PBKDF2(password, salt, {
    keySize: 256/32,
    iterations: 100000,
    hasher: SHA256Algo
  });
  
  return hash.toString(Hex) === storedHash;
}

🌐 Browser & Node.js Compatibility

Browser Usage

<!-- Via CDN -->
<script src="https://unpkg.com/crypto-es@latest/dist/index.js"></script>
<script>
  const hash = cryptoEs.SHA256('message').toString();
</script>

Webpack Configuration

// webpack.config.js
module.exports = {
  resolve: {
    extensions: ['.ts', '.js'],
    fallback: {
      crypto: false // crypto-es doesn't need Node crypto
    }
  }
};

Vite Configuration

// vite.config.js
export default {
  optimizeDeps: {
    include: ['crypto-es']
  }
};

TypeScript Configuration

// tsconfig.json
{
  "compilerOptions": {
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true
  }
}

📊 API Reference

Core Classes

WordArray

class WordArray {
  static create(words?: number[], sigBytes?: number): WordArray;
  static random(nBytes: number): WordArray;
  
  sigBytes: number;
  words: number[];
  
  concat(wordArray: WordArray): WordArray;
  clone(): WordArray;
  toString(encoder?: Encoder): string;
}

CipherParams

class CipherParams {
  ciphertext: WordArray;
  key?: WordArray;
  iv?: WordArray;
  salt?: WordArray;
  algorithm?: Cipher;
  mode?: Mode;
  padding?: Padding;
  blockSize?: number;
  formatter?: Formatter;
  
  static create(cipherParams: Partial<CipherParams>): CipherParams;
  toString(formatter?: Formatter): string;
}

Hasher

interface Hasher {
  update(messageUpdate: string | WordArray): Hasher;
  finalize(messageUpdate?: string | WordArray): WordArray;
}

Cipher

interface Cipher {
  encrypt(message: string | WordArray, key: string | WordArray, cfg?: CipherCfg): CipherParams;
  decrypt(ciphertext: string | CipherParams, key: string | WordArray, cfg?: CipherCfg): WordArray;
}

🚀 Performance Tips

  1. Use streaming for large data: Process data in chunks with update() and finalize()
  2. Choose appropriate algorithms: SHA256 for general hashing, AES for encryption
  3. Reuse hasher instances: Create once, reset and reuse for multiple operations
  4. Use typed arrays: Convert ArrayBuffer to WordArray for better performance
  5. Enable tree-shaking: Import only needed algorithms to reduce bundle size

🔒 Security Considerations

⚠️ Important Security Notes

  1. Never use MD5 or SHA1 for security: These are broken algorithms, use SHA256 or higher
  2. Always use authenticated encryption: Combine encryption with HMAC for integrity
  3. Use sufficient iterations for PBKDF2: Minimum 10,000, recommend 100,000+
  4. Generate random IVs: Never reuse IVs with the same key
  5. Use constant-time comparison: Prevent timing attacks when comparing hashes
  6. Store passwords properly: Use PBKDF2 with salt, never store plain text
  7. Avoid ECB mode: Use CBC, CTR, or GCM modes instead

Recommended Algorithms

  • Hashing: SHA256, SHA512, SHA3
  • Encryption: AES with 256-bit keys
  • Key Derivation: PBKDF2 with 100,000+ iterations
  • HMAC: HmacSHA256 or HmacSHA512

🛠️ Development

Setup

# Clone repository
git clone https://github.com/entronad/crypto-es.git
cd crypto-es

# Install dependencies
npm install

# Build library
npm run build

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

Available Scripts

  • npm run build - Build the library
  • npm run build:watch - Build in watch mode
  • npm test - Run tests
  • npm run test:watch - Run tests in watch mode
  • npm run test:coverage - Generate coverage report
  • npm run typecheck - Check TypeScript types
  • npm run clean - Clean build artifacts

Project Structure

crypto-es/
├── src/                # Source code
│   ├── core.ts        # Core utilities
│   ├── cipher-core.ts # Cipher base classes
│   ├── md5.ts         # MD5 implementation
│   ├── sha256.ts      # SHA256 implementation
│   ├── aes.ts         # AES implementation
│   └── ...            # Other algorithms
├── __tests__/         # Test files
├── dist/              # Built output
│   ├── *.mjs         # ESM modules
│   ├── *.cjs         # CommonJS modules
│   └── *.d.ts        # TypeScript definitions
└── package.json       # Package configuration

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Guidelines

  • Write tests for new features
  • Ensure all tests pass
  • Follow existing code style
  • Update documentation as needed
  • Add yourself to contributors

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

MIT © LIN Chen


Note: This library is for legitimate use only. Always follow your local laws and regulations regarding cryptography.