Hachage flou (TLSH)

Chaque hachage de la page Hachage & authentification des messages est conçu de sorte qu'un seul bit modifié produise une empreinte totalement différente. TLSH (Trend Micro Locality Sensitive Hash) est conçu pour faire l'inverse : des entrées similaires produisent des empreintes similaires, et sgcTLSH_Diff évalue à quel point deux empreintes sont éloignées. Il répond à la question « à quel point ces deux fichiers se ressemblent-ils » plutôt qu'« est-ce que ces deux fichiers sont identiques », ce qui le rend utile pour le regroupement et la détection de quasi-doublons, le tri par famille de malwares, et la recherche de documents copiés et légèrement modifiés.

TLSH n'est pas un hachage de sécurité. Ne l'utilisez pas pour l'intégrité ou l'authentification.

Il n'est pas résistant aux collisions, et un attaquant qui contrôle l'entrée peut délibérément orienter l'empreinte. Chaque fonction se trouve dans sgcCrypto_TLSH.

Calculer une empreinte

L'entrée doit faire au moins 50 octets (cTLSH_MinDataLength) et être suffisamment variée pour remplir plus de la moitié des compartiments internes ; une empreinte fait 72 caractères (cTLSH_DigestLength), commençant par le préfixe de version T1. Une entrée trop courte ou trop uniforme (une longue série d'un même octet répété, par exemple) n'a pas assez de signal pour être caractérisée, et les fonctions ci-dessous renvoient une chaîne vide plutôt qu'une empreinte dénuée de sens.


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;

Un fichier volumineux n'a pas besoin d'être chargé en mémoire d'un seul coup ; transmettez-le par blocs via l'interface de streaming, ou passez directement un flux à sgcTLSH_Stream :


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

Comparer deux empreintes


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

Zéro (cTLSH_IdenticalDiff) signifie la même empreinte ; le score augmente avec la différence entre les deux entrées, sans limite supérieure fixe. Il n'existe pas de seuil universel, calibrez-le sur votre propre corpus, mais à titre indicatif une distance inférieure à environ 30 indique généralement le même contenu ou un contenu quasiment identique, tandis que des valeurs plus élevées indiquent une relation progressivement plus faible. aLengthDiff intègre la différence de longueur des entrées dans le score ; désactivez-le lorsque vous comparez du contenu légitimement complété ou tronqué, comme des fichiers journaux qui ont été pivotés à des tailles différentes. La fonction renvoie -1 si l'une des deux empreintes est mal formée.