Как включить CRC32 файла в определенное место? - PullRequest
0 голосов
/ 22 декабря 2018

Я работаю над генератором данных, чтобы сгенерировать двоичные файлы в закрытой системе, для которой мы предполагаем, что нет никакого риска внешних атак или каких-либо злонамеренных намерений.

Идея состоит в том, чтобы найти способ дляэти двоичные файлы содержат быстрый и относительно надежный способ гарантировать, что они не были случайно повреждены в цепочке инструментов, поэтому конечный получатель этого двоичного файла может проверить целостность файла без каких-либо дополнительных ресурсов (таких как file.sha1, содержащий контрольную сумму).

Поскольку это может повлиять на решение, я должен сказать, что двоичный файл может иметь размер от 1 кБ до, возможно, 300 МБ данных.В файле есть определенная позиция, где я могу разместить контрольную сумму любой фиксированной длины для всех файлов.Позиция уже определена, я не могу изменить ее, но могу изменить длину.

Так что, если решение состоит в том, чтобы включить 128 байтов данных в эту позицию, чтобы удовлетворить любой возможный случай, тогда все двоичные файлы будут содержать этодлина байта в этой позиции.

Поскольку было бы невозможно включить в него криптографический хэш файла без необходимости обрезать его перед проверкой, я прочитал, что CRC32 - хороший способ достижения этой цели.Я также ознакомился с такими утилитами, как «обман» или «манипулятор CRC», но они, похоже, не удовлетворяют моему случаю.

Вот краткий пример того, что мне нужно.Давайте рассмотрим двоичный файл:

               This position will never change
               v
1011101100010010000000010110011100100110
               ^^^^^^^^
               This is the fixed-length part dedicated to file integrity check

Я хотел бы найти способ вставить правильную контрольную сумму, чтобы у всего файла, включая контрольную сумму, была общая контрольная сумма.Может быть, известная программа уже делает это?

Спасибо за вашу поддержку

Ответы [ 2 ]

0 голосов
/ 23 декабря 2018

Вам нужно вычислить CRC вперед и назад к точке вставки и поместить туда эксклюзив или из этих двух.Тогда CRC всего этого будет постоянной.(Предполагая отсутствие коррупции.)

Вот пример кода:

// Example of the generation of a "middle" CRC, which is inserted somewhere in
// the middle of a sequence, where the CRC is generated such that the CRC of
// the complete sequence will be zero. This particular CRC has no pre or post
// processing.
//
// Placed into the public domain by Mark Adler, 11 May 2016.

#include <stddef.h>         // for size_t
#include <stdint.h>         // for uint32_t and uint64_t

#define POLY 0xedb88320     // CRC polynomial

// Byte-wise CRC tables for forward and reverse calculations.
uint32_t crc_forward_table[256];
uint32_t crc_reverse_table[256];

// Fill in CRC tables using bit-wise calculations.
void crc32_make_tables(void) {
    for (uint32_t n = 0; n < 256; n++) {
        uint32_t crc = n;
        for (int k = 0; k < 8; k++)
            crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
        crc_forward_table[n] = crc;
        crc_reverse_table[crc >> 24] = (crc << 8) ^ n;
    }
}

// Return the forward CRC of buf[0..len-1], starting with crc at the front.
uint32_t crc32(uint32_t crc, unsigned char *buf, size_t len) {
    for (size_t n = 0; n < len; n++)
        crc = (crc >> 8) ^ crc_forward_table[(crc ^ buf[n]) & 0xff];
    return crc;
}

// Return the reverse CRC of buf[0..len-1], starting with crc at the end.
uint32_t crc32_reverse(uint32_t crc, unsigned char *buf, size_t len) {
    while (len)
        crc = (crc << 8) ^ crc_reverse_table[crc >> 24] ^ buf[--len];
    return crc;
}

// Put a 32-bit value into a byte buffer in little-endian order.
void put4(uint32_t word, unsigned char *pos) {
    pos[0] = word;
    pos[1] = word >> 8;
    pos[2] = word >> 16;
    pos[3] = word >> 24;
}

#include <stdlib.h>         // for random() and srandomdev()

// Fill dat[0..len-1] with uniformly random byte values. All of the bits from
// each random() call are used, except for possibly a few leftover at the end.
void ranfill(unsigned char *dat, size_t len) {
    uint64_t ran = 1;
    while (len) {
        if (ran < 0x100)
            ran = (ran << 31) + random();
        *dat++ = ran;
        ran >>= 8;
        len--;
    }
}

#include <stdio.h>          // for printf()

#define LEN 1024            // length of the message without the CRC

// Demonstrate the generation of a middle-CRC, using the forward and reverse
// CRC computations. Verify that the CRC of the resulting sequence is zero.
int main(void) {
    crc32_make_tables();
    srandomdev();
    unsigned char dat[LEN+4];
    ranfill(dat, LEN/2);
    put4(0, dat + LEN/2);       // put zeros where the CRC will go
    ranfill(dat + LEN/2 + 4, (LEN+1)/2);
    put4(crc32(0, dat, LEN/2) ^ crc32_reverse(0, dat + LEN/2, (LEN+1)/2 + 4),
         dat + LEN/2);          // replace the zeros with the CRC
    printf("%08x\n", crc32(0, dat, LEN+4));
    return 0;
}
0 голосов
/ 22 декабря 2018

Вы все еще можете использовать криптографический хеш, просто скопируйте хеш, а затем обнулите блок хеша перед проверкой хеша.Точно так же, перед тем, как хэшировать файл, вам нужно убедиться, что блок хеша имеет все нули.

Вы можете использовать dd в сценарии оболочки для копирования данных в определенную позицию байта в файле.Или вы можете использовать стандартный файловый ввод-вывод с произвольным доступом на любом хорошем языке программирования.

Однако я хотел бы задать вопрос, действительно ли эта сложность необходима.Более стандартным решением было бы поместить хеш отдельно (либо в отдельный файл, либо в самом начале или конце файла), что полностью исключает эту проблему.Размещение хеша в конце файла может сделать его более неудобным для чтения, в зависимости от формата файла, но при установке хеша в начале файла такой проблемы быть не должно.

...