2024-03-05 13:11:23 +00:00

133 lines
3.0 KiB
JavaScript

import crypto from "crypto"
export default class SecureEntry {
constructor(model, params = {}) {
this.params = params
if (!model) {
throw new Error("Missing model")
}
this.model = model
}
static get encrytionAlgorithm() {
return "aes-256-cbc"
}
async set(key, value, {
keyName = "key",
valueName = "value",
}) {
if (!keyName) {
throw new Error("Missing keyName")
}
if (!valueName) {
throw new Error("Missing valueName")
}
if (!key) {
throw new Error("Missing key")
}
if (!value) {
throw new Error("Missing value")
}
let entry = await this.model.findOne({
[keyName]: key,
[valueName]: value,
}).catch(() => null)
const encryptionKey = Buffer.from(process.env.SYNC_ENCRIPT_SECRET, "hex")
const iv = crypto.randomBytes(16)
const cipher = crypto.createCipheriv(SecureEntry.encrytionAlgorithm, encryptionKey, iv)
let encryptedData
try {
encryptedData = cipher.update(value)
}
catch (error) {
console.error(error)
}
encryptedData = Buffer.concat([encryptedData, cipher.final()])
value = iv.toString("hex") + ":" + encryptedData.toString("hex")
if (entry) {
entry[valueName] = value
await entry.save()
return entry
}
entry = new this.model({
[keyName]: key,
[valueName]: value,
})
await entry.save()
return entry
}
async get(key, value, {
keyName = "key",
valueName = "value",
}) {
if (!keyName) {
throw new Error("Missing keyName")
}
if (!key) {
throw new Error("Missing key")
}
const searchQuery = {
[keyName]: key,
}
if (value) {
searchQuery[valueName] = value
}
const entry = await this.model.findOne(searchQuery).catch(() => null)
if (!entry || !entry[valueName]) {
return null
}
const encryptionKey = Buffer.from(process.env.SYNC_ENCRIPT_SECRET, "hex")
const iv = Buffer.from(entry[valueName].split(":")[0], "hex")
const encryptedText = Buffer.from(entry[valueName].split(":")[1], "hex")
const decipher = crypto.createDecipheriv(SecureEntry.encrytionAlgorithm, encryptionKey, iv)
let decrypted = decipher.update(encryptedText)
decrypted = Buffer.concat([decrypted, decipher.final()])
return decrypted.toString()
}
async deleteByID(_id) {
if (!_id) {
throw new Error("Missing _id")
}
const entry = await this.model.findById(_id).catch(() => null)
if (!entry) {
return null
}
await entry.delete()
return entry
}
}