鉴于Android Keystore存在许多已知问题及其丢失数据的能力,或者只是一般会摔倒(请参阅here,here,here,here, here和here)我很想知道是否有任何开发人员在实时应用中实际使用Android Keystore来生成密钥,并且没有遇到与Keystore无法生成相关的大量崩溃报告从Keystore创建或检索密钥?你是如何解决已知问题的?我对使用KeyPairGenerator
类生成不需要用户身份验证的私钥 - 公钥对(即不需要在设备上设置屏幕锁定)的场景特别感兴趣。 / p>
编辑:我在下面列出了我用于通过Android Keystore生成私钥 - 公钥对的代码:
KeyPair createPrivateKeyEntry(@NonNull Context context,
@NonNull String keyAlias) throws CryptoException {
try {
AlgorithmParameterSpec spec = getAlgorithmParameterSpec(context, keyAlias);
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
"RSA",
"AndroidKeyStore"
);
keyPairGenerator.initialize(spec);
return keyPairGenerator.generateKeyPair();
} catch (Exception e) {
String message = "Unexpected error when attempting to create a private key entry.";
throw new CryptoException(message, e);
}
}
private AlgorithmParameterSpec getAlgorithmParameterSpec(@NonNull Context context,
@NonNull String keyAlias) {
int keySize = 2048;
X500Principal subject = new X500Principal("CN=" + keyAlias);
BigInteger serialNumber = BigInteger.valueOf(1337);
Calendar validityStartCalendar = Calendar.getInstance();
Calendar validityEndCalendar = Calendar.getInstance();
validityEndCalendar.add(Calendar.YEAR, 99);
Date validityStartDate = validityStartCalendar.getTime();
Date validityEndDate = validityEndCalendar.getTime();
AlgorithmParameterSpec spec;
if (Build.VERSION.SDK_INT >= 23) {
spec = new KeyGenParameterSpec.Builder(keyAlias, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setKeySize(keySize)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
.setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
.setCertificateSubject(subject)
.setCertificateSerialNumber(serialNumber)
.setKeyValidityStart(validityStartDate)
.setKeyValidityEnd(validityEndDate)
.setUserAuthenticationRequired(false)
.build();
} else {
spec = new KeyPairGeneratorSpec.Builder(context)
.setAlias(keyAlias)
.setKeySize(keySize)
.setSubject(subject)
.setSerialNumber(serialNumber)
.setStartDate(validityStartDate)
.setEndDate(validityEndDate)
.build();
}
return spec;
}