Java 将AndroidKeyStoreRSAPrivateKey强制转换为RSAPrivateKey

Java 将AndroidKeyStoreRSAPrivateKey强制转换为RSAPrivateKey,java,android,cryptography,java-security,android-6.0-marshmallow,Java,Android,Cryptography,Java Security,Android 6.0 Marshmallow,我将遵循以下教程:。它(松散地)与Google示例应用程序相关联: 我可以使用公钥加密我的数据,并且可以在运行棒棒糖的设备上解密。但是,我有一个运行棉花糖的Nexus 6,出现以下错误: java.lang.RuntimeException: Unable to create application com.android.test: java.lang.ClassCastException: android.security.keystore.AndroidKeyStoreRSAPrivate

我将遵循以下教程:。它(松散地)与Google示例应用程序相关联:

我可以使用公钥加密我的数据,并且可以在运行棒棒糖的设备上解密。但是,我有一个运行棉花糖的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);
我不愿意把这归因于安卓m的古怪之处,因为我看不出java加密库会发生变化的原因。如果M版本出现,我们的应用程序立即在M上崩溃,我会有大麻烦

我做错了什么?错误明确地说您不能强制转换到RSAPrivateKey,那么有人知道从条目中获取RSAPrivateKey的更好方法吗


非常感谢。

我还没有尝试过,但您应该能够将android.security.keystore.AndroidKeyStoreRSAPrivateKey单独转换为以下内容。这些应该是您需要的接口:

  • java.security.PrivateKey
  • java.security.interfaces.RSAKey

  • 我通过从Cipher.getInstance和not转换到RSAprivateKey中删除提供程序,成功地实现了这一点

    KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) entry;
    
    Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());
    
    我不是100%,但我认为原因在于棉花糖从OpenSSL到BoringSSL的变化。


    无论如何,上述方法适用于M及以下级别。

    我通过以下方法解决了此问题(除了上面的@James answer): 在安卓6.0上,您不应该使用“AndroidOpenSSL”创建密码,它将在密码初始化处使用“需要RSA私钥或公钥”进行解密而失败。只需使用Cipher.getInstance(“RSA/ECB/PKCS1Padding”)就可以了。

    问题

  • 我们正在尝试将“java.security.PrivateKey解析为java.security.interfaces.RSAPrivateKey”和“java.security.PublicKey解析为java.security.interfaces.RSAPrivateKey”。这就是为什么我们得到ClassCastException
  • 解决方案

    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
    
  • 我们不需要解析密钥,我们可以直接使用“java.security.PrivateKey”和“java.security.PublicKey”进行加密和解密
  • 加密

    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
    
    解密

    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
    

    现在在AOSP上打开:。此解决方案对棒棒糖有效。但在棉花糖上它抛出:java.security.InvalidKeyException:需要RSA私有还是公共key@resp78在安卓6.0上,您不应该使用“AndroidOpenSSL”创建密码,它将在密码初始化处使用“需要RSA私钥或公钥”进行解密而失败。只需使用Cipher.getInstance(“RSA/ECB/PKCS1Padding”)就可以了。适用于棉花糖和Android N preview 5。谢谢。您的解决方案不足以防止它在Andr 6上崩溃。我尝试了它,做了更多的事情设置encryptPadding:setEncryptionPaddings(KeyProperties.ENCRYPTION\u PADDING\u RSA\u PKCS1)替换为ENCRYPTION\u PADDING\u NONE,然后它就工作了。您应该使用什么提供程序?给出异常消息:需要RSA私钥或公钥。