Реверсивный CRC32 - PullRequest
       22

Реверсивный CRC32

9 голосов
/ 03 октября 2009

Я ищу способ отменить контрольную сумму CRC32 . Есть решения вокруг, но они либо плохо написаны , чрезвычайно технически и / или в сборке . Сборка (в настоящее время) выходит за рамки моего понимания, поэтому я надеюсь, что кто-то сможет собрать реализацию на языке более высокого уровня. Ruby идеален, но я могу разбирать PHP, Python, C, Java и т. Д.

Есть ли кто-нибудь?

Ответы [ 4 ]

19 голосов
/ 03 октября 2009

CRC32 является обратимым, только если исходная строка имеет длину 4 байта или менее.

5 голосов
/ 22 октября 2009

Прочитайте документ под названием "Обратный ход теории и практики CRC" .

Это C #:

public class Crc32
{
    public const uint poly = 0xedb88320;
    public const uint startxor = 0xffffffff;

    static uint[] table = null;
    static uint[] revtable = null;

    public void FixChecksum(byte[] bytes, int length, int fixpos, uint wantcrc)
    {
        if (fixpos + 4 > length) return;

        uint crc = startxor;
        for (int i = 0; i < fixpos; i++) {
            crc = (crc >> 8) ^ table[(crc ^ bytes[i]) & 0xff];
        }

        Array.Copy(BitConverter.GetBytes(crc), 0, bytes, fixpos, 4);

        crc = wantcrc ^ startxor;
        for (int i = length - 1; i >= fixpos; i--) {
            crc = (crc << 8) ^ revtable[crc >> (3 * 8)] ^ bytes[i];
        }

        Array.Copy(BitConverter.GetBytes(crc), 0, bytes, fixpos, 4);
    }

    public Crc32()
    {
        if (Crc32.table == null) {
            uint[] table = new uint[256];
            uint[] revtable = new uint[256];

            uint fwd, rev;
            for (int i = 0; i < table.Length; i++) {
                fwd = (uint)i;
                rev = (uint)(i) << (3 * 8);
                for (int j = 8; j > 0; j--) {
                    if ((fwd & 1) == 1) {
                        fwd = (uint)((fwd >> 1) ^ poly);
                    } else {
                        fwd >>= 1;
                    }

                    if ((rev & 0x80000000) != 0) {
                        rev = ((rev ^ poly) << 1) | 1;
                    } else {
                        rev <<= 1;
                    }
                }
                table[i] = fwd;
                revtable[i] = rev;
            }

            Crc32.table = table;
            Crc32.revtable = revtable;
        }
    }
}
1 голос
/ 15 ноября 2012

Вы можете изменить его, возвращая биты, чтобы сгенерировать исходные 32 бита, если вы знаете, с каким поли он был создан. Но если вы хотите перевернуть CRC32 из заданного файла и добавить последовательность байтов в конец файла, чтобы соответствовать исходному CRC, я разместил код в этой теме на PHP:

Я потратил немного времени на это, поэтому надеюсь, что это поможет кому-то, работающему над более сложными проблемами: Реверсивный CRC32 Ура! * * 1005

0 голосов
/ 03 октября 2009

Cade Roux прав насчет реверсирования CRC32.

Упомянутые вами ссылки предоставляют решение для исправления CRC, который стал недействительным путем изменения исходного потока байтов. Это исправление достигается путем изменения некоторых (неважных) байтов и воссоздания исходного значения CRC.

...