feat: enhance employee and symbol management with new features, improved UI components, and backend schema updates
This commit is contained in:
132
packages/backend/convex/auth/utils.ts
Normal file
132
packages/backend/convex/auth/utils.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* Utilitários para autenticação e criptografia
|
||||
* Usando Web Crypto API para criptografia segura
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gera um hash seguro de senha usando PBKDF2
|
||||
*/
|
||||
export async function hashPassword(password: string): Promise<string> {
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(password);
|
||||
|
||||
// Gerar salt aleatório
|
||||
const salt = crypto.getRandomValues(new Uint8Array(16));
|
||||
|
||||
// Importar a senha como chave
|
||||
const keyMaterial = await crypto.subtle.importKey(
|
||||
"raw",
|
||||
data,
|
||||
"PBKDF2",
|
||||
false,
|
||||
["deriveBits"]
|
||||
);
|
||||
|
||||
// Derivar a chave usando PBKDF2
|
||||
const derivedBits = await crypto.subtle.deriveBits(
|
||||
{
|
||||
name: "PBKDF2",
|
||||
salt: salt,
|
||||
iterations: 100000,
|
||||
hash: "SHA-256",
|
||||
},
|
||||
keyMaterial,
|
||||
256
|
||||
);
|
||||
|
||||
// Combinar salt + hash
|
||||
const hashArray = new Uint8Array(derivedBits);
|
||||
const combined = new Uint8Array(salt.length + hashArray.length);
|
||||
combined.set(salt);
|
||||
combined.set(hashArray, salt.length);
|
||||
|
||||
// Converter para base64
|
||||
return btoa(String.fromCharCode(...combined));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifica se uma senha corresponde ao hash
|
||||
*/
|
||||
export async function verifyPassword(
|
||||
password: string,
|
||||
hash: string
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
// Decodificar o hash de base64
|
||||
const combined = Uint8Array.from(atob(hash), (c) => c.charCodeAt(0));
|
||||
|
||||
// Extrair salt e hash
|
||||
const salt = combined.slice(0, 16);
|
||||
const storedHash = combined.slice(16);
|
||||
|
||||
// Gerar hash da senha fornecida
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(password);
|
||||
|
||||
const keyMaterial = await crypto.subtle.importKey(
|
||||
"raw",
|
||||
data,
|
||||
"PBKDF2",
|
||||
false,
|
||||
["deriveBits"]
|
||||
);
|
||||
|
||||
const derivedBits = await crypto.subtle.deriveBits(
|
||||
{
|
||||
name: "PBKDF2",
|
||||
salt: salt,
|
||||
iterations: 100000,
|
||||
hash: "SHA-256",
|
||||
},
|
||||
keyMaterial,
|
||||
256
|
||||
);
|
||||
|
||||
const newHash = new Uint8Array(derivedBits);
|
||||
|
||||
// Comparar os hashes
|
||||
if (newHash.length !== storedHash.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < newHash.length; i++) {
|
||||
if (newHash[i] !== storedHash[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Erro ao verificar senha:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gera um token aleatório seguro
|
||||
*/
|
||||
export function generateToken(): string {
|
||||
const array = new Uint8Array(32);
|
||||
crypto.getRandomValues(array);
|
||||
return btoa(String.fromCharCode(...array))
|
||||
.replace(/\+/g, "-")
|
||||
.replace(/\//g, "_")
|
||||
.replace(/=/g, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Valida formato de matrícula (apenas números)
|
||||
*/
|
||||
export function validarMatricula(matricula: string): boolean {
|
||||
return /^\d+$/.test(matricula) && matricula.length >= 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Valida formato de senha (alfanuméricos e símbolos)
|
||||
*/
|
||||
export function validarSenha(senha: string): boolean {
|
||||
// Mínimo 8 caracteres, pelo menos uma letra, um número e um símbolo
|
||||
const regex = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/;
|
||||
return regex.test(senha);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user