Most visited

Recently visited

Added in API level 23

KeyProtection

public final class KeyProtection
extends Object implements KeyStore.ProtectionParameter

java.lang.Object
   ↳ android.security.keystore.KeyProtection


指定将密钥或密钥对导入Android Keystore system时的安全方式 该类指定了导入密钥的授权使用,例如使用密钥是否需要用户验证,密钥被授权(例如,解密,但不签名)哪些操作(使用什么参数)(例如,仅使用特定填充方案或摘要)以及密钥的有效开始和结束日期。 此类中表示的密钥使用授权仅适用于密钥和私钥 - 公钥可用于任何支持的操作。

要将密钥或密钥对导入Android Keystore,请使用 KeyProtection.Builder创建此类的实例,并将该实例传递到 KeyStore.setEntry ,同时导入密钥或密钥对。

要从Android密钥库中获取密钥/对称密钥或私钥,请使用KeyStore.getKey(String, null)KeyStore.getEntry(String, null) 要从Android密钥库获取公钥,请使用getCertificate(String) ,然后使用getPublicKey()

为了帮助获取存储在Android密钥库密钥对的具体算法,公共参数,其私钥,实现 ECKey或者 RSAKey接口,而它的公共密钥实现 ECPublicKey或者 RSAPublicKey接口。

注:存储在Android密钥库中的密钥的密钥材料不可访问。

这个类的实例是不可变的。

Known issues

A known bug in Android 6.0 (API Level 23) causes user authentication-related authorizations to be enforced even for public keys. To work around this issue extract the public key material to use outside of Android Keystore. For example:
 PublicKey unrestrictedPublicKey =
         KeyFactory.getInstance(publicKey.getAlgorithm()).generatePublic(
                 new X509EncodedKeySpec(publicKey.getEncoded()));
 

Example: AES key for encryption/decryption in GCM mode

This example illustrates how to import an AES key into the Android KeyStore under alias key1 authorized to be used only for encryption/decryption in GCM mode with no padding. The key must export its key material via getEncoded() in RAW format.
 SecretKey key = ...; // AES key

 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 keyStore.load(null);
 keyStore.setEntry(
         "key1",
         new KeyStore.SecretKeyEntry(key),
         new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                 .setBlockMode(KeyProperties.BLOCK_MODE_GCM)
                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                 .build());
 // Key imported, obtain a reference to it.
 SecretKey keyStoreKey = (SecretKey) keyStore.getKey("key1", null);
 // The original key can now be discarded.

 Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
 cipher.init(Cipher.ENCRYPT_MODE, keyStoreKey);
 ...
 

Example: HMAC key for generating MACs using SHA-512

This example illustrates how to import an HMAC key into the Android KeyStore under alias key1 authorized to be used only for generating MACs using SHA-512 digest. The key must export its key material via getEncoded() in RAW format.
 SecretKey key = ...; // HMAC key of algorithm "HmacSHA512".

 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 keyStore.load(null);
 keyStore.setEntry(
         "key1",
         new KeyStore.SecretKeyEntry(key),
         new KeyProtection.Builder(KeyProperties.PURPOSE_SIGN).build());
 // Key imported, obtain a reference to it.
 SecretKey keyStoreKey = (SecretKey) keyStore.getKey("key1", null);
 // The original key can now be discarded.

 Mac mac = Mac.getInstance("HmacSHA512");
 mac.init(keyStoreKey);
 ...
 

Example: EC key pair for signing/verification using ECDSA

This example illustrates how to import an EC key pair into the Android KeyStore under alias key2 with the private key authorized to be used only for signing with SHA-256 or SHA-512 digests. The use of the public key is unrestricted. Both the private and the public key must export their key material via getEncoded() in PKCS#8 and X.509 format respectively.
 PrivateKey privateKey = ...;   // EC private key
 Certificate[] certChain = ...; // Certificate chain with the first certificate
                                // containing the corresponding EC public key.

 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 keyStore.load(null);
 keyStore.setEntry(
         "key2",
         new KeyStore.PrivateKeyEntry(privateKey, certChain),
         new KeyProtection.Builder(KeyProperties.PURPOSE_SIGN)
                 .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
                 .build());
 // Key pair imported, obtain a reference to it.
 PrivateKey keyStorePrivateKey = (PrivateKey) keyStore.getKey("key2", null);
 PublicKey publicKey = keyStore.getCertificate("key2").getPublicKey();
 // The original private key can now be discarded.

 Signature signature = Signature.getInstance("SHA256withECDSA");
 signature.initSign(keyStorePrivateKey);
 ...
 

