|
|
const crypto = require("crypto"); |
|
|
const { dumpENV } = require("../helpers/updateENV"); |
|
|
|
|
|
|
|
|
|
|
|
class EncryptionManager { |
|
|
#keyENV = "SIG_KEY"; |
|
|
#saltENV = "SIG_SALT"; |
|
|
#encryptionKey; |
|
|
#encryptionSalt; |
|
|
|
|
|
constructor({ key = null, salt = null } = {}) { |
|
|
this.#loadOrCreateKeySalt(key, salt); |
|
|
this.key = crypto.scryptSync(this.#encryptionKey, this.#encryptionSalt, 32); |
|
|
this.algorithm = "aes-256-cbc"; |
|
|
this.separator = ":"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.xPayload = this.key.toString("base64"); |
|
|
} |
|
|
|
|
|
log(text, ...args) { |
|
|
console.log(`\x1b[36m[EncryptionManager]\x1b[0m ${text}`, ...args); |
|
|
} |
|
|
|
|
|
#loadOrCreateKeySalt(_key = null, _salt = null) { |
|
|
if (!!_key && !!_salt) { |
|
|
this.log( |
|
|
"Pre-assigned key & salt for encrypting arbitrary data was used." |
|
|
); |
|
|
this.#encryptionKey = _key; |
|
|
this.#encryptionSalt = _salt; |
|
|
return; |
|
|
} |
|
|
|
|
|
if (!process.env[this.#keyENV] || !process.env[this.#saltENV]) { |
|
|
this.log("Self-assigning key & salt for encrypting arbitrary data."); |
|
|
process.env[this.#keyENV] = crypto.randomBytes(32).toString("hex"); |
|
|
process.env[this.#saltENV] = crypto.randomBytes(32).toString("hex"); |
|
|
if (process.env.NODE_ENV === "production") dumpENV(); |
|
|
} else |
|
|
this.log("Loaded existing key & salt for encrypting arbitrary data."); |
|
|
|
|
|
this.#encryptionKey = process.env[this.#keyENV]; |
|
|
this.#encryptionSalt = process.env[this.#saltENV]; |
|
|
return; |
|
|
} |
|
|
|
|
|
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 = { EncryptionManager }; |
|
|
|