ff1-js
A pure JavaScript/TypeScript implementation of FF1 (Format-Preserving Encryption) based on the NIST SP 800-38G specification. This library provides secure format-preserving encryption that maintains the format and length of your data while ensuring strong cryptographic protection.
🚀 Features
- NIST Compliant: Implements FF1 according to NIST SP 800-38G specification
- Format Preserving: Maintains the format and length of your data
- Multiple Alphabets: Support for numeric, alphanumeric, hexadecimal, and custom alphabets
- TypeScript Support: Full TypeScript definitions included
- Zero Dependencies: Pure JavaScript implementation with no external dependencies
- Cross-Platform: Works in Node.js and modern browsers
- Comprehensive Testing: 100% test coverage with extensive test suite
📦 Installation
npm install ff1-js
🎯 Quick Start
Basic Usage
import { FF1, Alphabets } from 'ff1-js';
// Create an FF1 instance for alphanumeric encryption
const ff1 = new FF1(
'your-32-byte-key-here', // Key (16, 24, or 32 bytes)
'your-tweak-value', // Tweak
62, // Radix (base)
Alphabets.ALPHANUMERIC // Alphabet
);
// Encrypt
const encrypted = ff1.encrypt('Hello123');
console.log(encrypted); // Output: "K0d8I, J7vaK!"
// Decrypt
const decrypted = ff1.decrypt(encrypted);
console.log(decrypted); // Output: "Hello123"
Using Helper Functions
import { createNumericFF1, createAlphanumericFF1 } from 'ff1-js';
// For numeric data (0-9)
const numericFF1 = createNumericFF1('your-key', 'your-tweak');
const encrypted = numericFF1.encrypt('123456');
console.log(encrypted); // Output: "789012" (same length, numeric only)
// For alphanumeric data (0-9, a-z, A-Z)
const alphanumericFF1 = createAlphanumericFF1('your-key', 'your-tweak');
const encrypted = alphanumericFF1.encrypt('ABC123');
console.log(encrypted); // Output: "XyZ789" (same length, alphanumeric)
📚 API Reference
FF1 Class
Constructor
new FF1(
key: Buffer | string,
tweak: Buffer | string,
radix: number,
alphabet: string,
minLength?: number,
maxLength?: number
)
Parameters:
key
: Encryption key (16, 24, or 32 bytes)tweak
: Tweak value (0 to 2^104 bytes)radix
: Base of the alphabet (2-256)alphabet
: String containing all valid charactersminLength
: Minimum input length (default: 2)maxLength
: Maximum input length (default: 100)
Methods
encrypt(input: string, tweak?: Buffer | string): string
Encrypts a string while preserving its format.
decrypt(input: string, tweak?: Buffer | string): string
Decrypts a string while preserving its format.
getConfig(): FF1Config
Returns the current configuration.
Predefined Alphabets
import { Alphabets } from 'ff1-js';
Alphabets.NUMERIC // "0123456789" (radix: 10)
Alphabets.LOWERCASE // "abcdefghijklmnopqrstuvwxyz" (radix: 26)
Alphabets.UPPERCASE // "ABCDEFGHIJKLMNOPQRSTUVWXYZ" (radix: 26)
Alphabets.ALPHANUMERIC // "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" (radix: 62)
Alphabets.HEXADECIMAL // "0123456789abcdef" (radix: 16)
Alphabets.BASE64 // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" (radix: 64)
Helper Functions
createFF1(key, tweak, alphabet?, minLength?, maxLength?)
Creates an FF1 instance with a custom alphabet.
createNumericFF1(key, tweak, minLength?, maxLength?)
Creates an FF1 instance for numeric data (0-9).
createAlphanumericFF1(key, tweak, minLength?, maxLength?)
Creates an FF1 instance for alphanumeric data (0-9, a-z, A-Z).
🔧 Usage Examples
Credit Card Number Encryption
import { createNumericFF1 } from 'ff1-js';
const ff1 = createNumericFF1('your-secret-key-32-bytes', 'card-tweak');
// Encrypt credit card number
const cardNumber = '1234567890123456';
const encrypted = ff1.encrypt(cardNumber);
console.log(encrypted); // "9876543210987654" (same length, numeric)
// Decrypt
const decrypted = ff1.decrypt(encrypted);
console.log(decrypted); // "1234567890123456"
Social Security Number Encryption
import { createNumericFF1 } from 'ff1-js';
const ff1 = createNumericFF1('your-secret-key-32-bytes', 'ssn-tweak');
const ssn = '123456789';
const encrypted = ff1.encrypt(ssn);
console.log(encrypted); // "987654321" (same length, numeric)
Custom Alphabet
import { FF1 } from 'ff1-js';
// Custom alphabet for phone numbers (digits + dash)
const phoneAlphabet = '0123456789-';
const ff1 = new FF1('your-key', 'your-tweak', 11, phoneAlphabet);
const phone = '555-1234';
const encrypted = ff1.encrypt(phone);
console.log(encrypted); // "123-5678" (same format, same length)
Hexadecimal Data
import { FF1, Alphabets } from 'ff1-js';
const ff1 = new FF1('your-key', 'your-tweak', 16, Alphabets.HEXADECIMAL);
const hexData = 'abcdef123456';
const encrypted = ff1.encrypt(hexData);
console.log(encrypted); // "123456abcdef" (same length, hexadecimal)
🔒 Security Considerations
Key Management
- Use cryptographically secure random keys
- Store keys securely (environment variables, key management systems)
- Rotate keys regularly
- Never hardcode keys in your source code
Tweak Usage
- Use unique tweaks for different data types
- Tweak should be deterministic for the same data type
- Consider using a hash of the data type as tweak
Example Secure Setup
import { createAlphanumericFF1 } from 'ff1-js';
import crypto from 'crypto';
// Generate secure key
const key = crypto.randomBytes(32);
// Create tweak from data type
const dataType = 'user-id';
const tweak = crypto.createHash('sha256').update(dataType).digest();
const ff1 = createAlphanumericFF1(key, tweak);
// Use for user ID encryption
const userId = 'user123';
const encrypted = ff1.encrypt(userId);
🧪 Testing
Run the test suite:
npm test
Run with coverage:
npm run test:coverage
📦 Building
Build the library:
npm run build
This creates:
dist/cjs/
- CommonJS builddist/esm/
- ES Module builddist/umd/
- UMD build for browsersdist/types/
- TypeScript definitions
🌐 Browser Usage
For browser usage, include the UMD build:
<script src="dist/umd/ff1.js"></script>
<script>
const ff1 = new FF1.FF1('your-key', 'your-tweak', 62, FF1.Alphabets.ALPHANUMERIC);
const encrypted = ff1.encrypt('Hello123');
</script>
📋 Requirements
- Node.js >= 18.0.0
- TypeScript >= 5.0.0 (for development)
🤝 Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
📄 License
MIT License - see LICENSE file for details.
🔗 References
📞 Support
For support and questions:
- Email: kasfi.tamiya@ifabula.com
- GitLab Issues: Create an issue
Made with ❤️ by PT Ifabula Digital Kreasi