Example: RSA key pair for signing/verification using PKCS#1 padding

This example illustrates how to import an RSA key pair into the Android KeyStore under alias key2 with the private key authorized to be used only for signing using the PKCS#1 signature padding scheme with SHA-256 digest and only if the user has been authenticated within the last ten minutes. The use of the public key is unrestricted (see Known Issues). Both the private and the public key must export their key material via getEncoded() in PKCS#8 and X.509 format respectively.
 PrivateKey privateKey = ...;   // RSA private key
 Certificate[] certChain = ...; // Certificate chain with the first certificate
                                // containing the corresponding RSA public key.

 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 keyStore.load(null);
 keyStore.setEntry(
         "key2",
         new KeyStore.PrivateKeyEntry(privateKey, certChain),
         new KeyProtection.Builder(KeyProperties.PURPOSE_SIGN)
                 .setDigests(KeyProperties.DIGEST_SHA256)
                 .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
                 // Only permit this key to be used if the user
                 // authenticated within the last ten minutes.
                 .setUserAuthenticationRequired(true)
                 .setUserAuthenticationValidityDurationSeconds(10 * 60)
                 .build());
 // Key pair imported, obtain a reference to it.
 PrivateKey keyStorePrivateKey = (PrivateKey) keyStore.getKey("key2", null);
 PublicKey publicKey = keyStore.getCertificate("key2").getPublicKey();
 // The original private key can now be discarded.

 Signature signature = Signature.getInstance("SHA256withRSA");
 signature.initSign(keyStorePrivateKey);
 ...
 

Example: RSA key pair for encryption/decryption using PKCS#1 padding

This example illustrates how to import an RSA key pair into the Android KeyStore under alias key2 with the private key authorized to be used only for decryption using the PKCS#1 encryption padding scheme. The use of public key is unrestricted, thus permitting encryption using any padding schemes and digests. Both the private and the public key must export their key material via getEncoded() in PKCS#8 and X.509 format respectively.
 PrivateKey privateKey = ...;   // RSA private key
 Certificate[] certChain = ...; // Certificate chain with the first certificate
                                // containing the corresponding RSA public key.

 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 keyStore.load(null);
 keyStore.setEntry(
         "key2",
         new KeyStore.PrivateKeyEntry(privateKey, certChain),
         new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
                 .build());
 // Key pair imported, obtain a reference to it.
 PrivateKey keyStorePrivateKey = (PrivateKey) keyStore.getKey("key2", null);
 PublicKey publicKey = keyStore.getCertificate("key2").getPublicKey();
 // The original private key can now be discarded.

 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
 cipher.init(Cipher.DECRYPT_MODE, keyStorePrivateKey);
 ...
 

Summary

Nested classes

class KeyProtection.Builder

KeyProtection实例的构建器。

Public methods

String[] getBlockModes()

获取该组块模式(例如, GCMCBC )与该密钥可以加密/解密时使用。

String[] getDigests()

获取一组摘要算法(例如, SHA-256SHA-384 )与该键可被使用。

String[] getEncryptionPaddings()

获取一组填充方案(例如, PKCS7PaddingPKCS1PaddingNoPadding )与该密钥可以加密/解密时使用。

Date getKeyValidityForConsumptionEnd()

获取密钥对于解密和验证无效的时间。

Date getKeyValidityForOriginationEnd()

获取密钥对于加密和签名不再有效的时间。

Date getKeyValidityStart()

获取密钥尚未生效的时刻。

int getPurposes()

获取可以使用密钥的一组目的(例如,加密,解密,签名)。

String[] getSignaturePaddings()

