web-dev-qa-db-fra.com

Comment une somme de contrôle CRC32 est-elle calculée?

Peut-être que je ne le vois tout simplement pas, mais CRC32 semble soit inutilement compliqué, soit insuffisamment expliqué partout où je pourrais trouver sur le Web.

Je comprends que c’est le reste d’une division arithmétique de la valeur du message qui n’est pas basée sur le carry, divisée par le polynôme (générateur), mais son implémentation réelle m’échappe.

J'ai lu Guide indolore des algorithmes de détection d'erreur du CRC , et je dois dire que ce n'était pas indolore. Cela va assez bien sur la théorie, mais l'auteur n'aboutit jamais à un simple "ça y est". Il dit quels sont les paramètres de l'algorithme CRC32 standard, mais il omet de décrire clairement comment vous y parvenez.

La partie qui me tient est quand il dit "c'est ça" et ajoute ensuite, "oh au fait, ça peut être inversé ou commencé avec des conditions initiales différentes", et ne donne pas une réponse claire de ce que la manière finale de calculer une somme de contrôle CRC32 compte tenu de tous les changements qu’il vient d’ajouter.

  • Existe-t-il une explication plus simple de la manière dont CRC32 est calculé?

J'ai essayé de coder en C comment la table est formée:

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;
}

mais cela semble générer des valeurs incompatibles avec celles que j'ai trouvées ailleurs sur Internet. Je pourrais utiliser les valeurs trouvées en ligne, mais je souhaite comprendre comment elles ont été créées.

Toute aide pour éclaircir ces chiffres incroyablement confus serait très appréciée .

84
aquanar

Le polynôme pour CRC32 est:

x32 + x26 + x23 + x22 + x16 + x12 + x11 + xdix + x8 + xsept + x5 + x4 + x2 + x + 1

Ou en hexadécimal et binaire:

0x 01 04 C1 1D B7
1 0000 0100 1100 0001 0001 1101 1011 0111

Le terme le plus élevé (x32) n’est généralement pas écrit explicitement, il peut donc être représenté au format hex

0x 04 C1 1D B7

N'hésitez pas à compter les 1 et les 0, mais vous constaterez qu'ils correspondent au polynôme, où 1 est le bit 0 (ou le premier bit) et x est le bit 1 (ou le second bit).

Pourquoi ce polynôme? Parce qu'il doit y avoir une norme donnée polynôme et la norme a été définie par IEEE 802.3. De plus, il est extrêmement difficile de trouver un polynôme qui détecte efficacement différentes erreurs de bits.

Vous pouvez considérer le CRC-32 comme une série d '"arithmétique binaire sans transport" ou, plus généralement, "d'opérations XOR et de décalage". C'est ce qu'on appelle techniquement l'arithmétique polynomiale.

Pour mieux le comprendre, pensez à cette multiplication:

(x^3 + x^2 + x^0)(x^3 + x^1 + x^0)
= (x^6 + x^4 + x^3
 + x^5 + x^3 + x^2
 + x^3 + x^1 + x^0)
= x^6 + x^5 + x^4 + 3*x^3 + x^2 + x^1 + x^0

Si nous supposons que x est la base 2 alors nous obtenons:

x^7 + x^3 + x^2 + x^1 + x^0

