【问题标题】:AES key with setIsStrongBoxBacked - failed decryption带有 setIsStrongBoxBacked 的 AES 密钥 - 解密失败
【发布时间】:2020-04-20 11:19:31
【问题描述】:

我在带有 setIsStrongBoxBacked=true 的 StrongBox (Pixel 4) 的 Android 10 设备上生成了 AES 密钥,如下所示:

fun generateKey(): SecretKey {
        val generator = KeyGenerator.getInstance("AES", "AndroidKeyStore")
        generator.init(
                KeyGenParameterSpec.Builder("alias", PURPOSE_ENCRYPT or PURPOSE_DECRYPT)
                        .setBlockModes(BLOCK_MODE_GCM)
                        .setEncryptionPaddings(ENCRYPTION_PADDING_NONE)
                        .setIsStrongBoxBacked(true)
                        .build()
        )
        return generator.generateKey()
}

接下来,我使用这个密钥加密了一些 ByteArray。一段时间后,在使用相同的密钥和相同的 IV 向量进行解密的过程中,我得到了错误的 ByteArray,结果毫无例外。

加密和解密方法都很标准:

fun encrypt(plaintext: ByteArray, iv: ByteArray, key: SecretKey): ByteArray {
        val cipher = Cipher.getInstance("AES/GCM/NoPadding")
        cipher.init(ENCRYPT_MODE, key, GCMParameterSpec(128, iv))
        return cipher.doFinal(plaintext)
}

fun decrypt(ciphertext: ByteArray, iv: ByteArray, key: SecretKey): ByteArray {
        val cipher = Cipher.getInstance("AES/GCM/NoPadding")
        cipher.init(DECRYPT_MODE, key, GCMParameterSpec(128, iv))
        return cipher.doFinal(ciphertext)
}

奇怪的是,使用相同的密钥生成代码,但使用setIsStrongBoxBacked=false,以及相同的加密/解密逻辑,一切都按预期工作。

官方文档没有说对我的情况有帮助。目前,我可以禁用 StrongBox 支持逻辑,但我想知道问题出在哪里 - 我的代码是缺少关键的东西还是 Android 10/Pixel 4 的问题?

附言

经过进一步检查,我意识到加密逻辑也有问题。使用setIsStrongBoxBacked=true,每次我使用 AES/GCM/NoPadding 算法加密任何 ByteArray 时,即使 IV 是随机生成的,密文看起来都一样(只有身份验证标签部分不同)。根据我对 GCM 模式的了解,有些地方不对劲。

setIsStrongBoxBacked=true加密1:

IV=[40, 91, -4, -98, 104, 94, -39, -83, -34, 22, -33, 12]

ciphertext=[13, -48, -83, -34, 13, -48, -83, -34, 13, -48, -83, -34, 13, -48, -83, -34, 13, -48, -83, -34, 13, -48, -83, -34, 13, -48, -83, -34, 13, -48, -83, -34, 12, -86, -16, -38, 93, 100, 82, 108, 101, -27, -42, -107, 36, 49, 109, 47]

setIsStrongBoxBacked=true加密2:

IV=[-123, -96, -66, -87, 43, -103, -126, -107, 8, -73, 68, -49]

ciphertext=[13, -48, -83, -34, 13, -48, -83, -34, 13, -48, -83, -34, 13, -48, -83, -34, 13, -48, -83, -34, 13, -48, -83, -34, 13, -48, -83, -34, 13, -48, -83, -34, 85, 108, -23, -62, 18, 74, -81, -2, 111, -94, 7, 15, -56, 106, -114, -69]

对于setIsStrongBoxBacked=false,只要IV每次都不同,相同的加密逻辑就会生成完全不同的密文,就像它应该做的那样:

setIsStrongBoxBacked=false加密1:

IV=[-113, -48, -5, -106, -86, -1, 121, -40, -13, -54, -56, 10]

ciphertext=[126, -97, 118, 42, -110, 67, 77, 9, 120, -79, 74, -101, -123, 106, -21, -18, -49, -123, -10, -33, -4, -99, 58, -125, 69, -37, 111, -66, -114, -47, 17, 41, -3, 72, -52, -36, -67, 47, 39, -108, -46, -113, 114, -46, -114, 24, -51, -95]

setIsStrongBoxBacked=false加密2:

IV=[-106, 12, -84, -108, -102, -11, 38, 30, 10, 22, -123, -28]

ciphertext=[-51, -85, -125, -34, -72, 47, -13, 6, -111, 14, -85, 53, -8, -68, -17, -81, -106, 50, -94, -22, 66, 74, -39, 12, 12, 74, 48, -41, -41, -55, -28, 2, 61, 11, 120, -3, 124, 8, -46, 78, -93, 97, 87, -97, -26, -42, -105, 74]

附言 2

只有在使用 AES/GCM/NoPadding 算法时才会出现此问题。对于其他 AES 模式(CBC、CRT 等),即使setIsStrongBoxBacked=true,加密和解密都可以正常工作

附言 3 问题 - https://issuetracker.google.com/issues/147039506

附言 4 应用适用于 Pixel 4 的最新安全补丁后,问题消失了。

【问题讨论】:

  • 你可能想提交一个错误报告(如果你找不到骗子),这太奇怪了,绝对不应该发生。请注意,如果没有加密/解密代码,我们无法判断您是否在那里犯了错误。
  • @Maarten-reinstateMonica 嘿,感谢重播 :) 我已经通过复制和粘贴加密和解密方法编辑了我的问题 - 正如您可能知道的那样,它们非常标准。现在我将在 CRT 模式下使用 AES,因为它按预期工作,现在我不需要在解密机制上进行身份验证。我还将按照您的建议在 Google 问题跟踪器中打开问题 :)
  • 不,我不能对那个特定的代码说什么。如果有什么问题,那就是调用辅助方法的方式。但是,如果您对其他模式使用完全相同的代码,那么我猜它就是这样。打开问题后,别忘了在下方提供链接!

标签: android cryptography pixel


【解决方案1】:

您似乎重新发现了 CVE-2019-9465。正如您所注意到的,当使用带有 Strongbox 的 AES-GCM 时,会产生可预测的伪造密文。如果 Cipher 初始化和使用之间存在延迟,这似乎会发生,但该错误的确切原因尚不清楚,因为它存在于 Titan M 芯片的固件中。

在 2019 年 12 月的 Android 安全更新中针对 Pixel 3 及更高版本进行了修复。我写了一篇更深入的文章:https://alexbakker.me/post/mysterious-google-titan-m-bug-cve-2019-9465.html

【讨论】:

    猜你喜欢
    • 2015-03-29
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-03
    • 2018-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多