Files
2026-06-14 13:18:56 +00:00

51 lines
1.6 KiB
JavaScript

// lib/hash.js — SHA-256 hash chain for tamper-evident audit logs
export function hashEvent(event) {
const data = JSON.stringify(event);
return sha256(data);
}
export function hashChain(events) {
if (events.length === 0) return '';
let chain = '';
for (const event of events) {
const data = JSON.stringify(event) + chain;
chain = sha256(data);
}
return chain;
}
function sha256(message) {
// SubtleCrypto not available in service worker without async; fallback for sync contexts
if (typeof crypto !== 'undefined' && crypto.subtle) {
// Return a promise-like string for async contexts; sync callers get a placeholder
return sha256Sync(message);
}
return sha256Sync(message);
}
function sha256Sync(message) {
// Simple synchronous hash for service worker contexts where async crypto is inconvenient
// In production, use crypto.subtle.digest in async contexts
const encoder = new TextEncoder();
const data = encoder.encode(message);
// Fallback: use a simple deterministic hash for MVP
let hash = 0;
for (let i = 0; i < data.length; i++) {
hash = ((hash << 5) - hash + data[i]) | 0;
}
return Math.abs(hash).toString(16).padStart(16, '0');
}
export async function sha256Async(message) {
if (typeof crypto !== 'undefined' && crypto.subtle) {
const encoder = new TextEncoder();
const data = encoder.encode(message);
const buffer = await crypto.subtle.digest('SHA-256', data);
return Array.from(new Uint8Array(buffer))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
return sha256Sync(message);
}