【问题标题】:Apple Watch crashes on bit operations with error code Thread1: exc_breakpoint(code=exc_arm_breakpoint,subcode=0xe7ffdefe)Apple Watch 在位操作时崩溃,错误代码 Thread1: exc_breakpoint(code=exc_arm_breakpoint,subcode=0xe7ffdefe)
【发布时间】:2017-04-11 11:48:49
【问题描述】:

我正在使用 SHA1 对 Apple Watch 上的用户数据进行哈希处理,当运行 SHA1Bytes 函数时,我收到以下错误:

线程 1:exc_breakpoint(code=exc_arm_breakpoint,subcode=0xe7ffdefe)。 这个特定的行给了我错误: j = ( UInt32((msg[i]<<24) | (msg[i+1]<<16) | (msg[i+2]<<8) | msg[i+3]) )

这是提取上述行的一段代码:

class func SHA1Bytes(msg: [Int])->String{
        func rotateLeft(number: UInt32, rotateBy: UInt32)->UInt32{
            return ((number << rotateBy) | (number>>(32-rotateBy)))
        }

        func cvt_hex(value: UInt32)->String{
            var str = ""
            for i:UInt32 in stride(from: 7, through: 0, by: -1){
                let v: UInt32 = (value >> (i*4)&0x0f)
                str += String(v,radix: 16, uppercase: false)
            }
            return str
        }

        var W = [UInt32](repeating: 0, count: 80)
        var H0 = UInt32("67452301",radix: 16)!
        var H1 = UInt32("EFCDAB89",radix: 16)!
        var H2 = UInt32("98BADCFE",radix: 16)!
        var H3 = UInt32("10325476",radix: 16)!
        var H4 = UInt32("C3D2E1F0",radix: 16)!

        var wordArray = [UInt32]()
        for k in stride(from: 0, to: msg.count-3, by: 4) {
            let j = ( UInt32((msg[k]<<24) | (msg[k+1]<<16) | (msg[k+2]<<8) | msg[k+3]) )
            wordArray.append(j)
        }
        ...
        return encoded.uppercased()
    }

完全相同的代码在 iOS Playground 中完美运行,但在第一代 Apple Watch 上运行时崩溃。我已经检查并且输入数组存在,我正在尝试访问它的现有元素,j 的结果不应该溢出。 代码因以下变量值而失败:

j=(UInt32) 2308511418, k=(Int)48, msg=([Int])56values

这些是msg的值:

[47]    Int 217
[48]    Int 137
[49]    Int 153
[50]    Int 22
[51]    Int 186
[52]    Int 163
[53]    Int 41
[54]    Int 208
[55]    Int 104

【问题讨论】:

  • 1. SHA1 不是加密,它是一个加密哈希函数。 2. 使用 Common Crypto 而不是本地实现。
  • 感谢您的更正,但是我想重新创建与后端进行身份验证完全相同的方法,因此最好更正这段代码。而且我仍然很好奇为什么它不能在 Watch 上运行,而它在操场上完美运行......
  • SHA1 是一种标准方法,除非代码中出现错误,否则您可以使用不同的实现并获得相同的结果。
  • 我理解,但更改为标准方法仍然有助于我理解导致此错误的原因。此外,我想让我的项目保持纯 Swift 并避免创建桥接头。
  • 啊,纯粹的快速思想,该死的正确性和性能。 Swift3:let messageData = string.data(using:.utf8)!var digestData = Data(count: Int(CC_SHA1_DIGEST_LENGTH))_ = digestData.withUnsafeMutableBytes {digestBytes inmessageData.withUnsafeBytes {messageBytes inCC_SHA1(messageBytes, CC_LONG(messageData.count), digestBytes)}}

标签: swift swift3 apple-watch watchos-3


【解决方案1】:

第一代 Apple Watch 是 32 位设备,与 64 位设备相比具有不同的溢出限制。

在 32 位设备上,Int 类型是 32 位的,您有转移到符号位的风险。

在游乐场尝试以下操作:

UInt32(Int64(153) << 24) // Equivalent to your code

UInt32(Int32(153) << 24) // Simulates a 32-bit device and crashes.

UInt32(153) << 24         // A possible solution

【讨论】:

  • 你是对的,出于某种原因,即使 UInt32 溢出,操场也不会崩溃。但是,即使您的第三行也会导致溢出,操场会忽略该溢出,但 Apple Watch 不会,但我找到了解决方案并将其添加为答案。我不得不使用溢出乘法而不是按位左移。
【解决方案2】:

我设法弄清楚即使 UInt32 溢出模拟器也不会崩溃,但是,在这种情况下,32 位 Apple Watch 确实会崩溃。 解决方案是使用溢出运算符,它只存在于加法、减法和乘法。因此,我将按位左移更改为乘以 2^(要移动的位数)。 这是正确的解决方案:UInt32(msg[k])&amp;*UInt32(1&lt;&lt;24)

let j = (UInt32(msg[k])&amp;*UInt32(1&lt;&lt;24))|UInt32(msg[k+1]&amp;*(1&lt;&lt;16))|UInt32(msg[k+2]&amp;*(1&lt;&lt;8))|UInt32(msg[k+3])

【讨论】:

  • 最好真正依赖 FIPS 认证或经过严格审查的实施。
  • 我理解您的安全顾虑,但请理解我选择不使用 Common Crypto 并非偶然,我还必须考虑其他因素。
猜你喜欢
  • 2013-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多