Pourquoi? Parce que 3x ^ 3 est 11x ^ 11 (mais nous n'avons besoin que de 1 ou 0 chiffres), nous reportons donc:

=1x^110 + 1x^101 + 1x^100          + 11x^11 + 1x^10 + 1x^1 + x^0
=1x^110 + 1x^101 + 1x^100 + 1x^100 + 1x^11 + 1x^10 + 1x^1 + x^0
=1x^110 + 1x^101 + 1x^101          + 1x^11 + 1x^10 + 1x^1 + x^0
=1x^110 + 1x^110                   + 1x^11 + 1x^10 + 1x^1 + x^0
=1x^111                            + 1x^11 + 1x^10 + 1x^1 + x^0

Mais les mathématiciens ont changé les règles pour que ce soit le mod 2. Donc, fondamentalement, tout mod polynôme binaire est simplement additionnel, sans retenue ou XOR. Donc, notre équation originale ressemble à:

=( 1x^110 + 1x^101 + 1x^100 + 11x^11 + 1x^10 + 1x^1 + x^0 ) MOD 2
=( 1x^110 + 1x^101 + 1x^100 +  1x^11 + 1x^10 + 1x^1 + x^0 )
= x^6 + x^5 + x^4 + 3*x^3 + x^2 + x^1 + x^0 (or that original number we had)

Je sais que c’est un acte de foi, mais c’est au-delà de mes capacités en tant que programmeur. Si vous êtes un étudiant en informatique ou un ingénieur endurcis, je vous défie de le décomposer. Tout le monde va bénéficier de cette analyse.

Donc, pour élaborer un exemple complet:

   Original message                : 1101011011
   Polynomial of (W)idth 4         :      10011
   Message after appending W zeros : 11010110110000

Maintenant, nous divisons le Message augmenté par le Poly en utilisant l’arithmétique CRC. C'est la même division que précédemment:

            1100001010 = Quotient (nobody cares about the quotient)
       _______________
10011 ) 11010110110000 = Augmented message (1101011011 + 0000)
=Poly   10011,,.,,....
        -----,,.,,....
         10011,.,,....
         10011,.,,....
         -----,.,,....
          00001.,,....
          00000.,,....
          -----.,,....
           00010,,....
           00000,,....
           -----,,....
            00101,....
            00000,....
            -----,....
             01011....
             00000....
             -----....
              10110...
              10011...
              -----...
               01010..
               00000..
               -----..
                10100.
                10011.
                -----.
                 01110
                 00000
                 -----
                  1110 = Remainder = THE CHECKSUM!!!!

La division donne un quotient, que nous jetons, et un reste, qui est la somme de contrôle calculée. Ceci termine le calcul. Habituellement, la somme de contrôle est ensuite ajoutée au message et le résultat transmis. Dans ce cas, la transmission serait: 11010110111110.

Utilisez uniquement un nombre 32 bits comme diviseur et utilisez l'intégralité de votre flux comme dividende. Jetez le quotient et conservez le reste. Pointez le reste sur la fin de votre message et vous avez un CRC32.

Critique moyenne des gars:

         QUOTIENT
        ----------
DIVISOR ) DIVIDEND
                 = REMAINDER
  1. Prenez les 32 premiers bits.
  2. Bits de décalage
  3. Si 32 bits sont inférieurs à DIVISOR, passez à l'étape 2.
  4. XOR 32 bits de DIVISOR. Passez à l'étape 2.

(Notez que le flux doit être divisible par 32 bits ou doit être rempli. Par exemple, un flux ANSI 8 bits doit être rempli. De plus, à la fin du flux, la division est arrêtée.)

93
user295190

Un CRC est assez simple. vous prenez un polynôme représenté sous forme de bits et de données et divisez le polynôme en données (ou vous représentez les données sous forme de polynôme et faites la même chose). Le reste, qui est compris entre 0 et le polynôme est le CRC. Votre code est un peu difficile à comprendre, en partie parce qu’il est incomplet: temp et testcrc ne sont pas déclarés, il n’est donc pas clair ce qui est indexé et combien de données sont traitées par l’algorithme.

Pour comprendre les CRC, essayez d’en calculer quelques-unes en utilisant une courte donnée (environ 16 bits) avec un polynôme court - 4 bits peut-être. Si vous pratiquez de cette façon, vous comprendrez vraiment comment vous pourriez coder.

Si vous le faites fréquemment, un CRC est assez lent à calculer dans un logiciel. Le calcul du matériel est beaucoup plus efficace et ne nécessite que quelques portes.

8
WhirlWind

