dug*_*ous 5 android android-keystore
我在 AndroidKeyStore 中有一个公钥/私钥对,生成如下:
val spec = KeyGenParameterSpec.Builder(alias(username), KeyProperties.PURPOSE_DECRYPT or KeyProperties.PURPOSE_ENCRYPT)
.setKeySize(keySize)
.setUserAuthenticationRequired(true)
.setBlockModes(ablockMode)
.setEncryptionPaddings(apaddingMode)
.setCertificateSubject(X500Principal("CN=Itsami Mario, OU=Adventure Unit, O=Plumber Bros, C=US"))
.setKeyValidityStart(Date())
.setKeyValidityEnd(Date(Date().time + 1000 * 60 * 60 * 24 * 7))
.setCertificateSerialNumber(BigInteger(64, SecureRandom()))
.setDigests(digest)
.build()
keyPairGen.initialize(spec)
return keyPairGen.genKeyPair()
Run Code Online (Sandbox Code Playgroud)
我希望每次使用私钥时都需要生物识别身份验证,但我不想在使用公钥加密时要求生物识别提示。但是,当我在 KeyGenerator 中使用setUserAuthenticationRequired(true),然后在不首先显示 BiometricPrompt 的情况下尝试加密时,我收到一条android.security.KeyStoreException消息:Key user not authenticated
如何要求解密验证而不加密加密?
您必须在运行 Android 6 Marshmallow 的设备上进行测试。这是该版本中的一个已知问题,已在 Android 7 中修复。
要解决此问题,您可以提取公钥的编码并PublicKey从中创建一个新对象,如下所示:
PublicKey publicKey = keyPair.getPublicKey();
PublicKey unrestrictedPublicKey =
KeyFactory.getInstance(publicKey.getAlgorithm()).generatePublic(
new X509EncodedKeySpec(publicKey.getEncoded()));
Run Code Online (Sandbox Code Playgroud)
这适用于所有版本。
请注意,还可以创建在解密时需要身份验证但在加密时不需要身份验证的 AES 密钥,这非常酷(AES 比 RSA 快得多)。诀窍是在 AndroidKeyStore 之外生成密钥,然后将其导入两次,一次使用,PURPOSE_ENCRYPT一次使用PURPOSE_DECRYPT,使用两个不同的别名,并在 DECRYPT 版本上指定用户身份验证要求。就像是:
// Note that we do *not* specify "AndroidKeyStore" when we call getInstance()
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey secretKey = keyGen.generateKey();
// This time we do specify "AndroidKeyStore".
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
// Now we import the encryption key, with no authentication requirements.
keyStore.setEntry(
"encrypt_key",
new KeyStore.SecretKeyEntry(secretKey),
new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
.setBlockMode(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build());
// And the decryption key, this time requiring user authentication.
keyStore.setEntry(
"decrypt_key",
new KeyStore.SecretKeyEntry(secretKey),
new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
.setBlockMode(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setUserAuthentication(true)
.build());
Run Code Online (Sandbox Code Playgroud)
现在,您可以随时使用密钥别名“encrypt_key”进行加密,无需用户身份验证,并且可以使用密钥别名“decrypt_key”进行解密,但前提是您执行该操作BiometricPrompt。
这样做的缺点是秘密会短暂存在于非安全内存中。实际上,只有当攻击者在创建密钥时已经破坏了设备时,这才重要,在这种情况下,您很可能已经丢失了。
| 归档时间: |
|
| 查看次数: |
1276 次 |
| 最近记录: |