崩溃将AndroidKeyStoreRSAPrivateKey转换为RSAPrivateKey

时间:2015-09-04 14:35:23

标签: java android cryptography java-security android-6.0-marshmallow

我正在关注本教程: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的更好方法?

非常感谢。

3 个答案:

答案 0 :(得分:8)

<强>问题

  1. 我们正在尝试将java.security。 PrivateKey 解析为java.security.interfaces。 RSAPrivateKey &#34; &安培; &#34; java.security。 PublicKey 到java.security.interfaces。 RSAPublicKey &#34;。这就是我们获得ClassCastException的原因。
  2. <强>解决方案

    1. 我们不需要解析密钥,我们可以直接使用&#34; java.security。 PrivateKey &#34; &安培; &#34; java.security的公钥&#34;用于加密&amp;解密。
    2. <强>加密

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

      <强>解密

      KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)entry;
      PrivateKey privateKey = privateKeyEntry.getPrivateKey(); // Don't TypeCast to RSAPrivateKey
      

答案 1 :(得分:5)

我也解决了这个问题(除了上面的@James回答): 在Android 6.0上,您不应该使用&#34; AndroidOpenSSL&#34;对于密码创建,它将失败&#34;需要RSA私钥或公钥&#34;在cipher init进行解密。只需使用Cipher.getInstance(&#34; RSA / ECB / PKCS1Padding&#34;)即可使用。

答案 2 :(得分:-3)

我没有尝试过,但您应该能够将android.security.keystore.AndroidKeyStoreRSAPrivateKey分别投射到以下内容。这些应该是您需要的接口:

  1. 为java.security.PrivateKey
  2. java.security.interfaces.RSAKey