Fuzzy hashing (TLSH)

Elke hash op de pagina Hashing & berichtauthenticatie is zo gebouwd dat een enkel gewijzigd bit een volledig ongerelateerde digest oplevert. TLSH (Trend Micro Locality Sensitive Hash) is juist gebouwd om het tegenovergestelde te doen: gelijkaardige invoer levert gelijkaardige digests op, en sgcTLSH_Diff scoort hoe ver twee digests uit elkaar liggen. Het beantwoordt "hoe gelijk zijn deze twee bestanden" in plaats van "zijn deze twee bestanden identiek", wat het nuttig maakt voor clustering en de detectie van bijna-duplicaten, de triage van malwarefamilies, en het vinden van documenten die zijn gekopieerd en licht bewerkt.

TLSH is geen beveiligingshash. Gebruik ze niet voor integriteit of authenticatie.

Ze is niet botsingsbestendig, en een aanvaller die de invoer beheerst, kan de digest opzettelijk sturen. Elke functie bevindt zich in sgcCrypto_TLSH.

Een digest berekenen

De invoer moet ten minste 50 bytes zijn (cTLSH_MinDataLength) en gevarieerd genoeg om meer dan de helft van de interne buckets te vullen; een digest is 72 tekens (cTLSH_DigestLength), beginnend met het versievoorvoegsel T1. Een invoer die te kort of te uniform is (bijvoorbeeld een lange reeks van één herhaalde byte) heeft niet genoeg signaal om te karakteriseren, en de onderstaande functies geven een lege string terug in plaats van een betekenisloze digest.


function sgcTLSH(const aData: TBytes): string;
function sgcTLSH_Stream(aStream: TStream): string;
function sgcTLSH_IsValid(const aDigest: string): Boolean;

var
  vDigest: string;
begin
  vDigest := sgcTLSH(oFileBytes);
  if vDigest = '' then
    { too short or too uniform to characterize }
  else
    { vDigest is a 72-character T1... string };
end;

Een groot bestand hoeft niet in één keer in het geheugen te worden gehouden; voer het in blokken door de streaming-interface, of geef een stream rechtstreeks door aan sgcTLSH_Stream:


procedure sgcTLSH_Init(var aContext: TsgcTLSHContext);
procedure sgcTLSH_Update(var aContext: TsgcTLSHContext; const aData: TBytes);
function sgcTLSH_Final(var aContext: TsgcTLSHContext): string;

Twee digests vergelijken


function sgcTLSH_Diff(const aLeft, aRight: string; aLengthDiff: Boolean = True): Integer;

Nul (cTLSH_IdenticalDiff) betekent dezelfde digest; de score groeit naarmate de twee invoerwaarden meer verschillen, zonder vaste bovengrens. Er is geen universele drempel, kalibreer deze aan de hand van uw eigen corpus, maar als vertrekpunt duidt een afstand onder ruwweg 30 gewoonlijk op dezelfde of vrijwel dezelfde inhoud, terwijl hogere waarden op een geleidelijk zwakker verband duiden. aLengthDiff verwerkt het verschil in invoerlengte in de score; schakel dit uit bij het vergelijken van inhoud die legitiem is opgevuld of afgekapt, zoals logbestanden die op verschillende groottes zijn geroteerd. De functie geeft -1 terug als een van beide digests misvormd is.