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密钥库中的密钥的密钥材料不可访问。
这个类的实例是不可变的。
PublicKey unrestrictedPublicKey =
KeyFactory.getInstance(publicKey.getAlgorithm()).generatePublic(
new X509EncodedKeySpec(publicKey.getEncoded()));
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);
...
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);
...
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);
...
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);
...
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);
...
Nested classes |
|
---|---|
class |
KeyProtection.Builder |
Public methods |
|
---|---|
String[] |
getBlockModes() 获取该组块模式(例如, |
String[] |
getDigests() 获取一组摘要算法(例如, |
String[] |
getEncryptionPaddings() 获取一组填充方案(例如, |
Date |
getKeyValidityForConsumptionEnd() 获取密钥对于解密和验证无效的时间。 |
Date |
getKeyValidityForOriginationEnd() 获取密钥对于加密和签名不再有效的时间。 |
Date |
getKeyValidityStart() 获取密钥尚未生效的时刻。 |
int |
getPurposes() 获取可以使用密钥的一组目的(例如,加密,解密,签名)。 |
String[] |
getSignaturePaddings() 获取一组填充方案(例如, |
int |
getUserAuthenticationValidityDurationSeconds() 获取用户成功通过身份验证后授权使用此密钥的持续时间(秒)。 |
boolean |
isDigestsSpecified() 如果指定了可以使用密钥的一组摘要算法,则返回 |
boolean |
isInvalidatedByBiometricEnrollment() 返回 |
boolean |
isRandomizedEncryptionRequired() 返回 |
boolean |
isUserAuthenticationRequired() 如果密钥仅在用户已通过身份验证时才有权使用,则返回 |
boolean |
isUserAuthenticationValidWhileOnBody() 返回 |
Inherited methods |
|
---|---|
From class java.lang.Object
|
String[] getBlockModes ()
获取该组块模式(例如, GCM
, CBC
)与该密钥可以加密/解密时使用。 试图在任何其他模块模式下使用密钥将被拒绝。
见KeyProperties
。 BLOCK_MODE
常量。
Returns | |
---|---|
String[] |
String[] getDigests ()
获取一组摘要算法(例如, SHA-256
, SHA-384
)与该键可被使用。
见KeyProperties
。 DIGEST
常量。
Returns | |
---|---|
String[] |
Throws | |
---|---|
IllegalStateException |
if this set has not been specified. |
也可以看看:
String[] getEncryptionPaddings ()
获取一组填充方案(例如, PKCS7Padding
, PKCS1Padding
, NoPadding
)与该密钥可以加密/解密时使用。 尝试将密钥与任何其他填充方案一起使用将被拒绝。
见KeyProperties
。 ENCRYPTION_PADDING
常量。
Returns | |
---|---|
String[] |
Date getKeyValidityForConsumptionEnd ()
获取密钥对于解密和验证无效的时间。
Returns | |
---|---|
Date |
instant or null if not restricted. |
Date getKeyValidityForOriginationEnd ()
获取密钥对于加密和签名不再有效的时间。
Returns | |
---|---|
Date |
instant or null if not restricted. |
Date getKeyValidityStart ()
获取密钥尚未生效的时刻。
Returns | |
---|---|
Date |
instant or null if not restricted. |
int getPurposes ()
获取可以使用密钥的一组目的(例如,加密,解密,签名)。 试图将钥匙用于任何其他目的将被拒绝。
见KeyProperties
。 PURPOSE
标志。
Returns | |
---|---|
int |
String[] getSignaturePaddings ()
获取一组填充方案(例如, PSS
, PKCS#1
)与该密钥可以签名/验证时使用。 尝试将密钥与任何其他填充方案一起使用将被拒绝。
见KeyProperties
。 SIGNATURE_PADDING
常量。
Returns | |
---|---|
String[] |
int getUserAuthenticationValidityDurationSeconds ()
获取用户成功通过身份验证后授权使用此密钥的持续时间(秒)。 这仅在需要用户认证时才有效(请参阅isUserAuthenticationRequired()
)。
此授权仅适用于密钥和私钥操作。 公钥操作不受限制。
Returns | |
---|---|
int |
duration in seconds or -1 if authentication is required for every use of the key. |
boolean isDigestsSpecified ()
如果指定了可以使用密钥的一组摘要算法,则返回 true
。
Returns | |
---|---|
boolean |
也可以看看:
boolean isInvalidatedByBiometricEnrollment ()
返回true
如果在注册新指纹或删除所有登记指纹时密钥不可逆转地失效。 这只对需要指纹用户验证才能用于每次使用的密钥有效。
Returns | |
---|---|
boolean |
boolean isRandomizedEncryptionRequired ()
如果使用此密钥的加密必须充分随机化,以便每次为同一明文生成不同的密文,则返回true
。 所需的正式密码属性在选择明文攻击下是不可区分的( IND-CPA
) 。 这个属性很重要,因为它可以缓解由于密文泄露明文信息而导致的几类弱点。 例如,如果一个给定的明文总是产生相同的密文,攻击者可能会看到重复的密文,并能够推断出有关明文的信息。
Returns | |
---|---|
boolean |
boolean isUserAuthenticationRequired ()
如果密钥仅在用户已通过身份验证时才有权使用,则返回 true
。
此授权仅适用于密钥和私钥操作。 公钥操作不受限制。
Returns | |
---|---|
boolean |
boolean isUserAuthenticationValidWhileOnBody ()
返回true
如果在将设备从用户身体上移除时密钥将被取消授权。 此选项对没有验证有效期的密钥不起作用,如果设备缺少贴身传感器,则该选项无效。
授权仅适用于密钥和私钥操作。 公钥操作不受限制。
Returns | |
---|---|
boolean |