我的 Android 应用程序需要加密一个文件,以便稍后可以解密和读取它。除应用程序之外的任何人(甚至用户)都不能解密。
以下是我进行加密和解密的方法。这在大多数情况下都有效,但有时对于某些用户来说会失败。它并不特定于特定手机(Nexus7、三星、摩托罗拉、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)
- 我究竟做错了什么?
- 我该如何修复/解决它?
- 这些异常是否表明文件被篡改?
- 使用屏幕锁定密码/PIN 码的用户是否会发生这种情况?
- 在生成新对之前,我应该删除该条目吗? (KeyStore.deleteEntry())
我观察到,屏幕锁定密码/PIN 更改后,密钥库返回 null。其他一些人似乎也遇到过这个问题(更改密码后 KeyStore getEntry 返回 null https://stackoverflow.com/questions/22618171/keystore-getentry-return-null-after-change-password)