-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
93 lines (85 loc) · 2.79 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/**
* PseudoCrypt — Short, reversible, pseudo-unique hashes for numeric values.
* Inspired by KevBurnsJr's original PHP implementation:
* https://web.archive.org/web/20130727034425/http://blog.kevburnsjr.com/php-unique-hash
*
* Author: Tanish Raj (@cttricks)
* License: MIT
* Repository: https://github.com/cttricks/pseudocrypt
*
* This module provides two main functions:
* - encode: Convert a number into a pseudo-unique base62-like string
* - decode: Retrieve the original number from the encoded string
*
* ⚠️ Not cryptographically secure. Use only for ID obfuscation, pretty URLs, etc.
*/
const goldenPrimes = {
1: '1',
41: '59',
2377: '1677',
147299: '187507',
9132313: '5952585',
566201239: '643566407',
35104476161: '22071637057',
2176477521929: '294289236153',
134941606358731: '88879354792675',
8366379594239857: '7275288500431249',
518715534842869223: '280042546585394647'
};
const chars62 = [
...Array.from({ length: 10 }, (_, i) => 48 + i), // 0-9
...Array.from({ length: 26 }, (_, i) => 65 + i), // A-Z
...Array.from({ length: 26 }, (_, i) => 97 + i) // a-z
];
const base62 = (int) => {
int = BigInt(int);
let str = '';
const base = BigInt(62);
while (int > 0) {
const mod = int % base;
str += String.fromCharCode(chars62[Number(mod)]);
int = int / base;
}
return str.split('').reverse().join('');
};
const unBase62 = (str) => {
return [...str].reverse().reduce((acc, char, i) => {
const val = BigInt(chars62.indexOf(char.charCodeAt(0)));
return acc + val * (BigInt(62) ** BigInt(i));
}, BigInt(0));
};
/**
* Encodes a number into a short, base62-like hash string.
* Useful for generating pseudo-unique, URL-safe identifiers.
*
* @param {number | string | bigint} num - The numeric value to encode.
* @param {number} [len=5] - The desired length of the output hash. Must be between 1 and 10.
* @returns {string} Encoded hash string.
*
* @example
* const shortId = encode(123456); // e.g. "4Gze1"
*/
const encode = (num, len = 5) => {
num = BigInt(num);
const ceil = BigInt(62) ** BigInt(len);
const prime = BigInt(Object.keys(goldenPrimes)[len]);
const hashed = (num * prime) % ceil;
return base62(hashed).padStart(len, '0');
};
/**
* Decodes a hash string back into its original numeric value.
*
* @param {string} hash - The encoded hash string (must be generated by `encode()`).
* @returns {bigint} Original numeric value.
*
* @example
* const original = decode("4Gze1"); // 123456n
*/
const decode = (hash) => {
const len = hash.length;
const ceil = BigInt(62) ** BigInt(len);
const mmi = BigInt(Object.values(goldenPrimes)[len]);
const val = unBase62(hash);
return (val * mmi) % ceil;
};
module.exports = { encode, decode };