Pour IEEE802.3, CRC-32. Pensez à l’ensemble du message en tant que flux de bits série, ajoutez 32 zéros à la fin du message. Ensuite, vous DEVEZ inverser les bits de CHAQUE octet du message et effectuer un complément à 1 des 32 premiers bits. Divisez maintenant par le polynôme CRC-32, 0x104C11DB7. Enfin, vous devez compléter le reste de 32 bits de cette division en inversant les bits, chacun des 4 octets du reste. Cela devient le CRC 32 bits qui est ajouté à la fin du message.

La raison de cette procédure étrange est que les premières implémentations Ethernet sérialisaient le message octet par octet et transmettaient le bit le moins significatif de chaque octet en premier. Le flux de bits série a ensuite été soumis à un calcul de registre à décalage CRC-32 série, qui a simplement été complété et envoyé sur le fil une fois le message terminé. La raison pour laquelle les 32 premiers bits du message sont complétés est que vous n'obtenez pas un CRC à zéro, même si le message était entièrement nul.

7
Pavlo Bobrek

En plus des articles Wikipédia Vérification cyclique de la redondance et Calcul du CRC ), j'ai trouvé un article. titré Inverser le CRC - Théorie et pratique* être une bonne référence.

Il existe essentiellement trois approches pour calculer un CRC: une approche algébrique, une approche axée sur les bits et une approche basée sur des tables. Dans Inverser le CRC - Théorie et pratique*, chacun de ces trois algorithmes/approches est expliqué en théorie accompagné dans l’ANNEXE d’une implémentation pour le CRC32 dans le langage de programmation C.

Lien PDF
Inverser la CDE - Théorie et pratique.
Rapport public HU Berlin
SAR-PR-2006-05
Mai 2006
Auteurs:
Martin Stigge, Henryk Plötz, Wolf Müller, Jens-Peter Redlich

6
jschmier

J'ai passé un certain temps à essayer de découvrir la réponse à cette question et j'ai finalement publié un tutoriel sur le CRC-32 aujourd'hui: tutoriel sur le hachage CRC-32 - AutoHotkey Community

Dans cet exemple, je montre comment calculer le hachage CRC-32 pour le ASCII chaîne 'abc':

calculate the CRC-32 hash for the ASCII string 'abc':

inputs:
dividend: binary for 'abc': 0b011000010110001001100011 = 0x616263
polynomial: 0b100000100110000010001110110110111 = 0x104C11DB7

011000010110001001100011
reverse bits in each byte:
100001100100011011000110
append 32 0 bits:
10000110010001101100011000000000000000000000000000000000
XOR the first 4 bytes with 0xFFFFFFFF:
01111001101110010011100111111111000000000000000000000000

'CRC division':
01111001101110010011100111111111000000000000000000000000
 100000100110000010001110110110111
 ---------------------------------
  111000100010010111111010010010110
  100000100110000010001110110110111
  ---------------------------------
   110000001000101011101001001000010
   100000100110000010001110110110111
   ---------------------------------
    100001011101010011001111111101010
    100000100110000010001110110110111
    ---------------------------------
         111101101000100000100101110100000
         100000100110000010001110110110111
         ---------------------------------
          111010011101000101010110000101110
          100000100110000010001110110110111
          ---------------------------------
           110101110110001110110001100110010
           100000100110000010001110110110111
           ---------------------------------
            101010100000011001111110100001010
            100000100110000010001110110110111
            ---------------------------------
              101000011001101111000001011110100
              100000100110000010001110110110111
              ---------------------------------
                100011111110110100111110100001100
                100000100110000010001110110110111
                ---------------------------------
                    110110001101101100000101110110000
                    100000100110000010001110110110111
                    ---------------------------------
                     101101010111011100010110000001110
                     100000100110000010001110110110111
                     ---------------------------------
                       110111000101111001100011011100100
                       100000100110000010001110110110111
                       ---------------------------------
                        10111100011111011101101101010011

remainder: 0b10111100011111011101101101010011 = 0xBC7DDB53
XOR the remainder with 0xFFFFFFFF:
0b01000011100000100010010010101100 = 0x438224AC
reverse bits:
0b00110101001001000100000111000010 = 0x352441C2

thus the CRC-32 hash for the ASCII string 'abc' is 0x352441C2
4
vafylec