私はこのチュートリアルに従っています: 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を取得するより良い方法を知っている人はいますか?
大変感謝します。
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以下で機能しました。
問題
ソリューション
暗号化
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
この問題も解決しました(上記の@Jamesの回答は別として):On Android 6.0では、暗号化の作成に「AndroidOpenSSL」を使用しないでください。RSAプライベートまたはパブリックが必要です。暗号化の初期化時に復号化のためのキー」。Cipher.getInstance( "RSA/ECB/PKCS1Padding")を使用するだけで機能します。