Android 密钥库的使用

信息安全 安卓 密钥管理 tpm
2021-08-30 10:10:08

我正在使用 Android Keystore 存储非对称加密(解密包含非对称密钥的文件)。我这样做是因为我想加密大量数据并且非对称是不够的,因为他们的密钥库自 SDK 23 以来就具有对称密钥。

  • 在经典 HSM 中,您无法访问加密密钥,您只能发送数据,而 HSM 会执行加密操作。但在 Android 中,您从密钥库中检索密钥以手动执行操作(使用密码等)。安全吗?
  • 如果不安全,是否可以在使用后从内存中擦除密钥?(例如,在我的功能结束时)
  • 如果安全,有什么风险?RAM被病毒破坏了吗?
4个回答

让我们看一下 Android 开发者文档“Android 密钥库系统”我们需要根据您使用KeyStore对象的方式对其进行分解如果您使用的是 Android KeyStore KeyStore.getInstance("AndroidKeyStore"),则:

1) 如果运行应用程序的设备具有硬件支持的安全存储,则

密钥材料可以绑定到 Android 设备的安全硬件(例如,可信执行环境 (TEE)、安全元件 (SE))。为密钥启用此功能后,其密钥材料永远不会暴露在安全硬件之外。

Android 密钥库系统”文章提供了有关如何使用此功能的更多信息。

2) 如果设备没有硬件支持的安全存储,则:

密钥材料永远不会进入申请流程。当应用程序使用 Android Keystore 密钥执行加密操作时,在后台将要签名或验证的明文、密文和消息馈送到执行加密操作的系统进程。

大概这个系统进程是用 C 语言编写的,它们对内存管理有更多的控制权,并且当它超出您的应用程序的范围时可以正确地将密钥归零(这导致我对垃圾收集器的咆哮......)

3)如果由于某种原因您在此处KeyStore.getInstance("JKS")的示例中使用-也许您出于某种原因需要访问私钥,或者您需要将私钥加载/存储在文件中-那么不,您不能擦除它:因为Java 垃圾收集器以在不清除或归零的情况下将内存返回给操作系统而闻名Android 开发人员文档中,我没有看到任何证据表明 Dalvik 垃圾收集器的工作方式有任何不同。.jks

此外,Java 垃圾收集器的机制之一是复制程序当前引用的任何堆变量,然后释放旧堆。这意味着即使在超出范围之前,您的私钥副本也可能被释放回操作系统。


底线:如果正确使用 Android KeyStore 对象,您的私钥将安全地保留在可信执行环境 (TEE)、安全元件 (SE) 或系统进程中。

如果出于某种原因您确实将私钥带入了您的应用程序,那么所有的赌注都将失败,因为在 Java / Dalvik / Android 中,一旦有东西在您的应用程序的内存中,几乎不可能清除或清零它。

其他答案很好地涵盖了所有内容,但似乎有一个方面被误解了。正如引用的其他答案一样,...

密钥材料永远不会进入申请流程。当应用程序使用 Android Keystore 密钥执行加密操作时,在后台将要签名或验证的明文、密文和消息馈送到执行加密操作的系统进程。

这意味着 Android 应用程序无法通过任何支持的方式检索密钥的任何字节。Key.getEncoded()这种强制执行是可能的,因为 Android(和 Java)可以通过接口中的单个方法访问原始密钥材料Key对于由 Android 密钥库管理的密钥,Key.getEncoded()返回null.

如果您确实需要将密钥数据导入 AndroidKeyStore(例如,您需要对其执行一些密钥存储不支持的操作),那么如何确保它不会保留在应用程序内存中并不是很明显。但是,我自己一直在玩弄这个,如果您执行以下操作,您似乎很安全:

  • 确保您的关键数据只存储在一个byte[]或类似的(而不是一个String或其他可能复制其数据的对象)中。
  • 实现您自己的 *KeySpec 类,它不会复制任何数据(默认的会这样做,并且没有直接的方法来清除复制的数据,因为它是私有的)
  • byte[]将密钥数据放入密钥库后立即覆盖它。
  • 关键位:立即使用零或垃圾数据将另一个虚拟条目存储在密钥库中。这似乎是消除通过 RPC 将数据发送到密钥库服务时生成的副本的唯一方法。

希望这可以帮助。

在 Android 中,您从 Keystore 检索密钥以手动执行操作。安全吗?

来自 Android 文档:

密钥材料永远不会进入申请流程。当应用程序使用 Android Keystore 密钥执行加密操作时,将在后台将要签名或验证的明文、密文和消息馈送到执行加密操作的系统进程。 https://developer.android.com/training/articles/keystore.html

因此,当您手动使用 Cipher 类并检索您的密钥时,这实际上是在系统进程中完成的,而不是您的应用程序。您是正确的,因为您可以根据需要回显密钥(这将是不安全的),但简单地扫描您的应用程序(或它使用的内存)不会产生密钥。

如果不安全,是否可以在使用后从内存中擦除密钥?

没必要。执行操作的系统进程会为您执行此操作。

如果安全,有什么风险?RAM被病毒破坏了吗?

真正不安全的情况是,如果设备没有安全元素,则可以读取 KeyStore。

来自 Android 文档:

如果 Android 操作系统遭到入侵或攻击者可以读取设备的内部存储,则攻击者可能能够在 Android 设备上使用任何应用程序的 Android Keystore 密钥,但无法从设备中提取它们。 https://developer.android.com/training/articles/keystore.html