CRC-32 can't get the correct check sum - any help appreciated

HI, I am trying to write a function node to output CRC-32 values based on a Hex value input, but the calculated CRC values are incorrect. I had no trouble writing function nodes for CRC-8 and CRC-16 so I am not sure why this is not working. I am sure my mistake is something silly.

Here is the Hex value I am trying to find the check sum of > 01C80101C900000000000000. It is input from an inject node in a buffer.

If I put this Hex value it into an online calculator I get the value of 0x664A6454 (edited the checksum as per below) using CRC-32 algorithm >> https://crccalc.com/

This is the function node I have written


buffer = msg.payload;
var crc = 0xFFFFFFFF;   //start crc value
var poly = 0x04C11DB7;  //polynomial 
var odd;

for (var i = 0; i < buffer.length; i++) {
    crc = crc ^ buffer[i];

    for (var j = 0; j < 8; j++) {
        odd = crc & 0x0001;
        crc = crc >> 1;
        if (odd) {
            crc = crc ^ poly;
        }
    }
}

I have tried a few different variations of the CRC-32 code I have found online, like this, but answer is the same.

buffer = msg.payload;
var crc = 0xFFFFFFFF;   //start crc value
var poly = 0x04C11DB7;  //polynomial 

for (var i = 0; i < buffer.length; i++) {
    crc = crc ^ buffer[i];
    for (j = 7; j >= 0; j--) {   
         mask = -(crc & 1);
         crc = (crc >> 1) ^ (poly & mask);
      }
}

So I must be doing something incorrect on the node-red side, but I can't figure it out. Thanks!

I dont get the checksum you mentioned.

The outcome is different for me.
What crc type do you need?

Okay, I had the input selected as ASCII instead of HEX, these are the CRC check sums. I am agnostic on which CRC to use.

For reference the output I am getting from my function node is [FB D8 F5 09] which doesn't match any of these

Any help appreciated. Thanks

Based on one of the many examples in this forum: How can CRC16 XModem accept Hex Input - #2 by Steve-Mcl

A common approach is to use a well established lib. e.g. easy-crc.

Demo of easy-crc

image

Flow (use CTRL-I to import)

[{"id":"e2beeb574d982801","type":"inject","z":"b0865f2b12f5f1a6","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"01C80101C900000000000000","payloadType":"str","x":1090,"y":140,"wires":[["4bf21b40a1445e15"]]},{"id":"4bf21b40a1445e15","type":"function","z":"b0865f2b12f5f1a6","name":"easy-crc","func":"//See https://www.npmjs.com/package/easy-crc?activeTab=readme for list of supported algorithms\n\n/*\nSupported CRC32 algorithms:\nCRC-32\nCRC-32C\nCRC-32D\nCRC-32Q\nBZIP2\nJAMCRC\nMPEG-2\nPOSIX\nXFER\n*/\n\nconst { crc32 } = easyCrc;\nconst data = Buffer.from(msg.payload, 'hex');\nmsg.payload = {} \n\nmsg.payload.CRC32 = crc32('CRC-32', data)\nmsg.payload.CRC32C = crc32('CRC-32C', data)\nmsg.payload.CRC32D = crc32('CRC-32D', data)\nmsg.payload.CRC32Q = crc32('CRC-32Q', data)\nmsg.payload.BZIP2 = crc32('BZIP2', data)\nmsg.payload.JAMCRC = crc32('JAMCRC', data)\nmsg.payload.MPEG2 = crc32('MPEG-2', data)\nmsg.payload.POSIX = crc32('POSIX', data)\nmsg.payload.XFER = crc32('XFER', data)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"easyCrc","module":"easy-crc"}],"x":1100,"y":200,"wires":[["25cd665db5eaa0d9"]]},{"id":"25cd665db5eaa0d9","type":"debug","z":"b0865f2b12f5f1a6","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1130,"y":260,"wires":[]}]

If you are adverse to using NPM modules in your function nodes then here is a hand coded "CRC-32"

image

[{"id":"8cfbeeef9e2ee878","type":"inject","z":"b0865f2b12f5f1a6","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"01C80101C900000000000000","payloadType":"str","x":1090,"y":400,"wires":[["d72681dcdc9878a5"]]},{"id":"d72681dcdc9878a5","type":"function","z":"b0865f2b12f5f1a6","name":"hand coded CRC32","func":"\nconst buffer = Buffer.from(msg.payload, 'hex');\n\nconst makeCRCTable = function () {\n    let c;\n    const crcTable = [];\n    for (let n = 0; n < 256; n++) {\n        c = n;\n        for (let k = 0; k < 8; k++) {\n            c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));\n        }\n        crcTable[n] = c;\n    }\n    return crcTable;\n}\n\nconst crc32 = function (buffer) {\n    const crcTable = context.crcTable || (context.crcTable = makeCRCTable());\n    context.crcTable = crcTable\n    let crc = 0 ^ (-1);\n    for (let i = 0; i < buffer.length; i++) {\n        crc = (crc >>> 8) ^ crcTable[(crc ^ buffer[i]) & 0xFF];\n    }\n    return (crc ^ (-1)) >>> 0;\n};\n\n\nmsg.payload = crc32(buffer)\nreturn msg\n\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1130,"y":460,"wires":[["76586e5b0b84bcc8"]]},{"id":"76586e5b0b84bcc8","type":"debug","z":"b0865f2b12f5f1a6","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1130,"y":520,"wires":[]}]

Awesome, thanks so much Steve! Life saver.

If you have the time to answer one more question. For learning purposes so I can better understand the input and output reflection, how do you modify the code for the CRC32Q implementation?

The first version is very easy. Just specify "CRC-32Q" instead of "CRC-32" inside the function.

For the hand coded version, you will need to adjust it for a different constant and start value (where applicable)

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.