【发布时间】: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