Some type updates and an improvement to encryption to allow selecting the secret from an option list.
This commit is contained in:
parent
5e68a4d814
commit
c645a9bc21
|
@ -37,6 +37,7 @@ const environment = {
|
|||
},
|
||||
JS_BCRYPT: process.env.JS_BCRYPT,
|
||||
JWT_SECRET: process.env.JWT_SECRET,
|
||||
ENCRYPTION_KEY: process.env.ENCRYPTION_KEY,
|
||||
COUCH_DB_URL: process.env.COUCH_DB_URL || "http://localhost:4005",
|
||||
COUCH_DB_USERNAME: process.env.COUCH_DB_USER,
|
||||
COUCH_DB_PASSWORD: process.env.COUCH_DB_PASSWORD,
|
||||
|
|
|
@ -2,19 +2,45 @@ import crypto from "crypto"
|
|||
import env from "../environment"
|
||||
|
||||
const ALGO = "aes-256-ctr"
|
||||
const SECRET = env.JWT_SECRET
|
||||
const SEPARATOR = "-"
|
||||
const ITERATIONS = 10000
|
||||
const RANDOM_BYTES = 16
|
||||
const STRETCH_LENGTH = 32
|
||||
|
||||
export enum SecretOption {
|
||||
JWT = "jwt",
|
||||
ENCRYPTION = "encryption",
|
||||
}
|
||||
|
||||
function getSecret(secretOption: SecretOption): string {
|
||||
let secret, secretName
|
||||
switch (secretOption) {
|
||||
case SecretOption.ENCRYPTION:
|
||||
secret = env.ENCRYPTION_KEY
|
||||
secretName = "ENCRYPTION_KEY"
|
||||
break
|
||||
case SecretOption.JWT:
|
||||
default:
|
||||
secret = env.JWT_SECRET
|
||||
secretName = "JWT_SECRET"
|
||||
break
|
||||
}
|
||||
if (!secret) {
|
||||
throw new Error(`Secret "${secretName}" has not been set in environment.`)
|
||||
}
|
||||
return secret
|
||||
}
|
||||
|
||||
function stretchString(string: string, salt: Buffer) {
|
||||
return crypto.pbkdf2Sync(string, salt, ITERATIONS, STRETCH_LENGTH, "sha512")
|
||||
}
|
||||
|
||||
export function encrypt(input: string, secret: string | undefined = SECRET) {
|
||||
export function encrypt(
|
||||
input: string,
|
||||
secretOption: SecretOption = SecretOption.JWT
|
||||
) {
|
||||
const salt = crypto.randomBytes(RANDOM_BYTES)
|
||||
const stretched = stretchString(secret!, salt)
|
||||
const stretched = stretchString(getSecret(secretOption), salt)
|
||||
const cipher = crypto.createCipheriv(ALGO, stretched, salt)
|
||||
const base = cipher.update(input)
|
||||
const final = cipher.final()
|
||||
|
@ -22,10 +48,13 @@ export function encrypt(input: string, secret: string | undefined = SECRET) {
|
|||
return `${salt.toString("hex")}${SEPARATOR}${encrypted}`
|
||||
}
|
||||
|
||||
export function decrypt(input: string, secret: string | undefined = SECRET) {
|
||||
export function decrypt(
|
||||
input: string,
|
||||
secretOption: SecretOption = SecretOption.JWT
|
||||
) {
|
||||
const [salt, encrypted] = input.split(SEPARATOR)
|
||||
const saltBuffer = Buffer.from(salt, "hex")
|
||||
const stretched = stretchString(secret!, saltBuffer)
|
||||
const stretched = stretchString(getSecret(secretOption), saltBuffer)
|
||||
const decipher = crypto.createDecipheriv(ALGO, stretched, saltBuffer)
|
||||
const base = decipher.update(Buffer.from(encrypted, "hex"))
|
||||
const final = decipher.final()
|
||||
|
|
|
@ -14,3 +14,7 @@ export type EnvironmentVariablesDecrypted = Record<
|
|||
string,
|
||||
EnvironmentVariableValue
|
||||
>
|
||||
|
||||
export interface EnvironmentVariablesDocDecrypted extends Document {
|
||||
variables: EnvironmentVariablesDecrypted
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue