Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

ff1-js

kasfi.tamiya197MIT1.0.2TypeScript support: included

FF1 (Format-Preserving Encryption) implementation in JavaScript/TypeScript

ff1, format-preserving-encryption, encryption, cryptography, fpe, nist, aes, security, typescript, javascript

readme

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 characters
  • minLength: 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 build
  • dist/esm/ - ES Module build
  • dist/umd/ - UMD build for browsers
  • dist/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

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass
  6. Submit a pull request

📄 License

MIT License - see LICENSE file for details.

🔗 References

📞 Support

For support and questions:


Made with ❤️ by PT Ifabula Digital Kreasi