您可以使用普通的KeyStore 文件或Android KeyStore Provider。
密钥库(API 1)
您必须创建一个 KeyStore 文件,并且您还必须管理访问它的密钥。这个秘密非常敏感,很难对攻击者隐藏。就我个人而言,我更愿意将这一责任委托给 Android 系统,这就是为什么我不选择这个解决方案而不是下一个解决方案的原因。
Android KeyStore 提供程序 (API 18)
使用此 API,您将负责在 Android 上管理文件和机密的所有繁重工作。您不需要使用任何密码,因为操作系统本身会根据您的锁屏 PIN 码、密码、图案和其他变量存储它。
如果设备包含嵌入式安全硬件,则密钥将存储在那里(例如,可信执行环境 (TEE))。您可以检查KeyInfo#isInsideSecureHardware() 方法以查看密钥是否保存在那里。这种硬件机制为我们提供了额外的保护,以防我们的应用运行到受损的 Linux 内核中。
此外,从 Android 9(API 级别 28)开始,StrongBox Keymaster API 被引入用于包含安全芯片的设备(如 Google Pixel 3 上的 Titan M)。如果您在 Android 28 或更高版本上运行,您只需要调用 setIsStrongBoxBacked(boolean) 方法让 Android 知道您想要使用它(如果它在设备上可用)。尽管上述 TEE 解决方案是可接受的,但这种使用安全元件 (SE) 的机制是最安全的,因为它基于为安全目的而设计的不同硬件(CPU、内存、存储等)。
在这里,我们将有一个快速示例,说明如何使用 StrongBox 创建自签名证书和密钥对(如果支持):
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore")
.apply {
val certBuilder = KeyGenParameterSpec.Builder(alias, KeyProperties.PURPOSE_ENCRYPT)
.setKeyValidityStart(keyValidityStart)
.setKeyValidityEnd(keyValidityEnd)
.setCertificateSerialNumber(BigInteger.valueOf(1L))
.setCertificateSubject(X500Principal("CN=MyCompany"))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
initialize(
certBuilder
.setIsStrongBoxBacked(true) /* Enable StrongBox */
.build()
)
} else {
initialize(certBuilder.build())
}
}
.also {
val keyPair = it.generateKeyPair()
...
}
}
关于您的问题:
我们可以从 KeyStore 中提取密钥吗?
使用它们,您的应用程序可以获得PrivateKey 并使用它,如果这是您的意思。
其他应用程序(AppB)能否访问 AppA 生成的密钥?
使用 KeyStore 提供程序解决方案,每个应用程序只能访问其 KeyStore 实例或别名。相反,如果另一个应用程序可以访问该文件,它可能会尝试攻击它,则使用普通的 KeyStore。
在什么情况下我们可能会丢失钥匙?设备只恢复出厂设置?
删除应用程序将删除应用程序的 KeyStore 提供程序实例。但是,由于 Android 的a nasty bug(在 Android 5 之前更常见)如果用户将锁屏图案更改为密码或只是删除图案,KeyStore 将完全损坏。当用户从 Android 设置执行“清除凭据”时,也会发生同样的情况。使用经典的 KeyStore,您可以将其存储在外部存储中,即使在设备恢复出厂设置后也可以保留。但是,如前所述,它仍然不如提供者安全。
我可能在某些方面是错误的,但这是我学到的,我只是分享我的经验。希望这对您有所帮助。