0

From this answer I adapted the code below:

function _makeCRCTable() {
    const CRCTable = new Uint32Array(256);
    for (let i = 256; i--;) {
        let char = i;
        for (let j = 8; j--;) {
            char = char & 1 ? 3988292384 ^ char >>> 1 : char >>> 1;
        }
        CRCTable[i] = char;
    }
    return CRCTable;
}

This code generates table as here, but for Ogg I need another table - as here.

From Ogg documentation:

32 bit CRC value (direct algorithm, initial val and final XOR = 0, generator polynomial=0x04c11db7)

parseInt('04c11db7', 16)

return 79764919 - I tried this polynomial but resulting table is not correct.

I am new to the CRC field, as I found there are a few variations of CRC32 algorithm.

rcgldr
  • 27,407
  • 3
  • 36
  • 61
Vitaly Zdanevich
  • 13,032
  • 8
  • 47
  • 81
  • Why do you need a function that procedurally generates the table when you could just copy and paste that one? – Patrick Roberts Nov 22 '18 at 22:57
  • I think that this is more secure to generate table - against accidental changing of some value - with will lead to a bad situation when CRC32 will correct for 99% of cases. – Vitaly Zdanevich Nov 22 '18 at 23:01

1 Answers1

2

I'm not sure of javascript precedence, but the xor needs to occur after the shift:

char = char & 1 ? 3988292384 ^ (char >>> 1) : char >>> 1;

However the first table you show seems correct, as table[128] = table[0x80] = 3988292384 = 0xEDB88320 which is 0x104c11db7 bit reversed, then shifted right one bit.

The second table you have is for a left shifting CRC, where table[1] = x04c11db7. In this case the inner loop would include something like this:

let char = i << 24;
for (let j = 8; j--;) {
    char = char & 0x80000000 ? 0x04c11db7 ^ char << 1 : char << 1;
}

Example C code for comparison, generates crc for the patterns {0x01}, {0x01,0x00}, {0x01,0x00,0x00}, {0x01,0x00,0x00,0x00}.

#include <stdio.h>

typedef unsigned char uint8_t;
typedef unsigned int  uint32_t;

uint32_t crctbl[256];

void gentbl(void)
{
uint32_t crc;
uint32_t b;
uint32_t c;
uint32_t i;
    for(c = 0; c < 0x100; c++){
        crc = c<<24;
        for(i = 0; i < 8; i++){
            b = crc>>31;
            crc <<= 1;
            crc ^= (0 - b) & 0x04c11db7;
        }
        crctbl[c] = crc;
    }
}

uint32_t crc32(uint8_t * bfr, size_t size)
{
uint32_t crc = 0;
    while(size--)
        crc = (crc << 8) ^ crctbl[(crc >> 24)^*bfr++];
    return(crc);
}

int main(int argc, char** argv)
{
    uint32_t crc;
    uint8_t bfr[4] = {0x01,0x00,0x00,0x00};
    gentbl();
    crc = crc32(bfr, 1);        /* 0x04c11db7 */
    printf("%08x\n", crc);
    crc = crc32(bfr, 2);        /* 0xd219c1dc */
    printf("%08x\n", crc);
    crc = crc32(bfr, 3);        /* 0x01d8ac87 */
    printf("%08x\n", crc);
    crc = crc32(bfr, 4);        /* 0xdc6d9ab7 */
    printf("%08x\n", crc);
    return(0);
}

For JS:

function _makeCRC32Table() {
    const polynomial = 79764919;
    const mask = 2147483648;
    const CRCTable = new Uint32Array(256);
    for (let i = 256; i--;) {
        let char = i << 24;
        for (let j = 8; j--;) {
            char = char & mask ? polynomial ^ char << 1 : char << 1;
        }
        CRCTable[i] = char;
    }
    return CRCTable;
}

How to use this table:

[1, 0].reduce((crc, byte) => crc << 8 >>> 0 ^ CRCTable[crc >>> 24 ^ byte], 0) >>> 0

Here we added >>> 0 that takes the module of the number - because there is no unsigned int in JS - JavaScript doesn't have integers. It only has double precision floating-point numbers.

Note that for Ogg you must set generated CRC in the reverse order.

Vitaly Zdanevich
  • 13,032
  • 8
  • 47
  • 81
rcgldr
  • 27,407
  • 3
  • 36
  • 61
  • Thank you, I tried your code and my table now is `0 256 512 768 1024` in decimal numbers, looks like this is not correct. Anything else I can try? Also, just FYI - in JS left shift is `<<` and looks like XOR (^) already executed after the shift - according to the message from `Eslint` and I checked with and without brackets - result is the same. – Vitaly Zdanevich Nov 23 '18 at 07:52
  • @VitalyZdanevich - I didn't include enough of the code. I updated my answer. `i` needs to go into the upper bits of the crc before it is cycled. – rcgldr Nov 23 '18 at 08:13
  • Thank you! `0x04c11db7` is called polynomial, but what it `0x80000000`? I just want to use named variables in lieu of this magic numbers. – Vitaly Zdanevich Nov 23 '18 at 11:01
  • @VitalyZdanevich - 0x80000000 is the mask for most significant bit which is checked before doing the left shift. If it is 1 before the left shift, then after the left shift the crc is xor'ed with 0x04c11db7. This is simulating a divide by 0x104c11db7, which is 33 bits. If this was doing using 64 bit integers, you could shift left first, then check for (crc & 0x100000000) and if it's not zero, then xor with 0x104c11db7. – rcgldr Nov 23 '18 at 11:21
  • Thank you, and another question - the next part of CRC32 algorithm that uses this table in always the same in all CRC variants? For example [this one](https://stackoverflow.com/a/18639999/1879101) is correct? – Vitaly Zdanevich Nov 23 '18 at 11:57
  • @VitalyZdanevich - the main variations are initializing the CRC to 0 or to 0xFFFFFFFF (this is common), and if the CRC is complemented at the end (this is not that common). The table itself is made for taking in a byte, and cycling for 8 bits, where the index into the table is the byte value, 0x00 to 0xFF. The sequence is to XOR a byte of data with either the upper byte of the CRC for a left shifting CRC or with the lower byte of the CRC for a right shifting CRC, then using the upper or lower byte of the CRC to index the table to get the new CRC. – rcgldr Nov 23 '18 at 15:02
  • oh this is complicated for me now :( I cannot get correct result with my current code (assuming that input data is correct...) now I have this code: `arrayWithInputNumbers.reduce((crc, num) => crc << 8 ^ CRCTable[num ^ crc >>> 24], 0)` is it ok? As I mention documentation about Ogg in my original question - `direct algorithm, initial val and final XOR = 0` – Vitaly Zdanevich Nov 23 '18 at 16:12
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/184153/discussion-between-rcgldr-and-vitaly-zdanevich). – rcgldr Nov 23 '18 at 16:13