web-dev-qa-db-ja.com

AndroidKeyStoreRSAPrivateKeyをRSAPrivateKeyにキャストするとクラッシュする

私はこのチュートリアルに従っています: Androidキーストアを使用してパスワードやその他の機密情報を保存する方法 。これは(大まかに)Googleサンプルアプリと連携します:- 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を取得するより良い方法を知っている人はいますか?

大変感謝します。

40
James

Cipher.getInstanceからプロバイダーを削除し、notRSAprivateKeyにキャストすることで、これを機能させることができました。

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以下で機能しました。

56
James

問題

  1. 「Java.security .PrivateKey to Java.security.interfaces .RSAPrivateKey "&" Java.security .PublicKey to Java」を解析しようとしています。 .security.interfaces .RSAPublicKey "。だからこそ、ClassCastExceptionを取得しています。

ソリューション

  1. キーを解析する必要はありません。暗号化と復号化に「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
9
Vasanth

この問題も解決しました(上記の@Jamesの回答は別として):On Android 6.0では、暗号化の作成に「AndroidOpenSSL」を使用しないでください。RSAプライベートまたはパブリックが必要です。暗号化の初期化時に復号化のためのキー」。Cipher.getInstance( "RSA/ECB/PKCS1Padding")を使用するだけで機能します。

5
Sid