崩溃将AndroidKeyStoreRSAPrivateKey转换为RSAPrivateKey

Jam*_*mes 41 java android cryptography java-security android-6.0-marshmallow

我正在学习本教程:如何使用Android Keystore存储密码和其他敏感信息.它(松散地)与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
Run Code Online (Sandbox Code Playgroud)

这是它崩溃的代码:

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);
Run Code Online (Sandbox Code Playgroud)

我不愿意把它归结为Android M的奇怪,因为我看不出为什么java加密库会发生变化.如果M版本出现并且我们的应用程序立即在M上崩溃,我将遇到大麻烦.

我做错了什么?错误非常具体地说你不能转换为RSAPrivateKey,所以有谁知道从条目中获取RSAPrivateKey的更好方法?

非常感谢.

Jam*_*mes 57

我设法通过从Cipher.getInstance中删除Provider而不是转换为RSAprivateKey来实现此功能.

KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) entry;

Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding");
output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());
Run Code Online (Sandbox Code Playgroud)

我不是百分之百,但我认为我相信的原因是从OpenSSL到BoringSSL的棉花糖的变化. https://developer.android.com/preview/behavior-changes.html#behavior-apache-http-client

无论如何,以上工作适用于M及以下.

  • @ resp78在Android 6.0上你不应该使用"AndroidOpenSSL"进行密码创建,它会在cipher init中以"需要RSA私钥或公钥"失败进行解密.只需使用Cipher.getInstance("RSA/ECB/PKCS1Padding")即可. (4认同)
  • 现在在AOSP上打开:[问题205450:崩溃将AndroidKeyStoreRSAPrivateKey转换为RSAPrivateKey](https://code.google.com/p/android/issues/detail?id=205450). (3认同)
  • 这个解决方案适用于棒棒糖.但是在marshmallow上会抛出:java.security.InvalidKeyException:需要RSA私钥或公钥 (2认同)

Vas*_*nth 10

问题

  1. 我们正试图解析"java.security.专用密钥对java.security.interfaces中.RSAPrivateKey " & "java.security.公钥到java.security.interfaces中.RSAPublicKey ".这就是我们得到ClassCastException的原因.

  1. 我们并不需要解析的关键,我们可以直接使用"java.security.专用密钥 "和"java.security.公钥 "加密与解密.

加密

KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)entry; 
PublicKey publicKey = privateKeyEntry.getCertificate().getPublicKey(); // Don't TypeCast to RSAPublicKey
Run Code Online (Sandbox Code Playgroud)

解密

KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)entry;
PrivateKey privateKey = privateKeyEntry.getPrivateKey(); // Don't TypeCast to RSAPrivateKey
Run Code Online (Sandbox Code Playgroud)

  • 消息带来异常:需要RSA私钥或公钥. (4认同)

Sid*_*Sid 5

我也解决了这个问题(除了上面的@James回答):在Android 6.0上你不应该使用"AndroidOpenSSL"进行密码创建,它会在cipher init中使用"需要RSA私钥或公钥"来解密.只需使用Cipher.getInstance("RSA/ECB/PKCS1Padding")即可.