获取一组填充方案(例如, PSSPKCS#1 )与该密钥可以签名/验证时使用。

int getUserAuthenticationValidityDurationSeconds()

获取用户成功通过身份验证后授权使用此密钥的持续时间(秒)。

boolean isDigestsSpecified()

如果指定了可以使用密钥的一组摘要算法,则返回 true

boolean isInvalidatedByBiometricEnrollment()

返回 true如果在注册新的指纹或删除所有登记的指纹时密钥不可逆转地失效。

boolean isRandomizedEncryptionRequired()

返回 true如果使用此密钥的加密必须足够随机化,以便每次为相同的明文生成不同的密文。

boolean isUserAuthenticationRequired()

如果密钥仅在用户已通过身份验证时才有权使用,则返回 true

boolean isUserAuthenticationValidWhileOnBody()

返回 true如果在将设备从用户身体上移除时密钥将被取消授权。

Inherited methods

From class java.lang.Object

Public methods

getBlockModes

Added in API level 23
String[] getBlockModes ()

获取该组块模式(例如, GCMCBC )与该密钥可以加密/解密时使用。 试图在任何其他模块模式下使用密钥将被拒绝。

KeyProperties BLOCK_MODE常量。

Returns
String[]

getDigests

Added in API level 23
String[] getDigests ()

获取一组摘要算法(例如, SHA-256SHA-384 )与该键可被使用。

KeyProperties DIGEST常量。

Returns
String[]
Throws
IllegalStateException if this set has not been specified.

也可以看看:

getEncryptionPaddings

Added in API level 23
String[] getEncryptionPaddings ()

获取一组填充方案(例如, PKCS7PaddingPKCS1PaddingNoPadding )与该密钥可以加密/解密时使用。 尝试将密钥与任何其他填充方案一起使用将被拒绝。

KeyProperties ENCRYPTION_PADDING常量。

Returns
String[]

getKeyValidityForConsumptionEnd

Added in API level 23
Date getKeyValidityForConsumptionEnd ()

获取密钥对于解密和验证无效的时间。

Returns
Date instant or null if not restricted.

getKeyValidityForOriginationEnd

Added in API level 23
Date getKeyValidityForOriginationEnd ()

获取密钥对于加密和签名不再有效的时间。

Returns
Date instant or null if not restricted.

getKeyValidityStart

Added in API level 23
Date getKeyValidityStart ()

获取密钥尚未生效的时刻。

Returns
Date instant or null if not restricted.

getPurposes

Added in API level 23
int getPurposes ()

获取可以使用密钥的一组目的(例如,加密,解密,签名)。 试图将钥匙用于任何其他目的将被拒绝。

KeyProperties PURPOSE标志。

Returns
int

getSignaturePaddings

Added in API level 23
String[] getSignaturePaddings ()

获取一组填充方案(例如, PSSPKCS#1 )与该密钥可以签名/验证时使用。 尝试将密钥与任何其他填充方案一起使用将被拒绝。

KeyProperties SIGNATURE_PADDING常量。

Returns
String[]

getUserAuthenticationValidityDurationSeconds

Added in API level 23
int getUserAuthenticationValidityDurationSeconds ()

获取用户成功通过身份验证后授权使用此密钥的持续时间(秒)。 这仅在需要用户认证时才有效(请参阅isUserAuthenticationRequired() )。

此授权仅适用于密钥和私钥操作。 公钥操作不受限制。

Returns
int duration in seconds or -1 if authentication is required for every use of the key.

也可以看看:

isDigestsSpecified

Added in API level 23
boolean isDigestsSpecified ()

如果指定了可以使用密钥的一组摘要算法,则返回 true

Returns
boolean

也可以看看:

isInvalidatedByBiometricEnrollment

Added in API level 24
boolean isInvalidatedByBiometricEnrollment ()

返回true如果在注册新指纹或删除所有登记指纹时密钥不可逆转地失效。 这只对需要指纹用户验证才能用于每次使用的密钥有效。

Returns
boolean

也可以看看:

isRandomizedEncryptionRequired

Added in API level 23
boolean isRandomizedEncryptionRequired ()

如果使用此密钥的加密必须充分随机化,以便每次为同一明文生成不同的密文,则返回true 所需的正式密码属性在选择明文攻击下不可区分的( IND-CPA 这个属性很重要,因为它可以缓解由于密文泄露明文信息而导致的几类弱点。 例如,如果一个给定的明文总是产生相同的密文,攻击者可能会看到重复的密文,并能够推断出有关明文的信息。

Returns
boolean

isUserAuthenticationRequired

Added in API level 23
boolean isUserAuthenticationRequired ()

如果密钥仅在用户已通过身份验证时才有权使用,则返回 true

此授权仅适用于密钥和私钥操作。 公钥操作不受限制。

Returns
boolean

也可以看看:

isUserAuthenticationValidWhileOnBody

Added in API level 24
boolean isUserAuthenticationValidWhileOnBody ()

返回true如果在将设备从用户身体上移除时密钥将被取消授权。 此选项对没有验证有效期的密钥不起作用,如果设备缺少贴身传感器,则该选项无效。

授权仅适用于密钥和私钥操作。 公钥操作不受限制。

Returns
boolean

也可以看看:

Hooray!