如果我在Android 9上运行此代码,则会收到以下异常:
private static KeyStore.PrivateKeyEntry getPrivateKeyEntry(String alias) {
try {
KeyStore ks = KeyStore
.getInstance(SecurityConstants.KEYSTORE_PROVIDER_ANDROID_KEYSTORE);
ks.load(null);
KeyStore.Entry entry = ks.getEntry(alias, null);
if (entry == null) {
Log.w(TAG, "No key found under alias: " + alias);
Log.w(TAG, "Exiting signData()...");
return null;
}
if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
Log.w(TAG, "Not an instance of a PrivateKeyEntry");
Log.w(TAG, "Exiting signData()...");
return null;
}
return (KeyStore.PrivateKeyEntry) entry;
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
return null;
}
}
例外:
KeyStore异常 android.os.ServiceSpecificException :(代码7) 在android.os.Parcel.createException(Parcel.java:1956) 在android.os.Parcel.readException(Parcel.java:1910) 在android.os.Parcel.readException(Parcel.java:1860) 在android.security.IKeystoreService $ Stub $ Proxy.get(IKeystoreService.java:786) 在android.security.KeyStore.get(KeyStore.java:195) 在android.security.keystore.AndroidKeyStoreSpi.engineGetCertificateChain(AndroidKeyStoreSpi.java:118) 在java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:484) 在java.security.KeyStore.getEntry(KeyStore.java:1560) 在com.phenodev.testenc.KeyStoreHelper.getPrivateKeyEntry(KeyStoreHelper.java:151) 在com.phenodev.testenc.KeyStoreHelper.encrypt(KeyStoreHelper.java:173) 在com.phenodev.testenc.KeyStoreEncryptor.encrypt(KeyStoreEncryptor.java:19)
请帮助修复它。
答案 0 :(得分:29)
最后我找到了解决方案。由于Android P (KeyStore.PrivateKeyEntry) keyStore.getEntry("alias", null)
并不是获取私钥的正确方法,因此似乎。
我能够通过这种方式访问私钥/公钥来摆脱此警告
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
PrivateKey privateKey = (PrivateKey) keyStore.getKey("alias", null);
PublicKey publicKey = keyStore.getCertificate("alias").getPublicKey();
答案 1 :(得分:4)
从AndroidKeyStore
检索asymmetricKey时,我遇到了同样的问题
我基于Glass博士答案来获取密钥的解决方案如下:(aliasKey是您的别名字符串)
PublicKey:
val keyStore = KeyStore.getInstance("AndroidKeyStore")
keyStore.load(null)
val asymmetricPublicKey = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
keyStore.getCertificate(aliasKey).publicKey
} else {
val asymmetricKey = keyStore.getEntry(aliasKey, null) as KeyStore.PrivateKeyEntry
asymmetricKey.certificate.publicKey
}
PrivateKey:
val keyStore = KeyStore.getInstance("AndroidKeyStore")
keyStore.load(null)
val asymmetricPrivateKey = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
keyStore.getKey(aliasKey, null) as PrivateKey
} else {
val asymmetricKey = keyStore.getEntry(aliasKey, null) as KeyStore.PrivateKeyEntry
asymmetricKey.privateKey
}
使用此代码,我在装有Android P的模拟器和/或设备中没有警告
答案 2 :(得分:0)
我找到了一种消除警告的解决方案,如果您也可以全部测试,那就太好了。实际上,调用方法的顺序就是问题所在。
val privateKey = keyStore.getKey(alias, null)
val publicKey = if (privateKey != null) keyStore.getCertificate(alias).publicKey else null
if (privateKey != null && publicKey != null) {
KeyPair(publicKey, privateKey as PrivateKey)
}
这是调用方法的正确顺序。
当您这样做时:
val privateKey = keyStore.getKey(alias, null)
val certificate = keyStore.getCertificate(alias)
if (privateKey != null && certificate != null) {
KeyPair(certificate.publicKey, privateKey as PrivateKey)
}
您将收到以下警告(由于keyStore.getCertificate(alias):
KeyStore exception
android.os.ServiceSpecificException: (code 7)
at android.os.Parcel.createException(Parcel.java:2085)
at android.os.Parcel.readException(Parcel.java:2039)
at android.os.Parcel.readException(Parcel.java:1987)
at android.security.keystore.IKeystoreService$Stub$Proxy.get(IKeystoreService.java:978)
at android.security.KeyStore.get(KeyStore.java:236)
at android.security.KeyStore.get(KeyStore.java:225)
at android.security.keystore.AndroidKeyStoreSpi.engineGetCertificate(AndroidKeyStoreSpi.java:160)
at java.security.KeyStore.getCertificate(KeyStore.java:1120)
这意味着没有私钥,您应该首先在 之前创建并存储密钥对,然后再在密钥存储库中进行搜索。
现在有了MatPag的答案,它应该看起来像这样:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val privateKey = keyStore.getKey(alias, null)
val publicKey = if (privateKey != null) keyStore.getCertificate(alias).publicKey else null
return if (privateKey != null && publicKey != null) {
KeyPair(publicKey, privateKey as PrivateKey)
} else {
null
}
} else {
val asymmetricKey = keyStore.getEntry(alias, null) as KeyStore.PrivateKeyEntry
val privateKey = asymmetricKey.privateKey
val publicKey = if(privateKey != null) asymmetricKey.certificate.publicKey else null
return if(privateKey != null && publicKey != null) {
KeyPair(publicKey, privateKey as PrivateKey)
} else {
null
}
}
答案 3 :(得分:-2)
在我的情况下,警告仍然存在,甚至是将密钥作为公认的解决方案,但仅当密钥尚不存在时。
该警告来自getCertificate调用,因此请避免该警告:
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
PrivateKey privateKey = (PrivateKey) keyStore.getKey("alias", null);
PublicKey publicKey = privateKey != null ? keyStore.getCertificate("alias").getPublicKey() : null;