【问题标题】:CryptoSwift with AES128 CTR Mode - Buggy counter increment?具有 AES128 CTR 模式的 CryptoSwift - 错误计数器增量?
【发布时间】:2018-10-11 15:22:53
【问题描述】:

我在使用AES128CTR-Mode 和我的测试函数(nullArrayBugTest()) 时遇到了CryptoSwift-API (krzyzanowskim) 的问题,该函数在特定计数器值(0 和25 之间= 13 和24 之间)上产生错误数组计数通常应该是 16! 即使我使用带有错误值 13 的手动递增的“iv_13”而不是默认的“iv_0”和计数器 13... 测试一下以了解我的意思。

  func nullArrayBugTest() {
    var ctr:CTR
    let nilArrayToEncrypt = Data(hex: "00000000000000000000000000000000")
    let key_ = Data(hex: "000a0b0c0d0e0f010203040506070809")
    let iv_0:  Array<UInt8> = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]
    //let iv_13:  Array<UInt8> = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x1c]
    var decryptedNilArray = [UInt8]()

    for i in 0...25 {
        ctr = CTR(iv: iv_0, counter: i)
        do {
            let aes = try AES(key: key_.bytes, blockMode: ctr)
            decryptedNilArray = try aes.decrypt([UInt8](nilArrayToEncrypt))
            print("AES_testcase_\(i) for ctr: \(ctr) withArrayCount: \(decryptedNilArray.count)")
        }catch {
            print("De-/En-CryptData failed with: \(error)")
        }
    }
}

Output with buggy values

为什么我总是需要具有 16 个值的加密数组的问题并不重要:D。

有人知道为什么aes.decrypt()-function 会像我收到的那样处理吗?

感谢您的宝贵时间。

迈克尔·S.

【问题讨论】:

    标签: swift encryption aes cryptoswift


    【解决方案1】:

    CryptoSwift 默认为 PKCS#7 填充。您生成的明文有无效的填充。 CryptoSwift ignores padding errors, which IMO 是一个错误,但这就是它的实现方式。 (您认为“正确”的所有计数器都应该根本无法解密。)(我与 Marcin 讨论过这个问题,他提醒我,即使在这个低级别,忽略填充错误也是正常的以避免填充 oracle 攻击。I'd forgotten that I do it this way too....)

    也就是说,有时填充会“足够接近”,以至于 CryptoSwift 会尝试删除填充字节。它通常不是有效的填充,但对于 CrypoSwift 的测试来说已经足够接近了。

    例如,您的第一个计数器创建以下填充明文:

    [233, 222, 112, 79, 186, 18, 139, 53, 208, 61, 91, 0, 120, 247, 187, 254]
    

    254 > 16,因此 CryptoSwift 不会尝试删除填充。

    对于 13 的计数器,返回以下填充明文:

    [160, 140, 187, 255, 90, 209, 124, 158, 19, 169, 164, 110, 157, 245, 108, 12]
    

    12

    根本问题是你没有解密你加密的东西。您只是通过解密方案运行一个静态块。

    如果你不想要填充,你可以要求:

    let aes = try AES(key: key_.bytes, blockMode: ctr, padding: .noPadding)
    

    这将返回您所期望的。

    以防其他读者有任何困惑:CTR 的这种使用非常不安全,不应复制任何部分。我假设实际的加密代码不能像这样工作。

    【讨论】:

      【解决方案2】:

      我猜加密是在没有应用填充的情况下发生的,但是你使用填充来解密。要解决此问题,请在两侧使用相同的技术。也就是说,这是一个解决方案(@rob-napier 答案更详细):

      try AES(key: key_.bytes, blockMode: ctr, padding: .noPadding)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-24
        • 1970-01-01
        • 1970-01-01
        • 2020-04-29
        • 2021-08-10
        • 1970-01-01
        • 1970-01-01
        • 2018-04-15
        相关资源
        最近更新 更多