36

Ich folge diesem Tutorial: How to use the Android Keystore to store passwords and other sensitive information. Es hängt (locker) mit der Google Sample App zusammen: BasicAndroidKeyStore.Crash Casting AndroidKeyStoreRSAPrivateKey zu RSAPrivateKey

Ich kann meine Daten mit dem öffentlichen Schlüssel verschlüsseln, und ich kann auf Geräten mit Lollipop entschlüsseln. Allerdings habe ich ein Nexus 6 läuft Eibisch und diese stürzt den Fehler geben:

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 

Hier ist der Code, stürzt auf:

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); 

Ich bin nur ungern dies einem Android M Kuriosität to put down weil ich keinen Grund sehe, warum sich die Java-Crypto-Bibliotheken geändert hätten. Wenn die M-Version kommt und unsere App sofort auf M stürzt, werde ich in großen Schwierigkeiten sein.

Ich mache etwas falsch? Der Fehler sagt ganz konkret, dass Sie nicht nach RSAPrivateKey umwandeln können, also weiß jemand einen besseren Weg, den RSAPrivateKey aus dem Eintrag zu bekommen?

Vielen vielen Dank.

Antwort

53

ich es geschafft, diese Funktion zu erhalten, indem der Anbieter von Cipher.getInstance zu entfernen und nicht Casting zu einem RSAprivateKey.

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

Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey()); 

Ich bin nicht 100%, aber ich glaube, der Grund dafür ich die Änderung des Eibisch von OpenSSL zu BoringSSL glaube. https://developer.android.com/preview/behavior-changes.html#behavior-apache-http-client

Wie auch immer, das obige funktionierte für M und darunter.

+3

jetzt offen auf AOSP: [Ausgabe 205.450: Crash Casting AndroidKeyStoreRSAPrivateKey zu RSAPrivateKey] (https: // Code .google.com/p/android/issues/detail? id = 205450). – jww

+0

Dies funktionierte nicht für mich auf Android N Vorschau 4 – resp78

+1

diese Lösung funktioniert auf Lollipop. Aber auf Marshmallow wirft es: java.security.InvalidKeyException: Benötigen RSA privaten oder öffentlichen Schlüssel – deviant

-2

Ich habe es nicht versucht, aber Sie sollten in der Lage sein, die android.security.keystore.AndroidKeyStoreRSAPrivateKey separat zu werfen. Diese sollten die Schnittstellen, die Sie brauchen:

  1. java.security.PrivateKey
  2. java.security.interfaces.RSAKey
+0

erklären, bitte –

4

ich dieses Problem gelöst, indem auch die folgenden (abgesehen von @James oben antworten): Auf Android 6.0 Sie nicht „AndroidOpenSSL“ für Chiffre Schöpfung verwenden sollten, wäre es mit „Need RSA privaten oder öffentlichen Schlüsseln“ an Chiffre scheitern init für die Entschlüsselung. Verwenden Sie einfach Cipher.getInstance ("RSA/ECB/PKCS1Padding") und es wird funktionieren.

+0

Welchen Provider sollte man dann benutzen? – jonney

+0

funktioniert nicht in Androind N –

4

Ausgabe

  1. Wir versuchen zu analysieren "java.security. PrivateKey zu java.security.interfaces. RSAPrivateKey" & „java.security. PublicKey zu java.security Schnittstellen: RSAPublicKey ". Deshalb erhalten wir ClassCastException.

Lösung

  1. Wir brauchen nicht den Schlüssel zu analysieren, können wir direkt die "java.security. PrivateKey" verwenden & "java.security. PublicKey" für Verschlüsselung & Entschlüsselung.

Encryption

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

Decryption

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

Gibt Ausnahme mit Nachricht: Benötigen RSA privaten oder öffentlichen Schlüssel. – Talha