Hash Difuso (TLSH)

Cada hash de la página Hash y Autenticación de Mensajes está construido de modo que un solo bit cambiado produzca un resumen completamente distinto. TLSH (Trend Micro Locality Sensitive Hash) está construido para hacer justo lo contrario: entradas similares producen resúmenes similares, y sgcTLSH_Diff puntúa cuánto se alejan dos resúmenes entre sí. Responde a "cuánto se parecen estos dos archivos" en lugar de "son estos dos archivos idénticos", que es lo que lo hace útil para agrupamiento y detección de casi duplicados, triaje de familias de malware, y para encontrar documentos que fueron copiados y ligeramente editados.

 

TLSH no es un hash de seguridad. No lo use para integridad ni autenticación.

 

No es resistente a colisiones, y un atacante que controla la entrada puede dirigir deliberadamente el resumen. Cada función está en sgcCrypto_TLSH.

 

Calcular un resumen

 

La entrada debe tener al menos 50 bytes (cTLSH_MinDataLength) y ser lo bastante variada como para llenar más de la mitad de los cubos internos; un resumen tiene 72 caracteres (cTLSH_DigestLength), comenzando con el prefijo de versión T1. Una entrada demasiado corta o demasiado uniforme (una larga racha de un mismo byte repetido, por ejemplo) no tiene suficiente señal para caracterizarse, y las funciones siguientes devuelven una cadena vacía en lugar de un resumen sin sentido.

 


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 archivo grande no necesita mantenerse en memoria de una vez; páselo por la interfaz de streaming en bloques, o pase un stream directamente a sgcTLSH_Stream:

 


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

 

Comparar dos resúmenes

 


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

 

Cero (cTLSH_IdenticalDiff) significa el mismo resumen; la puntuación crece con lo distintas que sean las dos entradas, sin límite superior fijo. No hay un umbral universal, calíbrelo frente a su propio corpus, pero como punto de partida una distancia por debajo de aproximadamente 30 suele indicar el mismo contenido o casi el mismo, mientras que valores más altos indican progresivamente menos relación. aLengthDiff incorpora la diferencia de longitud de entrada a la puntuación; desactívelo al comparar contenido que está legítimamente rellenado o truncado, como archivos de registro que fueron rotados con distintos tamaños. La función devuelve -1 si alguno de los dos resúmenes está mal formado.