You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

77 lines
2.5 KiB

11 months ago
  1. const crypto = require("crypto");
  2. // Differs from EncryptionManager in that is does not set or define the keys that will be used
  3. // to encrypt or read data and it must be told the key (as base64 string) explicitly that will be used and is provided to
  4. // the class on creation. This key should be the same `key` that is used by the EncryptionManager class.
  5. class EncryptionWorker {
  6. constructor(presetKeyBase64 = "") {
  7. this.key = Buffer.from(presetKeyBase64, "base64");
  8. this.algorithm = "aes-256-cbc";
  9. this.separator = ":";
  10. }
  11. log(text, ...args) {
  12. console.log(`\x1b[36m[EncryptionManager]\x1b[0m ${text}`, ...args);
  13. }
  14. /**
  15. * Give a chunk source, parse its payload query param and expand that object back into the URL
  16. * as additional query params
  17. * @param {string} chunkSource
  18. * @returns {URL} Javascript URL object with query params decrypted from payload query param.
  19. */
  20. expandPayload(chunkSource = "") {
  21. try {
  22. const url = new URL(chunkSource);
  23. if (!url.searchParams.has("payload")) return url;
  24. const decryptedPayload = this.decrypt(url.searchParams.get("payload"));
  25. const encodedParams = JSON.parse(decryptedPayload);
  26. url.searchParams.delete("payload"); // remove payload prop
  27. // Add all query params needed to replay as query params
  28. Object.entries(encodedParams).forEach(([key, value]) =>
  29. url.searchParams.append(key, value)
  30. );
  31. return url;
  32. } catch (e) {
  33. console.error(e);
  34. }
  35. return new URL(chunkSource);
  36. }
  37. encrypt(plainTextString = null) {
  38. try {
  39. if (!plainTextString)
  40. throw new Error("Empty string is not valid for this method.");
  41. const iv = crypto.randomBytes(16);
  42. const cipher = crypto.createCipheriv(this.algorithm, this.key, iv);
  43. const encrypted = cipher.update(plainTextString, "utf8", "hex");
  44. return [
  45. encrypted + cipher.final("hex"),
  46. Buffer.from(iv).toString("hex"),
  47. ].join(this.separator);
  48. } catch (e) {
  49. this.log(e);
  50. return null;
  51. }
  52. }
  53. decrypt(encryptedString) {
  54. try {
  55. const [encrypted, iv] = encryptedString.split(this.separator);
  56. if (!iv) throw new Error("IV not found");
  57. const decipher = crypto.createDecipheriv(
  58. this.algorithm,
  59. this.key,
  60. Buffer.from(iv, "hex")
  61. );
  62. return decipher.update(encrypted, "hex", "utf8") + decipher.final("utf8");
  63. } catch (e) {
  64. this.log(e);
  65. return null;
  66. }
  67. }
  68. }
  69. module.exports = { EncryptionWorker };