Most ID obfuscation libraries (Hashids, Sqids, Optimus) are reversible encodings. If you know the algorithm, you can decode tokens or manipulate them without the server detecting it. Feistly uses a Feistel cipher with HMAC-SHA256 to provide:
- Tamper detection: Modified tokens fail validation - Domain separation: User ID 100 and Order ID 100 generate different tokens with the same key - Format-preserving encryption: 64-bit input to 64-bit ciphertext, deterministic
The tradeoff is speed. Feistly does ~60K ops/sec vs millions for Hashids, but for most web apps database queries are the bottleneck anyway.
Example:
const feistly = new Feistly({ masterKey: process.env.KEY });
const token = feistly.encrypt("user", 12345); // "7nX4kP2mQ"
feistly.decrypt("user", token); // "12345"
GitHub: https://github.com/jundev76/feistly
npm: https://www.npmjs.com/package/feistlyZero dependencies (Node.js crypto only), TypeScript native, includes benchmarks.
Feedback welcome – is this solving a real problem or is it overengineering?