【问题标题】:Can we extract public/private keys from the Android Keystore?我们可以从 Android Keystore 中提取公钥/私钥吗?
【发布时间】:2018-09-24 12:04:01
【问题描述】:

关于Android Keystore system的文章,

密钥材料永远不会进入申请流程。当应用程序使用 Android Keystore 密钥执行加密操作时,在后台将要签名或验证的明文、密文和消息馈送到执行加密操作的系统进程。如果应用程序的进程受到攻击,攻击者可能能够使用应用程序的密钥,但无法提取其密钥材料(例如,在 Android 设备之外使用)

所以,我的问题是为什么在BasicAndroidKeyStore,开发人员能够get the KeyPair object 然后print its public/private keys

如果开发人员可以访问密钥,那么如何认为该系统是安全的?它不是。如果攻击者破坏了应用程序进程,他可以轻松检索 kays 并在设备外部使用。

【问题讨论】:

  • 无法提取密钥仅在设备支持密钥库的“硬件安全”的情况下才有效(大多数设备都支持)。否则,您可以使用 root 权限(root 设备或 root 漏洞)访问 AndroidKeyStore。

标签: android android-keystore


【解决方案1】:

您从 BasicAndroidKeyStore 指向的 example code 不会将公钥记录为 KeyPair 类中的 getPublic() 仅返回对公钥对象的引用,而不是公钥本身。

Log.d(TAG, "Public Key reference is: " + kp.getPublic().toString());

日志:

D/KeyStoreFragment:公钥参考为:android.security.keystore.AndroidKeyStoreRSAPublicKey@b8004e8f

getPrivate() 也是如此。

Log.d(TAG, "Private Key reference is: " + kp.getPrivate().toString());

日志:

D/KeyStoreFragment:私钥参考是 android.security.keystore.AndroidKeyStoreRSAPrivateKey@5da42c27


现在,正如您在评论中指出的那样,kp.getPublic().getEncoded() 将返回实际的公钥,但公钥的原始用途并不意味着保密。

私钥是保密的,当使用硬件支持的密钥库和设备的安全硬件支持的密钥时,密钥安全地存储在 TEE/SE 中,不能由应用程序本身或其他错误提取具有root权限的演员。你可以在这个例子中看到它:

Log.d(TAG, "Private Key is " + Arrays.toString(kp.getPrivate().getEncoded()));

日志:

D/KeyStoreFragment:私钥为空


要验证您的设备的安全硬件是否支持您的密钥,您可以使用此代码的一些变体来满足您的需求。您可以在示例应用的 createKeys() 方法中将这个 sn-p 粘贴到上面提到的 Log.d 之后。

    KeyFactory factory = KeyFactory.getInstance(kp.getPrivate().getAlgorithm(), "AndroidKeyStore");
    KeyInfo keyInfo = null;
    try {
        keyInfo = factory.getKeySpec(kp.getPrivate(), KeyInfo.class);
    } catch (InvalidKeySpecException e) {
        e.printStackTrace();
    }
    if (keyInfo.isInsideSecureHardware())
        Log.d(TAG, "Key is supported in secure hardware");
    else
        Log.d(TAG, "Key is not supported in secure hardware");

【讨论】:

  • kp.getPublic().getEncoded() 呢?它返回键的字节数组。
  • @嗨,我是 Frogatto:这是公钥。根据定义,它必须是可导出的,因为它是公开的。
  • @Steve Miskovetz:您的代码示例 kp.getPublic().toString() 导致混淆 - 您应该将其更改为 getPrivate()
  • @Robert 是的。 kp.getPrivate().getEncoded() 返回 null。似乎使用 AndroidKeyStore 可以导出公钥(顾名思义),但私钥安全地保存在硬件中。
  • 感谢你们两位的cmets。我重构了我的答案,以便更清楚地区分 getPublic() 和 getPrivate() 以及涉及 getEncoded()。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-31
  • 1970-01-01
  • 2012-03-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多