利用 Android 密钥库系统,您可以在容器中存储加密密钥,从而提高从设备中提取密钥的难度。在密钥进入密钥库后,可以将它们用于加密操作,而密钥材料仍不可导出。此外,它提供了密钥使用的时间和方式限制措施,例如要求进行用户身份验证才能使用密钥,或者限制为只能在某些加密模式中使用。如需了解详细信息,请参阅安全功能部分。
密钥库系统由 KeyChain
API 以及在 Android 4.3(API 级别 18)中引入的 Android 密钥库提供程序功能使用。本文说明了何时以及如何使用 Android 密钥库提供程序。
KeyInfo
并检查 KeyInfo.isInsideSecurityHardware()
的返回值。支持的密钥使用授权可归为以下几个类别:
作为一项额外的安全措施,对于密钥材料位于安全硬件内部的密钥(请参阅 KeyInfo.isInsideSecurityHardware()
),某些密钥使用授权可能由安全硬件实施,具体取决于 Android 设备。加密和用户身份验证授权可能由安全硬件实施。由于安全硬件一般不具备独立的安全实时时钟,时间有效性间隔授权不可能由其实施。
您可以使用 KeyInfo.isUserAuthenticationRequirementEnforcedBySecureHardware()
查询密钥的用户身份验证授权是否由安全硬件实施。
在需要系统级凭据时请使用 KeyChain
API。在应用通过 KeyChain
API 请求使用任何凭据时,用户需要通过系统提供的 UI 选择应用可以访问已安装的哪些凭据。因此,在用户同意的情况下多个应用可以使用同一套凭据。
使用 Android 密钥库提供程序让各个应用存储自己的凭据,并且只允许应用自身访问。这样,应用可以管理仅能由自己使用的凭据,同时又可以提供等同于 KeyChain
API 为系统级凭据提供的安全优势。这一方法不需要用户选择凭据。
要使用此功能,请使用标准的 KeyStore
和 KeyPairGenerator
或 KeyGenerator
类,以及在 Android 4.3(API 级别 18)中引入的 AndroidKeyStore
提供程序。
AndroidKeyStore
注册为 KeyStore
类型以用于 KeyStore.getInstance(type)
方法,而在用于 KeyPairGenerator.getInstance(algorithm, provider)
和 KeyGenerator.getInstance(algorithm, provider)
方法时注册为提供程序。
生成新的 PrivateKey
要求您同时指定自签署证书具备的初始 X.509 属性。之后,您可以使用 KeyStore.setKeyEntry
将证书替换为由证书颁发机构 (CA) 签署的证书。
要生成密钥,请使用 KeyPairGenerator
和 KeyPairGeneratorSpec
:
/* * Generate a new EC key pair entry in the Android Keystore by * using the KeyPairGenerator API. The private key can only be * used for signing or verification and only with SHA-256 or * SHA-512 as the message digest. */ KeyPairGenerator kpg = KeyPairGenerator.getInstance( KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore"); kpg.initialize(new KeyGenParameterSpec.Builder( alias, KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512) .build()); KeyPair kp = kpg.generateKeyPair();
要生成密钥,请使用 KeyGenerator
和 KeyGenParameterSpec
。
AndroidKeyStore
提供程序的使用通过所有的标准 KeyStore
API 加以实现。
通过调用 aliases()
方法列出密钥库中的条目:
/* * Load the Android KeyStore instance using the the * "AndroidKeyStore" provider to list out what entries are * currently stored. */ KeyStore ks = KeyStore.getInstance("AndroidKeyStore"); ks.load(null); Enumeration<String> aliases = ks.aliases();
通过从密钥库提取 KeyStore.Entry
并使用 Signature
API(例如 sign()
)签署数据:
/* * Use a PrivateKey in the KeyStore to create a signature over * some data. */ KeyStore ks = KeyStore.getInstance("AndroidKeyStore"); ks.load(null); KeyStore.Entry entry = ks.getEntry(alias, null); if (!(entry instanceof PrivateKeyEntry)) { Log.w(TAG, "Not an instance of a PrivateKeyEntry"); return null; } Signature s = Signature.getInstance("SHA256withECDSA"); s.initSign(((PrivateKeyEntry) entry).getPrivateKey()); s.update(data); byte[] signature = s.sign();
类似地,请使用 verify(byte[])
方法验证数据:
/* * Verify a signature previously made by a PrivateKey in our * KeyStore. This uses the X.509 certificate attached to our * private key in the KeyStore to validate a previously * generated signature. */ KeyStore ks = KeyStore.getInstance("AndroidKeyStore"); ks.load(null); KeyStore.Entry entry = ks.getEntry(alias, null); if (!(entry instanceof PrivateKeyEntry)) { Log.w(TAG, "Not an instance of a PrivateKeyEntry"); return false; } Signature s = Signature.getInstance("SHA256withECDSA"); s.initVerify(((PrivateKeyEntry) entry).getCertificate()); s.update(data); boolean valid = s.verify(signature);
生成密钥或将密钥导入到 AndroidKeyStore
时,您可以指定密钥仅授权给经过身份验证的用户使用。用户使用安全锁定屏幕凭据(模式/PIN/密码、指纹)的子集进行身份验证。
这是一项高级安全功能,通常仅用于有以下要求的情形:在生成/导入密钥后(而不是之前或当中),应用进程受到攻击不会导致密钥被未经身份验证的用户使用。
如果密钥仅授权给经过身份验证的用户使用,可以将其配置为以下列两种模式之一运行:
KeyguardManager.createConfirmDeviceCredentialIntent
流程确认其安全锁定屏幕凭据后,即可使用此模式中的所有密钥。每个密钥的授权持续时间各不相同,并由 setUserAuthenticationValidityDurationSeconds
在密钥生成或导入时指定。此类密钥只能在启用安全锁定屏幕时生成或导入(请参阅 KeyguardManager.isDeviceSecure()
)。在安全锁定屏幕停用(重新配置为“无”、“滑动”或不验证用户身份的其他模式)或被强制重置(例如由设备管理员执行)时,这些密钥将永久失效。FingerprintManager.authenticate
。此类密钥只能在至少注册一个指纹时生成或导入(请参阅 FingerprintManager.hasEnrolledFingerprints
)。一旦注册新指纹或取消注册所有指纹,这些密钥将永久失效。Cipher
KeyGenerator
KeyFactory
KeyPairGenerator
Mac
Signature
SecretKeyFactory
算法 | 提供支持的 API 级别 | 备注 |
---|---|---|
AES/CBC/NoPadding | 23+ | |
AES/CBC/PKCS7Padding | 23+ | |
AES/CTR/NoPadding | 23+ | |
AES/ECB/NoPadding | 23+ | |
AES/ECB/PKCS7Padding | 23+ | |
AES/GCM/NoPadding | 23+ | 仅支持 12 字节长的 IV。 |
RSA/ECB/NoPadding | 18+ | |
RSA/ECB/PKCS1Padding | 18+ | |
RSA/ECB/OAEPWithSHA-1AndMGF1Padding | 23+ | |
RSA/ECB/OAEPWithSHA-224AndMGF1Padding | 23+ | |
RSA/ECB/OAEPWithSHA-256AndMGF1Padding | 23+ | |
RSA/ECB/OAEPWithSHA-384AndMGF1Padding | 23+ | |
RSA/ECB/OAEPWithSHA-512AndMGF1Padding | 23+ | |
RSA/ECB/OAEPPadding | 23+ |
算法 | 提供支持的 API 级别 | 备注 |
---|---|---|
AES | 23+ | 支持的大小:128、192、256 |
HmacSHA1 | 23+ |
|
HmacSHA224 | 23+ |
|
HmacSHA256 | 23+ |
|
HmacSHA384 | 23+ |
|
HmacSHA512 | 23+ |
|
算法 | 提供支持的 API 级别 | 备注 |
---|---|---|
EC | 23+ | 支持的密钥规范:KeyInfo (仅私钥)、ECPublicKeySpec (仅公钥)、X509EncodedKeySpec (仅公钥) |
RSA | 23+ | 支持的密钥规范:KeyInfo (仅私钥)、RSAPublicKeySpec (仅公钥)、X509EncodedKeySpec (仅公钥) |
KeyPairGenerator
和
KeyGenerator
支持的相同。
算法 | 提供支持的 API 级别 | 备注 |
---|---|---|
DSA | 19–22 | |
EC | 23+ |
在 API 级别 23 前,EC 密钥可使用经 "RSA" 算法初始化的 |
RSA | 18+ |
|
算法 | 提供支持的 API 级别 | 备注 |
---|---|---|
HmacSHA1 | 23+ | |
HmacSHA224 | 23+ | |
HmacSHA256 | 23+ | |
HmacSHA384 | 23+ | |
HmacSHA512 | 23+ |
算法 | 提供支持的 API 级别 | 备注 |
---|---|---|
MD5withRSA | 18+ | |
NONEwithECDSA | 23+ | |
NONEwithRSA | 18+ | |
SHA1withDSA | 19–22 | |
SHA1withECDSA | 19+ | |
SHA1withRSA | 18+ | |
SHA1withRSA/PSS | 23+ | |
SHA224withDSA | 20–22 | |
SHA224withECDSA | 20+ | |
SHA224withRSA | 20+ | |
SHA224withRSA/PSS | 23+ | |
SHA256withDSA | 19–22 | |
SHA256withECDSA | 19+ | |
SHA256withRSA | 18+ | |
SHA256withRSA/PSS | 23+ | |
SHA384withDSA | 19–22 | |
SHA384withECDSA | 19+ | |
SHA384withRSA | 18+ | |
SHA384withRSA/PSS | 23+ | |
SHA512withDSA | 19–22 | |
SHA512withECDSA | 19+ | |
SHA512withRSA | 18+ | |
SHA512withRSA/PSS | 23+ |
算法 | 提供支持的 API 级别 | 备注 |
---|---|---|
AES | 23+ | 支持的密钥规范:KeyInfo |
HmacSHA1 | 23+ | 支持的密钥规范:KeyInfo |
HmacSHA224 | 23+ | 支持的密钥规范:KeyInfo |
HmacSHA256 | 23+ | 支持的密钥规范:KeyInfo |
HmacSHA384 | 23+ | 支持的密钥规范:KeyInfo |
HmacSHA512 | 23+ | 支持的密钥规范:KeyInfo |