mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-05-10 12:25:02 +00:00
perf: move encryption/decryption to a separate thread
This commit is contained in:
parent
0b337a13a4
commit
b7c7e002eb
16 changed files with 310 additions and 147 deletions
|
@ -1,9 +1,9 @@
|
|||
import test from "ava";
|
||||
import { decrypt, encrypt } from "./crypt";
|
||||
|
||||
test("encrypt() followed by decrypt()", (t) => {
|
||||
test("encrypt() followed by decrypt()", async (t) => {
|
||||
const original = "banana 123 👀 💕"; // Includes emojis to verify utf8 stuff works
|
||||
const encrypted = encrypt(original);
|
||||
const decrypted = decrypt(encrypted);
|
||||
const encrypted = await encrypt(original);
|
||||
const decrypted = await decrypt(encrypted);
|
||||
t.is(decrypted, original);
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import crypto from "crypto";
|
||||
import { spawn, Worker } from "threads";
|
||||
import "../loadEnv";
|
||||
import type { CryptFns } from "./cryptWorker";
|
||||
|
||||
if (!process.env.KEY) {
|
||||
// tslint:disable-next-line:no-console
|
||||
|
@ -8,27 +9,19 @@ if (!process.env.KEY) {
|
|||
}
|
||||
|
||||
const KEY = process.env.KEY;
|
||||
const ALGORITHM = "aes-256-gcm";
|
||||
let workerPromise: Promise<CryptFns> | null = null;
|
||||
|
||||
export function encrypt(str) {
|
||||
// Based on https://gist.github.com/rjz/15baffeab434b8125ca4d783f4116d81
|
||||
|
||||
const iv = crypto.randomBytes(16);
|
||||
const cipher = crypto.createCipheriv(ALGORITHM, KEY, iv);
|
||||
|
||||
let encrypted = cipher.update(str, "utf8", "base64");
|
||||
encrypted += cipher.final("base64");
|
||||
return `${iv.toString("base64")}.${cipher.getAuthTag().toString("base64")}.${encrypted}`;
|
||||
async function getWorker(): Promise<CryptFns> {
|
||||
if (workerPromise == null) {
|
||||
workerPromise = spawn(new Worker("./cryptWorker")) as unknown as Promise<CryptFns>;
|
||||
}
|
||||
return workerPromise;
|
||||
}
|
||||
|
||||
export function decrypt(encrypted) {
|
||||
// Based on https://gist.github.com/rjz/15baffeab434b8125ca4d783f4116d81
|
||||
|
||||
const [iv, authTag, encryptedStr] = encrypted.split(".");
|
||||
const decipher = crypto.createDecipheriv(ALGORITHM, KEY, Buffer.from(iv, "base64"));
|
||||
decipher.setAuthTag(Buffer.from(authTag, "base64"));
|
||||
|
||||
let decrypted = decipher.update(encryptedStr, "base64", "utf8");
|
||||
decrypted += decipher.final("utf8");
|
||||
return decrypted;
|
||||
export async function encrypt(data: string) {
|
||||
return (await getWorker()).encrypt(data, KEY);
|
||||
}
|
||||
|
||||
export async function decrypt(data: string) {
|
||||
return (await getWorker()).decrypt(data, KEY);
|
||||
}
|
||||
|
|
11
backend/src/utils/cryptHelpers.ts
Normal file
11
backend/src/utils/cryptHelpers.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { decrypt, encrypt } from "./crypt";
|
||||
|
||||
export async function encryptJson(obj: any): Promise<string> {
|
||||
const serialized = JSON.stringify(obj);
|
||||
return encrypt(serialized);
|
||||
}
|
||||
|
||||
export async function decryptJson<T extends unknown>(encrypted: string): Promise<T> {
|
||||
const decrypted = await decrypt(encrypted);
|
||||
return JSON.parse(decrypted);
|
||||
}
|
31
backend/src/utils/cryptWorker.ts
Normal file
31
backend/src/utils/cryptWorker.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
import crypto from "crypto";
|
||||
import { expose } from "threads";
|
||||
|
||||
const ALGORITHM = "aes-256-gcm";
|
||||
|
||||
function encrypt(str, key) {
|
||||
// Based on https://gist.github.com/rjz/15baffeab434b8125ca4d783f4116d81
|
||||
|
||||
const iv = crypto.randomBytes(16);
|
||||
const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
|
||||
|
||||
let encrypted = cipher.update(str, "utf8", "base64");
|
||||
encrypted += cipher.final("base64");
|
||||
return `${iv.toString("base64")}.${cipher.getAuthTag().toString("base64")}.${encrypted}`;
|
||||
}
|
||||
|
||||
function decrypt(encrypted, key) {
|
||||
// Based on https://gist.github.com/rjz/15baffeab434b8125ca4d783f4116d81
|
||||
|
||||
const [iv, authTag, encryptedStr] = encrypted.split(".");
|
||||
const decipher = crypto.createDecipheriv(ALGORITHM, key, Buffer.from(iv, "base64"));
|
||||
decipher.setAuthTag(Buffer.from(authTag, "base64"));
|
||||
|
||||
let decrypted = decipher.update(encryptedStr, "base64", "utf8");
|
||||
decrypted += decipher.final("utf8");
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
const toExpose = { encrypt, decrypt };
|
||||
expose(toExpose);
|
||||
export type CryptFns = typeof toExpose;
|
Loading…
Add table
Add a link
Reference in a new issue