我正在关注本教程:How to use the Android Keystore to store passwords and other sensitive information。它(宽松地)与Google Sample应用:BasicAndroidKeyStore联系在一起。
我可以使用公钥加密数据,也可以在运行Lollipop的设备上解密。但是我有一个运行棉花糖的Nexus 6,它崩溃了,并显示错误消息:
java.lang.RuntimeException: Unable to create application com.android.test: java.lang.ClassCastException: android.security.keystore.AndroidKeyStoreRSAPrivateKey cannot be cast to java.security.interfaces.RSAPrivateKey
这是它崩溃的代码:
KeyStore.Entry entry;
//Get Android KeyStore
ks = KeyStore.getInstance(KeystoreHelper.KEYSTORE_PROVIDER_ANDROID_KEYSTORE);
// Weird artifact of Java API. If you don't have an InputStream to load, you still need to call "load", or it'll crash.
ks.load(null);
// Load the key pair from the Android Key Store
entry = ks.getEntry(mAlias, null);
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) entry;
//ERROR OCCURS HERE::
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey();
Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
output.init(Cipher.DECRYPT_MODE, rsaPrivateKey);
我不愿意将此归结为Android M怪异之处,因为我认为没有理由更改Java加密库。如果M版本发布,并且我们的应用立即在M上崩溃,那么我将陷入大麻烦。
我做错了吗?该错误非常明确地表明您无法强制转换为RSAPrivateKey,所以有人知道从该条目中获取RSAPrivateKey的更好方法吗?
非常感谢。
最佳答案
我设法通过从Cipher.getInstance和而不是转换为RSAprivateKey的Provider中删除了提供程序来实现了这一工作。
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) entry;
Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding");
output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());
我不是100%,但是我认为这样做的原因是棉花糖从OpenSSL更改为BoringSSL。
https://developer.android.com/preview/behavior-changes.html#behavior-apache-http-client
无论如何,以上适用于M及以下。