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.