Crash casting AndroidKeyStoreRSAPrivateKey to RSAPrivateKey
je suis ce tutoriel: comment utiliser le Keystore Android pour stocker les mots de passe et autres informations sensibles. (Vaguement) les liens avec le Google app Exemple: BasicAndroidKeyStore.
je peux chiffrer mes données en utilisant la clé publique, et je peux déchiffrer sur les appareils exécutant Lollipop. Cependant, J'ai un Nexus 6 qui tourne marshmallow et qui se bloque donnant l'erreur:
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
Voici le code qu'il se bloque sur:
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);
je suis réticent à mettre cela à une surdité Android car je ne vois aucune raison pour laquelle les bibliothèques Java crypto auraient changé. Si la version M se libère et que notre application tombe immédiatement sur M, je vais avoir de gros problèmes.
je suis en train de faire quelque chose de mal? L'erreur dit très spécifiquement que vous ne pouvez pas lancer RSAPrivateKey, donc quelqu'un sait une meilleure façon d'obtenir le RSAPrivateKey à partir de l'entrée?
un grand merci.
4 réponses
j'ai réussi à obtenir ce fonctionnement en enlevant le fournisseur de Cipher.getInstance et casting à un RSAprivateKey.
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) entry;
Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding");
output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());
Je ne suis pas 100% mais je pense que la raison pour cela je crois est le changement de marshmallow D'OpenSSL à BoringSSL. https://developer.android.com/preview/behavior-changes.html#behavior-apache-http-client
de toute façon, ce qui précède a fonctionné pour M et en dessous.
Problème
- nous essayons d'analyser "java.sécurité. PrivateKey à java.sécurité.interface. RSAPrivateKey" & "java.sécurité. Publicickey à java.sécurité.interface. RSAPublicKey". C'est pourquoi nous obtenons ClassCastException.
Solution
- Nous n'avons pas besoin d'analyser les principaux, on peut utiliser directement les "Java.sécurité. PrivateKey" & "java.sécurité. Publicickey" pour le Chiffrement Et le Déchiffrement.
de Cryptage
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)entry;
PublicKey publicKey = privateKeyEntry.getCertificate().getPublicKey(); // Don't TypeCast to RSAPublicKey
déchiffrement
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)entry;
PrivateKey privateKey = privateKeyEntry.getPrivateKey(); // Don't TypeCast to RSAPrivateKey
j'ai résolu ce problème en suivant aussi ceci(à part la réponse de @James ci-dessus)): Sur Android 6.0, vous ne devez pas utiliser "AndroidOpenSSL" pour la création de chiffrement, il échouerait avec "besoin RSA Clé privée ou publique" à cipher init pour le déchiffrement. Utilisez simplement le cryptogramme.getInstance ("RSA/ECB/PKCS1Padding") et cela fonctionnera.
je havn'pas essayé, mais vous devriez être en mesure de lancer le android.sécurité.fichier de stockage des clés.AndroidKeyStoreRSAPrivateKey à la suite séparément. Ceux-ci devraient être les interfaces dont vous avez besoin:
- java.sécurité.PrivateKey
- java.sécurité.interface.RSAKey!--4-->