具有AES128 CTR模式的CryptoSwift-越野车计数器递增?

时间:2018-10-11 15:22:54

标签: swift encryption aes cryptoswift

在将CryptoSwift-API (krzyzanowskim)AES128一起使用时,我在CTR-Mode上遇到了问题,我的测试函数(nullArrayBugTest())在特定的计数器值(0到25之间)上产生了=在13和24上)的错误数组计数通常应为16! 即使我将手动递增的“ iv_13”与越野车值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()函数会像我收到的那样处理吗?

感谢您的宝贵时间。

Michael S。

2 个答案:

答案 0 :(得分:2)

CryptoSwift默认为PKCS#7填充。您产生的纯文本具有无效的填充。 CryptoSwift ignores padding errors, 哪个IMO是一个bug,但这就是它的实现方式。 (您认为“正确”的所有计数器实际上都根本无法解密。)(我与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 <16,所以CryptoSwift删除了12个字节,剩下4个字节。(这不是PKCS#7填充的工作方式,而是CryptoSwift的工作方式。)

潜在的问题是您没有解密加密的内容。您只是通过解密方案运行一个静态块。

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

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

这将返回您的期望。

以防万一其他读者有任何困惑:CTR的使用是完全不安全的,不应复制任何内容。我假设实际的加密代码无法像这样工作。

答案 1 :(得分:0)

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

try AES(key: key_.bytes, blockMode: ctr, padding: .noPadding)
相关问题