Моему Android-приложению нужно зашифровать файл, чтобы он мог расшифровать и прочитать его позже. Это не должно быть расшифровывается любым другим, кроме приложения, даже пользователем.
Вот как я делаю шифрование и дешифрование. Это работает большую часть времени, но несколько раз для некоторых пользователей это не работает. Он не специфичен для конкретного телефона (Nexus7, Samsung, Motorola, HTC - все типы сообщают об этой проблеме), но не все пользователи испытывают это. Только некоторые пользователи иногда.
Вот соответствующий код:
encrypt() {
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
final KeyStore.PrivateKeyEntry entry;
if (!ks.containsAlias(CERT_ALIAS)) {
Calendar cal = Calendar.getInstance();
Date now = cal.getTime();
cal.add(Calendar.YEAR, 50);
Date end = cal.getTime();
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
kpg.initialize(new KeyPairGeneratorSpec.Builder(getApplicationContext())
.setAlias(CERT_ALIAS)
.setStartDate(now)
.setEndDate(end)
.setSerialNumber(BigInteger.valueOf(1))
.setSubject(new X500Principal("CN=" + CERT_ALIAS))
.build());
KeyPair kp = kpg.generateKeyPair();
}
entry = (KeyStore.PrivateKeyEntry) ks.getEntry(
CERT_ALIAS, null);
pub = entry.getCertificate().getPublicKey();
// use the pub key to encrypt
}
decrypt() {
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
final KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) ks.getEntry(
CERT_ALIAS, null);
PrivateKey key1 = entry.getPrivateKey();
// use the private key decrypt
}
Этот код иногда бросает
java.lang.RuntimeException: error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long
at com.android.org.conscrypt.NativeCrypto.ENGINE_load_private_key(Native Method)
at com.android.org.conscrypt.OpenSSLEngine.getPrivateKeyById(OpenSSLEngine.java:66)
at android.security.AndroidKeyStore.engineGetKey(AndroidKeyStore.java:86)
at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:372)
at java.security.KeyStore.getEntry(KeyStore.java:644)
Итак, я модифицировал encrypt(), чтобы сначала попытаться получить запись, и если она вызывает исключение, создайте новую пару ключей.
final KeyStore.PrivateKeyEntry entry = null;
if (ks.containsAlias(CERT_ALIAS)) {
try {
entry = (KeyStore.PrivateKeyEntry) ks.getEntry(
CERT_ALIAS, null);
} catch (Exception e) {
}
}
if (entry == null) {
//generate new key pair
}
Но даже это иногда не срабатывает со следующим исключением.
java.lang.IllegalStateException: could not generate key in keystore
at android.security.AndroidKeyPairGenerator.generateKeyPair(AndroidKeyPairGenerator.java:100)
at java.security.KeyPairGenerator$KeyPairGeneratorImpl.generateKeyPair(KeyPairGenerator.java:275)
- Что я делаю неправильно?
- Как мне его исправить/обойти?
- Указывает ли эти исключения, что файлы подделываются?
- Это случается для пользователей с паролем/штифтом для блокировки экрана?
- Прежде чем я создам новую пару, должен ли я удалить запись? (KeyStore.deleteEntry())
Я заметил, что хранилище ключей возвращает значение null после изменения пароля/смены блокировки. Некоторые другие также, похоже, столкнулись с этой проблемой (KeyStore getEntry возвращает null после смены пароля)