Existe uma forma de criptografia que pode ter uma string de qualquer comprimento e produzir um hash de menos de 10 caracteres? Desejo produzir IDs razoavelmente exclusivos, mas com base no conteúdo da mensagem, em vez de aleatoriamente.
Posso viver restringindo as mensagens a valores inteiros, no entanto, se cadeias de comprimento arbitrário forem impossíveis. No entanto, o hash não deve ser semelhante para dois inteiros consecutivos, nesse caso.
encryption
uniqueidentifier
rath3r
fonte
fonte
Respostas:
Você pode usar qualquer algoritmo de hash comumente disponível (por exemplo, SHA-1), que fornecerá um resultado um pouco mais longo do que o necessário. Simplesmente trunque o resultado no comprimento desejado, que pode ser bom o suficiente.
Por exemplo, em Python:
fonte
hash(a)
colide com,hash(b)
entãobase64(hash(a))
também colide combase64(hash(b))
.sha1
colide , mas esta é outra história). Se você tiver um hash de 10 caracteres, você obtém uma entropia maior se estiver codificado combase64
vsbase16
(ou hex). Quão mais alto? Combase16
você obtém 4 bits de informação por caractere,base64
este valor é 6 bits / char. No total, um hash "hex" de 10 caracteres terá 40 bits de entropia, enquanto um hash base64 de 60 bits. Então é um pouco mais resistente, desculpe se não fui super claro.Se você não precisa de um algoritmo que seja forte contra modificação intencional, encontrei um algoritmo chamado adler32 que produz resultados bastante curtos (~ 8 caracteres). Escolha na lista suspensa aqui para experimentar:
http://www.sha1-online.com/
fonte
Você precisa hash o conteúdo para fazer um resumo. Existem muitos hashes disponíveis, mas 10 caracteres é muito pequeno para o conjunto de resultados. Há muito tempo, as pessoas usavam CRC-32, que produz um hash de 33 bits (basicamente 4 caracteres mais um bit). Também existe o CRC-64 que produz um hash de 65 bits. MD5, que produz um hash de 128 bits (16 bytes / caracteres), é considerado quebrado para fins criptográficos porque duas mensagens podem ser encontradas com o mesmo hash. Não é preciso dizer que sempre que você criar um resumo de 16 bytes a partir de uma mensagem de comprimento arbitrário, acabará com duplicatas. Quanto mais curto for o resumo, maior será o risco de colisões.
No entanto, sua preocupação de que o hash não seja semelhante para duas mensagens consecutivas (inteiros ou não) deve ser verdadeira com todos os hashes. Mesmo uma única mudança de bit na mensagem original deve produzir um resumo resultante muito diferente.
Portanto, usar algo como CRC-64 (e base-64 para obter o resultado) deve levá-lo ao bairro que está procurando.
fonte
Apenas resumindo uma resposta que foi útil para mim (observando o comentário de @erasmospunk sobre o uso da codificação em base 64). Meu objetivo era ter uma pequena cadeia que foi principalmente único ...
Não sou nenhum especialista, então corrija se houver algum erro gritante (em Python novamente como a resposta aceita):
O
result
aqui está usando mais do que apenas caracteres hexadecimais (o que você obteria se os usassehash.hexdigest()
), então é menos provável que haja uma colisão (ou seja, deve ser mais seguro truncar do que um resumo hexadecimal).Nota: Usando UUID4 (aleatório). Consulte http://en.wikipedia.org/wiki/Universally_unique_identifier para os outros tipos.
fonte
Você poderia usar um algoritmo hash existente que produza algo curto, como MD5 (128 bits) ou SHA1 (160). Em seguida, você pode encurtar ainda mais por XORing seções do resumo com outras seções. Isso aumentará a chance de colisões, mas não tão ruim quanto simplesmente truncar o resumo.
Além disso, você pode incluir o comprimento dos dados originais como parte do resultado para torná-los mais exclusivos. Por exemplo, fazer o XOR da primeira metade de um resumo MD5 com a segunda metade resultaria em 64 bits. Adicione 32 bits para o comprimento dos dados (ou menos se você souber que o comprimento sempre caberá em menos bits). Isso resultaria em um resultado de 96 bits (12 bytes) que você poderia transformar em uma string hexadecimal de 24 caracteres. Como alternativa, você pode usar a codificação base 64 para torná-la ainda mais curta.
fonte
Se você precisar,
"sub-10-character hash"
pode usar o algoritmo Fletcher-32 que produz hash de 8 caracteres (32 bits), CRC-32 ou Adler-32 .CRC-32 é mais lento que Adler32 por um fator de 20% - 100%.
Fletcher-32 é ligeiramente mais confiável do que Adler-32. Ele tem um custo computacional menor do que a soma de verificação de Adler: comparação Fletcher vs Adler .
Um programa de amostra com algumas implementações do Fletcher é fornecido abaixo:
Resultado:
Concorda com os vetores de teste :
O Adler-32 tem um ponto fraco para mensagens curtas com poucas centenas de bytes, porque as somas de verificação dessas mensagens têm uma cobertura insuficiente dos 32 bits disponíveis. Verifique isto:
O algoritmo Adler32 não é complexo o suficiente para competir com somas de verificação comparáveis .
fonte
Basta executá-lo em um terminal (no MacOS ou Linux):
8 caracteres de comprimento.
fonte
Você pode usar a biblioteca hashlib para Python. Os shake_128 e shake_256 algoritmos fornecer hash de comprimento variável. Aqui estão alguns códigos de trabalho (Python3):
Observe que, com um parâmetro de comprimento x (5 no exemplo), a função retorna um valor hash de comprimento 2x .
fonte
Agora é 2019 e existem opções melhores. Ou seja, xxhash .
fonte
Eu precisava de algo semelhante a uma função simples de redução de string recentemente. Basicamente, o código se parecia com isto (código C / C ++ adiante):
Provavelmente tem mais colisões do que o desejado, mas não se destina ao uso como uma função hash criptográfica. Você pode tentar vários multiplicadores (ou seja, mudar o 37 para outro número primo) se houver muitas colisões. Um dos recursos interessantes desse trecho é que quando Src é menor que Dest, Dest termina com a string de entrada como está (0 * 37 + valor = valor). Se você quiser algo "legível" no final do processo, o Normalize ajustará os bytes transformados ao custo de aumentar as colisões.
Fonte:
https://github.com/cubiclesoft/cross-platform-cpp/blob/master/sync/sync_util.cpp
fonte
DestSize
maior do que 4 (32 bits) quando o próprio hash é tão ínfima? Se você quisesse a resistência à colisão fornecida por uma saída maior que um int, você usaria SHA.