1

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)

Community
  • 1
  • 1
Logan
  • 52,262
  • 20
  • 99
  • 128

2 Answers2

1

I just found this answer from Apple Document,

In my case, it work for me,

let CRC32_UInt32 = CRC32.checksum(bytes: inputBytes) // 73DECCF1
let reverse_CRC32_UInt32 = CFSwapInt32(CRC32_UInt32)
let reverse_crc32 = String(reverse_CRC32_UInt32, radix: 16, uppercase: true) // F1CCDE73

below is CRC32 Algorithm:

class CRC32 {
        
    static var table: [UInt32] = {
        (0...255).map { i -> UInt32 in
            (0..<8).reduce(UInt32(i), { c, _ in
                (c % 2 == 0) ? (c >> 1) : (0xEDB88320 ^ (c >> 1))
            })
        }
    }()

    static func checksum(bytes: [UInt8]) -> UInt32 {
        return ~(bytes.reduce(~UInt32(0), { crc, byte in
            (crc >> 8) ^ table[(Int(crc) ^ Int(byte)) & 0xFF]
        }))
    }
}

hope this will be helpful for any needed ppl

羅祐昌
  • 11
  • 2
0

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.

Mark Adler
  • 101,978
  • 13
  • 118
  • 158
  • Interesting also is that Network Standard Order is big-endian. Also interesting is I asked: *what is meant by "reverse format"*. – zaph Dec 08 '15 at 03:13