Todo hash da página Hashing & Autenticação de Mensagens é construído de forma que um único bit alterado produza um digest completamente diferente. O TLSH (Trend Micro Locality Sensitive Hash) é construído para fazer o oposto: entradas semelhantes produzem digests semelhantes, e o sgcTLSH_Diff mede o quão distantes dois digests estão. Ele responde "quão parecidos são estes dois arquivos" em vez de "estes dois arquivos são idênticos", o que é o que o torna útil para clustering e detecção de quase duplicados, triagem de famílias de malware, e para encontrar documentos que foram copiados e levemente editados.
O TLSH não é um hash de segurança. Não o utilize para integridade ou autenticação.
Ele não é resistente a colisões, e um atacante que controla a entrada pode direcionar deliberadamente o digest. Toda função está em sgcCrypto_TLSH.
Calculando um digest
A entrada precisa ter pelo menos 50 bytes (cTLSH_MinDataLength) e ser variada o suficiente para preencher mais da metade dos buckets internos; um digest tem 72 caracteres (cTLSH_DigestLength), começando com o prefixo de versão T1. Uma entrada curta demais ou uniforme demais (uma longa sequência de um mesmo byte repetido, por exemplo) não tem sinal suficiente para ser caracterizada, e as funções abaixo retornam uma string vazia em vez de um digest sem 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;
Um arquivo grande não precisa ser mantido inteiro na memória de uma só vez; alimente-o através da interface de streaming em blocos, ou passe um stream diretamente para sgcTLSH_Stream:
procedure sgcTLSH_Init(var aContext: TsgcTLSHContext);
procedure sgcTLSH_Update(var aContext: TsgcTLSHContext; const aData: TBytes);
function sgcTLSH_Final(var aContext: TsgcTLSHContext): string;
Comparando dois digests
function sgcTLSH_Diff(const aLeft, aRight: string; aLengthDiff: Boolean = True): Integer;
Zero (cTLSH_IdenticalDiff) significa o mesmo digest; a pontuação cresce conforme as duas entradas forem mais diferentes, sem limite superior fixo. Não existe um limiar universal, calibre-o com base no seu próprio corpus, mas como ponto de partida uma distância abaixo de aproximadamente 30 costuma indicar o mesmo conteúdo ou um conteúdo quase igual, enquanto valores mais altos indicam uma relação progressivamente menor. aLengthDiff incorpora a diferença no tamanho da entrada na pontuação; desative-o ao comparar conteúdo que é legitimamente preenchido ou truncado, como arquivos de log que foram rotacionados em tamanhos diferentes. A função retorna -1 se qualquer um dos digests estiver malformado.