Skip to content

Commit a032b7c

Browse files
committed
Adding Lib Code
1 parent 6464805 commit a032b7c

6 files changed

Lines changed: 134 additions & 1 deletion

File tree

.npmignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Ignore dev and build configs
2+
rollup.config.js
3+
*.log
4+
5+
# Ignore local test files
6+
.test/
7+
8+
# Ignore everything not needed in the final npm package
9+
.gitignore
10+
*.md
11+
example/
12+
examples/
13+
14+
# Ignore dev-specific files
15+
.vscode/
16+
.idea/
17+
18+
# Ignore node_modules (shouldn't be included anyway)
19+
node_modules/

dist/pseudocrypt.min.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/pseudocrypt.min.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.js

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

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
".": "./index.js"
99
},
1010
"scripts": {
11+
"build": "rollup -c",
1112
"test": "node .test/index.js"
1213
},
1314
"repository": {
@@ -37,5 +38,9 @@
3738
"homepage": "https://github.com/cttricks/pseudocrypt#readme",
3839
"engines": {
3940
"node": ">=12"
41+
},
42+
"devDependencies": {
43+
"rollup": "^2.79.2",
44+
"rollup-plugin-terser": "^7.0.2"
4045
}
41-
}
46+
}

rollup.config.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { terser } from "rollup-plugin-terser";
2+
3+
export default {
4+
input: "index.js",
5+
output: {
6+
file: "dist/pseudocrypt.min.js",
7+
format: "umd",
8+
name: "PseudoCrypt",
9+
exports: "named",
10+
sourcemap: true
11+
},
12+
plugins: [terser()]
13+
};

0 commit comments

Comments
 (0)