Considere que você possui uma função de hash que pega cadeias de comprimento e retorna cadeias de comprimento e tem a propriedade agradável de que é resistente a colisões , ou seja, é difícil encontrar duas cadeias diferentes com o mesmo hash .
Agora você deseja criar uma nova função de hash que pega cadeias de comprimento arbitrário e as mapeia para cadeias de comprimento , enquanto ainda é resistente a colisões.
Para sua sorte, já em 1979 foi publicado um método agora conhecido como a construção Merkle – Damgård que alcança exatamente isso.
A tarefa desse desafio será implementar esse algoritmo; portanto, primeiro examinaremos uma descrição formal da construção de Merkle – Damgård, antes de seguir um exemplo passo a passo que deve mostrar que a abordagem é mais simples do que pode aparecer a princípio.
Dado um número inteiro , uma função de hash conforme descrito acima e uma sequência de entrada de comprimento arbitrário, a nova função de hash faz o seguinte:
- Defina , o comprimento de e divida em pedaços de comprimento , preenchendo o último pedaço com zeros à direita, se necessário. Isso produz muitos pedaços rotulados como.
- Adicione um pedaço inicial e final e , em que é uma string que consiste em zeros é em binário, preenchido com zeros à esquerda no comprimento .
- Agora, iterativamente, aplique ao bloco atual anexado ao resultado anterior : , em que . (Esta etapa pode ficar mais clara depois de analisar o exemplo abaixo.)
- A saída de é o resultado final .
A tarefa
Escreva um programa ou função que tenha como entrada um número inteiro positivo , uma função de hash como caixa preta e uma string não vazia e retorne o mesmo resultado que nas mesmas entradas.
Isso é código-golfe , então a resposta mais curta em cada idioma vence.
Exemplo
Digamos , então nossa função hash dada pega cadeias de comprimento 10 e retorna cadeias de comprimento 5.
- Dada a entrada de , obtemos os seguintes blocos: , , e . Observe que precisava ser preenchido com o comprimento 5 com um zero à direita.
- é apenas uma sequência de cinco zeros é cinco em binário ( ), preenchido com dois zeros à esquerda.
- Agora os pedaços são combinados com :
- é a nossa saída.
Vamos dar uma olhada na aparência dessa saída, dependendo de algumas opções 1 para :
- Se , ou seja, apenas retorna cada segundo caractere, obtemos:
Portanto, precisa ser a saída se esse for fornecido como função de caixa preta. - Se simplesmente retornar os 5 primeiros caracteres de sua entrada, a saída de será . Da mesma forma, se retornar os últimos 5 caracteres, a saída será .
- Se multiplicar os códigos de caracteres de sua entrada e retornar os cinco primeiros dígitos desse número, por exemplo, , então .
1 Por simplicidade, os não são realmente resistentes a colisões, embora isso não importe para testar sua submissão.
omgPzzles0
. Exemplo de entrada bem escolhido!