import { createHash, randomBytes } from 'crypto'; /** * Cryptographic utilities for privacy-preserving audit logging */ /** * Generate a deterministic hash for a user ID with an optional salt * This creates a one-way hash that can be used to obfuscate user IDs */ export function hashUserId(userId: string, salt?: string): string { const data = salt ? `${userId}:${salt}` : userId; return createHash('sha256').update(data).digest('hex'); } /** * Generate a cryptographically secure random salt */ export function generateSalt(): string { return randomBytes(32).toString('hex'); } /** * Create a PHI reference string in the format: hash.collection.field */ export function createPHIReference( hashedUserId: string, collection: string, field: string ): string { return `${hashedUserId}.${collection}.${field}`; } /** * Parse a PHI reference string into its components */ export function parsePHIReference(reference: string): { hashedUserId: string; collection: string; field: string; } | null { const parts = reference.split('.'); if (parts.length !== 3) { return null; } return { hashedUserId: parts[0], collection: parts[1], field: parts[2] }; } /** * Batch hash multiple values for efficiency */ export function batchHashUserIds( userIds: string[], salt?: string ): Map { const hashMap = new Map(); for (const userId of userIds) { hashMap.set(userId, hashUserId(userId, salt)); } return hashMap; }