1
votes

I think the components of the answer are out there, but I don't understand this stuff well enough, and I'm getting very stuck on conversions.

Here's an implementation I found for NSData to crc32:

https://github.com/krzyzanowskim/CryptoSwift/blob/643bbabd6781b6e226f18815dba616cf6a08629b/CryptoSwift/CRC.swift

Unfortunately, I need a version that has a reverse:

This thread seems to come the closest: Reversing CRC32

I've used its logic to create this which generates the two CRC tables:

func crcTables() -> (forwardTable: [UInt32], reverseTable: [UInt32]) {
    let poly: UInt32 = 0xedb88320;

    var forwardTable: [UInt32] = []
    var reverseTable: [UInt32] = []

    var forward: UInt32 = 0
    var reverse: UInt32 = 0
    for i in 0...UInt32(UInt8.max) {
        forward = i
        reverse = i << (3 * 8)

        for _ in 1...8 {
            if (forward & 1) == 1 {
                forward = (forward >> 1) ^ poly
            } else {
                forward >>= 1
            }

            if (reverse & 0x80000000) != 0 {
                reverse = ((reverse ^ poly) << 1) | 1
            } else {
                reverse <<= 1
            }
        }

        forwardTable.append(forward)
        reverseTable.append(reverse)
    }

    return (forwardTable, reverseTable)
}

But, now I'm very stuck on how to take the data and create a reverse crc32:

func reverseCRC(data: NSData) -> UInt32 {
    var bytes = [UInt8](count: data.length, repeatedValue: 0)
    data.getBytes(&bytes, length:data.length * sizeof(UInt8))


    return 0
}

Update

Through various searching, I have come up with this:

func reverseCRC32WithData(data: NSData, wantedCRC: UInt32 = 0) -> UInt32 {
    var reversedCRC = wantedCRC

    var bytes = [UInt8](count: data.length, repeatedValue: 0)
    data.getBytes(&bytes, length:data.length * sizeof(UInt8))

    // Drop trailing 1 if exists
    let bufferLength = (data.length >> 1) << 1

    for i in 0.stride(to: bufferLength + 4, by: sizeof(UInt16)) {
        var word: UInt16 = 0x0000
        if i < bufferLength {
            let b1 = bytes[bufferLength - 2 - i]
            let b2 = bytes[bufferLength - 1 - i]
            word = (UInt16(b1) << 8) | UInt16(b2)
        } else {
            word = 0xffff
        }

        reversedCRC = ((reversedCRC << 8) & 0xffffffff) ^ ReverseTable[Int((reversedCRC >> 24) & 0xff)] ^ (UInt32(word) >> 8) & 0xff
        reversedCRC = ((reversedCRC << 8) & 0xffffffff) ^ ReverseTable[Int((reversedCRC >> 24) & 0xff)] ^ (UInt32(word) & 0xff)
    }

    return reversedCRC
}

But, I don't really understand it (particularly the last 2 lines), and I'm unsure how to test its accuracy. If anyone can help in that direction.

Goal

I have a firmware update that I'm transmitting to hardware via bluetooth, and once all of the data for the firmware update has been transmitted, I submit a validation payload in the form of a:

Reversed CRC 32 (Big Endian)

1
What do you mean by "reverse"?Mark Adler
@MarkAdler unfortunately, I'm not entirely sure. The last quote on the bottom is what I'm given from the documentation.Logan

1 Answers

0
votes

Reversed CRC 32 (Big Endian)

That sounds like it simply means a normal CRC-32, sent in big-endian order. Most CRC's are generated in bit-reversed order, using a bit-reversed polynomial, since that makes the code a little simpler.

The "big endian" part is independent and refers to the fact that once you have a four-byte value, however it may have been generated, you can put it in the byte stream in big or little endian order. The specification is to put it in the stream in big-endian order, i.e. the most significant byte first.