aboutsummaryrefslogtreecommitdiff
path: root/src/lib/crypto.ts
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-01-24 13:09:50 +0000
committerFuwn <[email protected]>2026-01-24 13:09:50 +0000
commit396acf3bbbe00a192cb0ea0a9ccf91b1d8d2850b (patch)
treeb9df4ca6a70db45cfffbae6fdd7252e20fb8e93c /src/lib/crypto.ts
downloadumami-main.tar.xz
umami-main.zip
Initial commitHEADmain
Created from https://vercel.com/new
Diffstat (limited to 'src/lib/crypto.ts')
-rw-r--r--src/lib/crypto.ts65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/lib/crypto.ts b/src/lib/crypto.ts
new file mode 100644
index 0000000..a6d912b
--- /dev/null
+++ b/src/lib/crypto.ts
@@ -0,0 +1,65 @@
+import crypto from 'node:crypto';
+import { v4, v5, v7 } from 'uuid';
+
+const ALGORITHM = 'aes-256-gcm';
+const IV_LENGTH = 16;
+const SALT_LENGTH = 64;
+const TAG_LENGTH = 16;
+const TAG_POSITION = SALT_LENGTH + IV_LENGTH;
+const ENC_POSITION = TAG_POSITION + TAG_LENGTH;
+
+const HASH_ALGO = 'sha512';
+const HASH_ENCODING = 'hex';
+
+const getKey = (password: string, salt: Buffer) =>
+ crypto.pbkdf2Sync(password, salt, 10000, 32, 'sha512');
+
+export function encrypt(value: any, secret: any) {
+ const iv = crypto.randomBytes(IV_LENGTH);
+ const salt = crypto.randomBytes(SALT_LENGTH);
+ const key = getKey(secret, salt);
+
+ const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
+
+ const encrypted = Buffer.concat([cipher.update(String(value), 'utf8'), cipher.final()]);
+
+ const tag = cipher.getAuthTag();
+
+ return Buffer.concat([salt, iv, tag, encrypted]).toString('base64');
+}
+
+export function decrypt(value: any, secret: any) {
+ const str = Buffer.from(String(value), 'base64');
+ const salt = str.subarray(0, SALT_LENGTH);
+ const iv = str.subarray(SALT_LENGTH, TAG_POSITION);
+ const tag = str.subarray(TAG_POSITION, ENC_POSITION);
+ const encrypted = str.subarray(ENC_POSITION);
+
+ const key = getKey(secret, salt);
+
+ const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
+
+ decipher.setAuthTag(tag);
+
+ return decipher.update(encrypted) + decipher.final('utf8');
+}
+
+export function hash(...args: string[]) {
+ return crypto.createHash(HASH_ALGO).update(args.join('')).digest(HASH_ENCODING);
+}
+
+export function md5(...args: string[]) {
+ return crypto.createHash('md5').update(args.join('')).digest('hex');
+}
+
+export function secret() {
+ return hash(process.env.APP_SECRET || process.env.DATABASE_URL);
+}
+
+export function uuid(...args: any) {
+ if (args.length) {
+ return v5(hash(...args, secret()), v5.DNS);
+ }
+
+ return process.env.USE_UUIDV7 ? v7() : v4();
+}