在 Swift 中反转 CRC-32 NSData

Posted

技术标签:

【中文标题】在 Swift 中反转 CRC-32 NSData【英文标题】:Reverse CRC-32 NSData in Swift 【发布时间】:2016-03-12 12:03:52 【问题描述】:

我认为答案的组成部分已经存在,但我对这些东西的理解还不够透彻,而且我在转换上非常卡住。

这是我找到的 NSData 到 crc32 的实现:

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

不幸的是,我需要一个反向的版本:

这个帖子似乎是最接近的:Reversing CRC32

我已经使用它的逻辑来创建它,它会生成两个 CRC 表:

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)

但是,现在我非常纠结于如何获取数据并创建反向 crc32:

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


    return 0

更新

通过各种搜索,我想出了这个:

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

但是,我不太了解它(尤其是最后两行),我不确定如何测试它的准确性。如果有人可以在这个方向上提供帮助。

目标

我有一个固件更新,我通过蓝牙传输到硬件,一旦固件更新的所有数据都传输完毕,我会提交一个验证负载,格式为:

逆向 CRC 32(大端)

【问题讨论】:

“反向”是什么意思? @MarkAdler 不幸的是,我不完全确定。底部的最后一句话是我从文档中得到的。 【参考方案1】:

逆向 CRC 32(大端)

这听起来只是意味着一个普通的 CRC-32,以大端顺序发送。大多数 CRC 是使用位反转多项式以位反转顺序生成的,因为这使代码更简单。

“大端”部分是独立的,指的是一旦你有一个四字节的值,不管它可能已经生成,你可以把它按大端或小端的顺序放在字节流中。规范是按大端顺序将其放入流中,即最重要的字节在前。

【讨论】:

有趣的还有网络标准顺序是大端的。另外有趣的是我问:“反向格式”是什么意思

以上是关于在 Swift 中反转 CRC-32 NSData的主要内容,如果未能解决你的问题,请参考以下文章

在 Objective-C 中获取 NSData 的 CRC 校验和

反转 CRC32

反转 CRC32(a)

CUDA C - CRC32 - 寻找未知多项式和 crcxor - 程序加速

将 UIImage 转换为 NSData 并在 Swift 中转换回 UIImage?

将UIImage转换为NSData并在Swift中转换回UIImage?