Talvez eu simplesmente não esteja vendo, mas CRC32 parece desnecessariamente complicado ou insuficientemente explicado em qualquer lugar que pude encontrar na web.
Eu entendo que é o resto de uma divisão aritmética não baseada em carry do valor da mensagem, dividido pelo polinômio (gerador), mas a implementação real dele me escapa.
Eu li um guia indolor para algoritmos de detecção de erro CRC e devo dizer que não foi indolor. Ele repassa a teoria muito bem, mas o autor nunca chega a um simples "é isso". Ele diz quais são os parâmetros do algoritmo CRC32 padrão, mas se esquece de definir claramente como chegar a ele.
A parte que me pega é quando ele diz "é isso" e, em seguida, acrescenta: "ah, a propósito, pode ser revertido ou iniciado com diferentes condições iniciais" e não dá uma resposta clara de qual é o caminho final de calcular uma soma de verificação CRC32 dadas todas as mudanças que ele acabou de adicionar.
- Existe uma explicação mais simples de como o CRC32 é calculado?
Tentei codificar em C como a tabela é formada:
for (i = 0; i < 256; i++)
{
temp = i;
for (j = 0; j < 8; j++)
{
if (temp & 1)
{
temp >>= 1;
temp ^= 0xEDB88320;
}
else {temp >>= 1;}
}
testcrc[i] = temp;
}
mas isso parece gerar valores inconsistentes com valores que encontrei em outro lugar na Internet. Eu poderia usar os valores que encontrei online, mas quero entender como eles foram criados.
Qualquer ajuda para esclarecer esses números incrivelmente confusos seria muito apreciada.
0xEDB88320
também pode ser escrito msbit-first ( normal ) como0x04C11DB7
. Os valores da tabela que você encontrou em outro lugar foram gerados usando o mesmo polinômio CRC?Respostas:
O polinômio para CRC32 é:
Ou em hexadecimal e binário:
O termo mais alto (x 32 ) geralmente não é escrito explicitamente, então pode ser representado em hexadecimal
Sinta-se à vontade para contar os 1s e 0s, mas você descobrirá que eles correspondem ao polinômio, onde
1
é o bit 0 (ou o primeiro bit) ex
é o bit 1 (ou o segundo bit).Por que esse polinômio? Porque é necessário que haja um determinado polinômio padrão e o padrão foi definido pelo IEEE 802.3. Além disso, é extremamente difícil encontrar um polinômio que detecte erros de bits diferentes com eficácia.
Você pode pensar no CRC-32 como uma série de "Aritmética Binária sem Cargas" ou basicamente "XOR e operações de deslocamento". Isso é tecnicamente chamado de aritmética polinomial.
Para entender melhor, pense nesta multiplicação:
Se assumirmos que x é a base 2, obteremos:
Por quê? Como 3x ^ 3 é 11x ^ 11 (mas precisamos apenas de 1 ou 0 pré-dígito), transferimos:
Mas os matemáticos mudaram as regras para que seja o mod 2. Então, basicamente, qualquer mod 2 polinomial binário é apenas uma adição sem carry ou XORs. Portanto, nossa equação original se parece com:
Sei que isso é um ato de fé, mas está além da minha capacidade como programador de linha. Se você é um estudante de ciência da computação ou engenheiro, eu o desafio a decifrar isso. Todos se beneficiarão com esta análise.
Então, para trabalhar um exemplo completo:
Agora dividimos a Mensagem aumentada pelo Poli usando aritmética CRC. Esta é a mesma divisão de antes:
A divisão produz um quociente, que descartamos, e um resto, que é o checksum calculado. Isso encerra o cálculo. Normalmente, a soma de verificação é então anexada à mensagem e o resultado transmitido. Nesse caso, a transmissão seria: 11010110111110.
Use apenas um número de 32 bits como seu divisor e use todo o seu fluxo como seu dividendo. Jogue fora o quociente e guarde o restante. Pegue o restante no final de sua mensagem e você terá um CRC32.
Avaliação de cara comum:
(Observe que o fluxo deve ser divisível por 32 bits ou deve ser preenchido. Por exemplo, um fluxo ANSI de 8 bits teria que ser preenchido. Também no final do fluxo, a divisão é interrompida.)
fonte
x^6 + x^5 + x^4 + 3*x^3 + x^2 + x^1 + x^0 ... If we assume x is base 2 then we get: x^7 + x^3 + x^2 + x^1 + x^0
. Não é assim que a matemática funciona. Os coeficientes para o polinômio são mod (2) ou GF (2), os x são deixados sozinhos, resultando em x ^ 6 + x ^ 5 + x ^ 4 + x ^ 3 + x ^ 2 + x ^ 1 + x ^ 0 (desde 3 mod (2) = 1).Tack the remainder on the end of your message
- tecnicamente, o restante é subtraído dos bits 0 que foram acrescentados à mensagem, mas como este é o mod (2) math, tanto a adição quanto a subtração são iguais a XOR, e os bits zero XOR'ed com o restante são os mesmos como o restante.Why did you append four 0s though?
- os algoritmos de software para calcular o crc acrescentam efetivamente os 0s, mesmo que não seja aparente. Se estiver mostrando o cálculo CRC usando divisão de mão longa, então 0s precisam ser anexados para que o exemplo de divisão apareça corretamente.Para IEEE802.3, CRC-32. Pense na mensagem inteira como um fluxo de bits serial, acrescente 32 zeros ao final da mensagem. A seguir, você DEVE inverter os bits de CADA byte da mensagem e fazer um complemento de 1 para os primeiros 32 bits. Agora divida pelo polinômio CRC-32, 0x104C11DB7. Finalmente, você deve complementar os 1's do restante de 32 bits dessa divisão, invertendo cada um dos 4 bytes do restante. Isso se torna o CRC de 32 bits que é anexado ao final da mensagem.
A razão para esse procedimento estranho é que as primeiras implementações Ethernet serializariam a mensagem um byte por vez e transmitiriam o bit menos significativo de cada byte primeiro. O fluxo de bits serial então passou por um cálculo de registro de deslocamento CRC-32 serial, que foi simplesmente complementado e enviado na rede após a mensagem ser concluída. O motivo para complementar os primeiros 32 bits da mensagem é para que você não obtenha um CRC totalmente zero, mesmo que a mensagem seja totalmente zeros.
fonte
Um CRC é muito simples; você pega um polinômio representado como bits e os dados e divide o polinômio nos dados (ou você representa os dados como um polinômio e faz a mesma coisa). O resto, que está entre 0 e o polinômio, é o CRC. Seu código é um pouco difícil de entender, em parte porque está incompleto: temp e testcrc não são declarados, então não está claro o que está sendo indexado e quantos dados estão sendo executados pelo algoritmo.
A maneira de entender os CRCs é tentar computar alguns usando um pequeno pedaço de dados (16 bits ou mais) com um polinômio curto - 4 bits, talvez. Se praticar dessa forma, você realmente entenderá como proceder para codificá-lo.
Se você estiver fazendo isso com frequência, um CRC é muito lento para computar no software. A computação de hardware é muito mais eficiente e requer apenas algumas portas.
fonte
Além da verificação de redundância cíclica da Wikipedia e dos artigos Computação de CRC , achei um artigo intitulado Reversing CRC - Theory and Practice * uma boa referência.
Existem essencialmente três abordagens para calcular um CRC: uma abordagem algébrica, uma abordagem orientada a bits e uma abordagem baseada em tabelas. Em Reversing CRC - Theory and Practice * , cada um desses três algoritmos / abordagens é explicado em teoria, acompanhado no APÊNDICE por uma implementação para o CRC32 na linguagem de programação C.
* PDF Link
Reversing CRC - Teoria e Prática.
HU Berlin Public Report
SAR-PR-2006-05
May 2006
Autores:
Martin Stigge, Henryk Plötz, Wolf Müller, Jens-Peter Redlich
fonte
Passei um tempo tentando descobrir a resposta a esta pergunta e finalmente publiquei um tutorial sobre CRC-32 hoje: Tutorial de hash CRC-32 - Comunidade AutoHotkey
Neste exemplo, demonstro como calcular o hash CRC-32 para a string ASCII 'abc':
fonte
^
? stackoverflow.com/questions/62168128/…Depois, há sempre o Rosetta Code, que mostra o crc32 implementado em dezenas de linguagens de computador. https://rosettacode.org/wiki/CRC-32 e possui links para muitas explicações e implementações.
fonte
Para reduzir o crc32 ao lembrete, você precisa:
No código é:
onde reminderIEEE é o lembrete puro em GF (2) [x]
fonte