anything-llm/collector/utils/EncryptionWorker/index.js

78 lines
2.5 KiB
JavaScript
Raw Normal View History

[BETA] Live document sync (#1719) * wip bg workers for live document sync * Add ability to re-embed specific documents across many workspaces via background queue bgworkser is gated behind expieremental system setting flag that needs to be explictly enabled UI for watching/unwatching docments that are embedded. TODO: UI to easily manage all bg tasks and see run results TODO: UI to enable this feature and background endpoints to manage it * create frontend views and paths Move elements to correct experimental scope * update migration to delete runs on removal of watched document * Add watch support to YouTube transcripts (#1716) * Add watch support to YouTube transcripts refactor how sync is done for supported types * Watch specific files in Confluence space (#1718) Add failure-prune check for runs * create tmp workflow modifications for beta image * create tmp workflow modifications for beta image * create tmp workflow modifications for beta image * dual build update copy of alert modals * update job interval * Add support for live-sync of Github files * update copy for document sync feature * hide Experimental features from UI * update docs links * [FEAT] Implement new settings menu for experimental features (#1735) * implement new settings menu for experimental features * remove unused context save bar --------- Co-authored-by: timothycarambat <rambat1010@gmail.com> * dont run job on boot * unset workflow changes * Add persistent encryption service Relay key to collector so persistent encryption can be used Encrypt any private data in chunkSources used for replay during resync jobs * update jsDOC * Linting and organization * update modal copy for feature --------- Co-authored-by: Sean Hatfield <seanhatfield5@gmail.com>
2024-06-21 22:38:50 +02:00
const crypto = require("crypto");
// Differs from EncryptionManager in that is does not set or define the keys that will be used
// to encrypt or read data and it must be told the key (as base64 string) explicitly that will be used and is provided to
// the class on creation. This key should be the same `key` that is used by the EncryptionManager class.
class EncryptionWorker {
constructor(presetKeyBase64 = "") {
this.key = Buffer.from(presetKeyBase64, "base64");
this.algorithm = "aes-256-cbc";
this.separator = ":";
}
log(text, ...args) {
console.log(`\x1b[36m[EncryptionManager]\x1b[0m ${text}`, ...args);
}
/**
* Give a chunk source, parse its payload query param and expand that object back into the URL
* as additional query params
* @param {string} chunkSource
* @returns {URL} Javascript URL object with query params decrypted from payload query param.
*/
expandPayload(chunkSource = "") {
try {
const url = new URL(chunkSource);
if (!url.searchParams.has("payload")) return url;
const decryptedPayload = this.decrypt(url.searchParams.get("payload"));
const encodedParams = JSON.parse(decryptedPayload);
url.searchParams.delete("payload"); // remove payload prop
// Add all query params needed to replay as query params
Object.entries(encodedParams).forEach(([key, value]) =>
url.searchParams.append(key, value)
);
return url;
} catch (e) {
console.error(e);
}
return new URL(chunkSource);
}
encrypt(plainTextString = null) {
try {
if (!plainTextString)
throw new Error("Empty string is not valid for this method.");
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(this.algorithm, this.key, iv);
const encrypted = cipher.update(plainTextString, "utf8", "hex");
return [
encrypted + cipher.final("hex"),
Buffer.from(iv).toString("hex"),
].join(this.separator);
} catch (e) {
this.log(e);
return null;
}
}
decrypt(encryptedString) {
try {
const [encrypted, iv] = encryptedString.split(this.separator);
if (!iv) throw new Error("IV not found");
const decipher = crypto.createDecipheriv(
this.algorithm,
this.key,
Buffer.from(iv, "hex")
);
return decipher.update(encrypted, "hex", "utf8") + decipher.final("utf8");
} catch (e) {
this.log(e);
return null;
}
}
}
module.exports = { EncryptionWorker };