refactor: centralize configuration
This commit is contained in:
@@ -1,18 +1,10 @@
|
||||
import crypto from "node:crypto";
|
||||
|
||||
import {
|
||||
DEFAULT_AUTH_TAG_LENGTH,
|
||||
DEFAULT_BCRYPT_SALT_ROUNDS,
|
||||
DEFAULT_ENCRYPTION_ALGORITHM,
|
||||
DEFAULT_IV_LENGTH,
|
||||
} from "@basango/domain/constants";
|
||||
import { createEnvAccessor } from "@devscast/config";
|
||||
import { config } from "@basango/domain/config";
|
||||
import * as bcrypt from "bcrypt";
|
||||
|
||||
export const env = createEnvAccessor(["BASANGO_ENCRYPTION_KEY"] as const);
|
||||
|
||||
function getKey(): Buffer {
|
||||
const key = env("BASANGO_ENCRYPTION_KEY");
|
||||
const key = config.encryption.key;
|
||||
|
||||
if (Buffer.from(key, "hex").length !== 32) {
|
||||
throw new Error("BASANGO_ENCRYPTION_KEY must be a 64-character hex string (32 bytes).");
|
||||
@@ -20,6 +12,12 @@ function getKey(): Buffer {
|
||||
return Buffer.from(key, "hex");
|
||||
}
|
||||
|
||||
const getEncryptionSettings = () => ({
|
||||
algorithm: config.encryption.algorithm as crypto.CipherGCMTypes,
|
||||
authTagLength: config.encryption.authTagLength,
|
||||
ivLength: config.encryption.ivLength,
|
||||
});
|
||||
|
||||
/**
|
||||
* Encrypts a plaintext string using AES-256-GCM.
|
||||
* @param text The plaintext string to encrypt.
|
||||
@@ -27,8 +25,9 @@ function getKey(): Buffer {
|
||||
*/
|
||||
export function encrypt(text: string): string {
|
||||
const key = getKey();
|
||||
const iv = crypto.randomBytes(DEFAULT_IV_LENGTH);
|
||||
const cipher = crypto.createCipheriv(DEFAULT_ENCRYPTION_ALGORITHM, key, iv);
|
||||
const { algorithm, ivLength } = getEncryptionSettings();
|
||||
const iv = crypto.randomBytes(ivLength);
|
||||
const cipher = crypto.createCipheriv(algorithm, key, iv);
|
||||
|
||||
let encrypted = cipher.update(text, "utf8", "hex");
|
||||
encrypted += cipher.final("hex");
|
||||
@@ -50,17 +49,15 @@ export function encrypt(text: string): string {
|
||||
*/
|
||||
export function decrypt(encryptedPayload: string): string {
|
||||
const key = getKey();
|
||||
const { algorithm, authTagLength, ivLength } = getEncryptionSettings();
|
||||
const dataBuffer = Buffer.from(encryptedPayload, "base64");
|
||||
|
||||
// Extract IV, auth tag, and encrypted data
|
||||
const iv = dataBuffer.subarray(0, DEFAULT_IV_LENGTH);
|
||||
const authTag = dataBuffer.subarray(
|
||||
DEFAULT_IV_LENGTH,
|
||||
DEFAULT_IV_LENGTH + DEFAULT_AUTH_TAG_LENGTH,
|
||||
);
|
||||
const encryptedText = dataBuffer.subarray(DEFAULT_IV_LENGTH + DEFAULT_AUTH_TAG_LENGTH);
|
||||
const iv = dataBuffer.subarray(0, ivLength);
|
||||
const authTag = dataBuffer.subarray(ivLength, ivLength + authTagLength);
|
||||
const encryptedText = dataBuffer.subarray(ivLength + authTagLength);
|
||||
|
||||
const decipher = crypto.createDecipheriv(DEFAULT_ENCRYPTION_ALGORITHM, key, iv);
|
||||
const decipher = crypto.createDecipheriv(algorithm, key, iv);
|
||||
decipher.setAuthTag(authTag);
|
||||
|
||||
let decrypted = decipher.update(encryptedText.toString("hex"), "hex", "utf8");
|
||||
@@ -82,7 +79,8 @@ export function generateRandomBytes(size: number): string {
|
||||
}
|
||||
|
||||
export async function hashPassword(password: string): Promise<string> {
|
||||
return bcrypt.hash(password, DEFAULT_BCRYPT_SALT_ROUNDS);
|
||||
const rounds = config.encryption.bcryptSaltRounds;
|
||||
return bcrypt.hash(password, rounds);
|
||||
}
|
||||
|
||||
export async function verifyPassword(password: string, hashed: string): Promise<boolean> {
|
||||
|
||||
Reference in New Issue
Block a user