2022-11-24 19:48:51 +01:00
|
|
|
import crypto from "crypto"
|
|
|
|
import env from "../environment"
|
2022-02-14 19:32:09 +01:00
|
|
|
|
|
|
|
const ALGO = "aes-256-ctr"
|
2022-02-14 22:37:40 +01:00
|
|
|
const SEPARATOR = "-"
|
|
|
|
const ITERATIONS = 10000
|
|
|
|
const RANDOM_BYTES = 16
|
|
|
|
const STRETCH_LENGTH = 32
|
|
|
|
|
2023-01-16 19:15:43 +01:00
|
|
|
export enum SecretOption {
|
2023-03-13 16:02:59 +01:00
|
|
|
API = "api",
|
2023-01-16 19:15:43 +01:00
|
|
|
ENCRYPTION = "encryption",
|
|
|
|
}
|
|
|
|
|
|
|
|
function getSecret(secretOption: SecretOption): string {
|
|
|
|
let secret, secretName
|
|
|
|
switch (secretOption) {
|
|
|
|
case SecretOption.ENCRYPTION:
|
|
|
|
secret = env.ENCRYPTION_KEY
|
|
|
|
secretName = "ENCRYPTION_KEY"
|
|
|
|
break
|
2023-03-13 16:02:59 +01:00
|
|
|
case SecretOption.API:
|
2023-01-16 19:15:43 +01:00
|
|
|
default:
|
2023-03-13 16:02:59 +01:00
|
|
|
secret = env.API_ENCRYPTION_KEY
|
|
|
|
secretName = "API_ENCRYPTION_KEY"
|
2023-01-16 19:15:43 +01:00
|
|
|
break
|
|
|
|
}
|
|
|
|
if (!secret) {
|
|
|
|
throw new Error(`Secret "${secretName}" has not been set in environment.`)
|
|
|
|
}
|
|
|
|
return secret
|
|
|
|
}
|
|
|
|
|
2022-11-24 19:48:51 +01:00
|
|
|
function stretchString(string: string, salt: Buffer) {
|
2022-02-14 22:37:40 +01:00
|
|
|
return crypto.pbkdf2Sync(string, salt, ITERATIONS, STRETCH_LENGTH, "sha512")
|
|
|
|
}
|
2022-02-14 19:32:09 +01:00
|
|
|
|
2023-01-16 19:15:43 +01:00
|
|
|
export function encrypt(
|
|
|
|
input: string,
|
2023-03-13 16:02:59 +01:00
|
|
|
secretOption: SecretOption = SecretOption.API
|
2023-01-16 19:15:43 +01:00
|
|
|
) {
|
2022-02-14 22:37:40 +01:00
|
|
|
const salt = crypto.randomBytes(RANDOM_BYTES)
|
2023-01-16 19:15:43 +01:00
|
|
|
const stretched = stretchString(getSecret(secretOption), salt)
|
2022-02-14 22:37:40 +01:00
|
|
|
const cipher = crypto.createCipheriv(ALGO, stretched, salt)
|
2022-02-14 19:32:09 +01:00
|
|
|
const base = cipher.update(input)
|
|
|
|
const final = cipher.final()
|
|
|
|
const encrypted = Buffer.concat([base, final]).toString("hex")
|
2022-02-14 22:37:40 +01:00
|
|
|
return `${salt.toString("hex")}${SEPARATOR}${encrypted}`
|
2022-02-14 19:32:09 +01:00
|
|
|
}
|
|
|
|
|
2023-01-16 19:15:43 +01:00
|
|
|
export function decrypt(
|
|
|
|
input: string,
|
2023-03-13 16:02:59 +01:00
|
|
|
secretOption: SecretOption = SecretOption.API
|
2023-01-16 19:15:43 +01:00
|
|
|
) {
|
2022-02-14 22:37:40 +01:00
|
|
|
const [salt, encrypted] = input.split(SEPARATOR)
|
|
|
|
const saltBuffer = Buffer.from(salt, "hex")
|
2023-01-16 19:15:43 +01:00
|
|
|
const stretched = stretchString(getSecret(secretOption), saltBuffer)
|
2022-02-14 22:37:40 +01:00
|
|
|
const decipher = crypto.createDecipheriv(ALGO, stretched, saltBuffer)
|
2022-02-14 19:32:09 +01:00
|
|
|
const base = decipher.update(Buffer.from(encrypted, "hex"))
|
|
|
|
const final = decipher.final()
|
|
|
|
return Buffer.concat([base, final]).toString()
|
|
|
|
}
|