Detekce manipulace v archivech dokumentů: jak fungují hašové řetězce
Pouhým pohledem na dokument nelze ověřit, zda s ním nebylo manipulováno. Upravené PDF vypadá identicky s originálem. Nahrazený soubor má stejný název. Tiše upravený záznam auditního protokolu nezanechá žádnou viditelnou stopu.
Detekce manipulace vyžaduje mechanismus, který způsobí, že úprava zanechá detekovatelný artefakt, ideálně takový, který může ověřit někdo, kdo nebyl přítomen při původním vzniku. Hašové řetězce jsou jedním ze základních mechanismů, které toho dosahují.
Co dělá kryptografický haš
Kryptografická hašovací funkce přijme vstup libovolné délky a vyprodukuje výstup pevné délky (digest) se dvěma klíčovými vlastnostmi:
- Determinismus: stejný vstup vždy produkuje stejný výstup
- Lavinový efekt: jakákoli změna vstupu, i jediný bit, produkuje zcela odlišný výstup
SHA-256 produkuje 256bitový (32bajtový) digest. Pro jakýkoli praktický vstup je výpočetně neproveditelné:
- Najít dva různé vstupy produkující stejný výstup (odolnost vůči kolizím)
- Rekonstruovat vstup z výstupu (odolnost vůči vzoru)
- Vyprodukovat konkrétní výstup bez znalosti vstupu (odolnost vůči druhému vzoru)
Tyto vlastnosti znamenají, že haš SHA-256 je spolehlivým otiskem dokumentu. Pokud haš odpovídá, dokument je identický s tím, co bylo hašováno. Pokud haš neodpovídá, něco se změnilo.
var hash = SHA256.HashData(File.ReadAllBytes("invoice.pdf"));
Console.WriteLine(Convert.ToHexString(hash));
// A3F8C2...1B7D (64 hex chars, always the same for this file, always different if file changes)
Proč jediný haš nestačí
Hašování dokumentu vám dává otisk v jednom okamžiku. Kdo ale tento otisk uchovává a co brání tomu, aby někdo nahradil jak dokument, tak uložený haš?
Pokud haš ukládáte ve stejném systému jako dokument a vy tento systém kontrolujete, odhodlaný útočník (nebo interní aktér zakrývající stopy) může nahradit oboje. Haš stále odpovídá novému dokumentu. Manipulace je nezjistitelná.
Proto detekce manipulace vyžaduje externí ukotvení: haš uložený někde, kde ho správce nemůže jednostranně upravit. RFC 3161 časové razítko je standardním mechanismem: vloží haš dokumentu do tokenu podepsaného třetí stranou (TSA). Správce nemůže token pozměnit bez soukromého klíče TSA.
Co přidává hašový řetězec
Hašový řetězec rozšiřuje tento princip na sekvenci událostí. Místo hašování pouze dokumentu hašujete každý záznam auditu a zahrnete haš předchozího záznamu do aktuálního.
Hash(Entry N) = SHA256( EventData(N) + Hash(Entry N-1) )
Tím vzniká řetězec, kde každý záznam potvrzuje všechny předchozí záznamy. Pokud změníte Entry 3 v řetězci 10 záznamů, Hash(Entry 3) se změní. Protože Entry 4 obsahuje Hash(Entry 3), Hash(Entry 4) se změní. A tak dál až k Entry 10.
Minulý záznam nelze tiše upravit. Řetězec neproběhne validací.
Zde je minimální implementace:
public sealed record AuditEntry(
string EventType,
string Actor,
DateTimeOffset Timestamp,
string DocumentHash,
string PreviousEntryHash)
{
public string ComputeHash()
{
var raw = $"{EventType}|{Actor}|{Timestamp:O}|{DocumentHash}|{PreviousEntryHash}";
return Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(raw)));
}
}
public static string AppendEntry(IList<AuditEntry> chain, string eventType,
string actor, byte[] documentBytes)
{
var previousHash = chain.Count == 0
? new string('0', 64)
: chain[^1].ComputeHash();
var docHash = Convert.ToHexString(SHA256.HashData(documentBytes));
var entry = new AuditEntry(eventType, actor, DateTimeOffset.UtcNow, docHash, previousHash);
chain.Add(entry);
return entry.ComputeHash();
}
public static bool VerifyChain(IList<AuditEntry> chain)
{
var expectedPrevious = new string('0', 64);
foreach (var entry in chain)
{
if (entry.PreviousEntryHash != expectedPrevious) return false;
expectedPrevious = entry.ComputeHash();
}
return true;
}
Ověření má složitost O(n) a nevyžaduje žádná externí volání. Kdokoli s řetězcem může spustit VerifyChain a potvrdit, že žádný záznam nebyl upraven.
Ukotvení řetězce časovým razítkem
Ověřený hašový řetězec prokazuje interní konzistenci: žádný záznam nebyl upraven po sestavení řetězce. Ale neprokazuje, kdy byl řetězec sestaven.
Pokud dnes sestavíte podvodný řetězec a tvrdíte, že reprezentuje události z před tří let, řetězec samotný se validuje správně. Hašový řetězec nemá hodiny.
Zde RFC 3161 časová razítka ukotvují řetězec k reálnému času. V klíčových bodech řetězce (minimálně: při finalizaci řetězce; ideálně při každé významné události) si vyžádejte razítko od kvalifikované TSA. TSA vloží haš aktuálního záznamu do podepsaného tokenu s důvěryhodným časovým razítkem.
Nyní má řetězec externí ukotvení. Řetězec nemůžete antedatovat za nejstarší razítko, protože token TSA prokazuje, že haš existoval v daném okamžiku, a hodiny TSA jsou autoritativní.
// After appending an entry, request a timestamp for the entry hash
var entryHash = AppendEntry(chain, "created", "api:tenant-1", documentBytes);
var entryHashBytes = Convert.FromHexString(entryHash);
var timestampToken = await RequestTimestampAsync(entryHashBytes, tsaUrl);
// Store the token alongside the chain entry
chain[^1] = chain[^1] with { TimestampToken = timestampToken };
Auditor ověřující řetězec může:
- Ověřit interní konzistenci hašového řetězce (žádné úpravy)
- Ověřit každý token razítka oproti veřejnému certifikátu TSA (žádné antedatování)
- Ověřit haš dokumentu v každém záznamu oproti aktuálnímu dokumentu (žádná záměna)
Hašové řetězce vs. jiné mechanismy integrity
Protokoly s možností pouze přidávání (např. databázové tabulky bez DELETE): Zabraňují smazání pomocí řízení přístupu, ale jsou jen tak důvěryhodné, jako je systém řízení přístupu. Správce databáze je může obejít. Hašové řetězce jsou vynuceny matematicky, nikoli politikou.
Digitální podpisy na jednotlivých dokumentech: Podpis prokazuje, že dokument byl podepsán konkrétním klíčem v čase podpisu. Nezaznamenává, co se s dokumentem dělo poté. Řetězec kontroly vyžaduje zaznamenání událostí po podpisu (přenos, konverze, archivace), nejen okamžiku podpisu.
Blockchain: Jako základní primitivum používá hašové řetězce, ale přidává distribuovaný konsenzus, který brání jakékoli straně přepisovat historii. Pro archivy dokumentů poskytuje lokální hašový řetězec ukotvený externími RFC 3161 razítky stejnou záruku odolnosti vůči manipulaci bez složitosti distribuované sítě. Rozdíl je důležitý: nepotřebujete konsenzus mezi cizími stranami, abyste prokázali, že dokument nebyl upraven; potřebujete externí ukotvení, které nekontrolujete.
WORM úložiště (Write Once Read Many): Zabraňuje úpravám na úrovni úložiště. Médium fyzicky nemůže být přepsáno. To je doplněk k hašovým řetězcům, nikoli náhrada. WORM prokazuje, že uložené bity se nezměnily. Hašový řetězec prokazuje, jaká sekvence událostí tyto bity vytvořila. Oba dohromady poskytují silnější záruky než každý zvlášť.
Jak vypadá ověření v praxi
Kompletní ověřovací workflow pro dokument v archivu s hašovým řetězcem:
- Načtěte dokument a auditní stopu z archivu
- Vypočítejte SHA-256 dokumentu; potvrďte, že odpovídá
documentHashv posledním záznamu řetězce - Procházejte řetězec zpětně, přepočítávejte každý
entryHasha potvrďte, že odpovídápreviousEntryHashv dalším záznamu - U každého záznamu s tokenem razítka ověřte token oproti certifikátu TSA a potvrďte, že haš v tokenu odpovídá vypočítanému
entryHash - Potvrďte, že haš dokumentu z kroku 2 odpovídá hašu dokumentu v nejstarším záznamu pokrývajícím finální podobu dokumentu
Pokud všech pět kroků projde, dokument je ověřen jako nezměněný od svého vzniku, auditní stopa přesně zaznamenává každý zpracovatelský krok a razítka poskytují externě ověřitelné časové ukotvení.
Toto ověření vyžaduje: dokument, auditní stopu, tokeny razítek a veřejné certifikáty TSA. Bez přístupu k síti. Bez závislosti na provozuschopnosti systémů správce. Důkaz je soběstačný.
Detekce manipulace jako infrastruktura
Většina organizací hašové řetězce neimplementuje, protože se zdají jako pokročilá funkce. Nejsou. SHA-256 je dostupný v každém moderním runtime. Sestavení řetězce je otázka několika desítek řádků kódu. Výhodou je, že můžete prokázat integritu dokumentu skeptické třetí straně, aniž byste se spoléhali na její důvěru vůči vaší organizaci.
Pro regulovaná odvětví (finance, zdravotnictví, pojišťovnictví, veřejný sektor) tento důkaz není volitelný. Pro jakoukoli organizaci, která chce předkládat digitální dokumenty jako důkazy ve sporu, je to základní požadavek.
SealDoc implementuje auditní stopy s hašovými řetězci pro každý dokument ve svém pipeline. Řetězec je exportován v balíčku právních důkazů a je ověřitelný offline. Pro organizace, které potřebují budovat vlastní důkazní infrastrukturu, vystavuje SealDoc API auditní stopu a tokeny razítek jako strukturovaná data, která lze začlenit do vlastních ověřovacích workflows.