61 lines
1.6 KiB
TypeScript
61 lines
1.6 KiB
TypeScript
import { createCipheriv, createDecipheriv, createHmac, randomBytes } from "crypto";
|
|
|
|
function getEncryptionKey() {
|
|
const rawKey = process.env.CPF_ENC_KEY;
|
|
|
|
if (!rawKey) {
|
|
throw new Error("CPF_ENC_KEY nao configurada.");
|
|
}
|
|
|
|
const key = Buffer.from(rawKey, "base64");
|
|
|
|
if (key.length !== 32) {
|
|
throw new Error("CPF_ENC_KEY deve ter 32 bytes em base64.");
|
|
}
|
|
|
|
return key;
|
|
}
|
|
|
|
function getHashKey() {
|
|
const key = process.env.CPF_HASH_KEY;
|
|
|
|
if (!key) {
|
|
throw new Error("CPF_HASH_KEY nao configurada.");
|
|
}
|
|
|
|
return key;
|
|
}
|
|
|
|
export function onlyDigits(value: string) {
|
|
return value.replace(/\D/g, "");
|
|
}
|
|
|
|
export function encryptCpf(cpf: string) {
|
|
const iv = randomBytes(12);
|
|
const cipher = createCipheriv("aes-256-gcm", getEncryptionKey(), iv);
|
|
const encrypted = Buffer.concat([cipher.update(onlyDigits(cpf), "utf8"), cipher.final()]);
|
|
const tag = cipher.getAuthTag();
|
|
|
|
return `${iv.toString("base64")}.${tag.toString("base64")}.${encrypted.toString("base64")}`;
|
|
}
|
|
|
|
export function decryptCpf(payload: string) {
|
|
const [ivValue, tagValue, encryptedValue] = payload.split(".");
|
|
|
|
if (!ivValue || !tagValue || !encryptedValue) {
|
|
throw new Error("CPF cifrado invalido.");
|
|
}
|
|
|
|
const decipher = createDecipheriv("aes-256-gcm", getEncryptionKey(), Buffer.from(ivValue, "base64"));
|
|
decipher.setAuthTag(Buffer.from(tagValue, "base64"));
|
|
|
|
return Buffer.concat([
|
|
decipher.update(Buffer.from(encryptedValue, "base64")),
|
|
decipher.final()
|
|
]).toString("utf8");
|
|
}
|
|
|
|
export function hashCpf(cpf: string) {
|
|
return createHmac("sha256", getHashKey()).update(onlyDigits(cpf)).digest("hex");
|
|
}
|