Erreur de fichier de clés Android «Impossible de générer la clé dans le fichier de clés»

J’ai une erreur en essayant de générer une clé pour certains appareils. Je suis capable de reproduire l’erreur sur un Samsung Galaxy Note 4.4.2.

java.lang.IllegalStateException: could not generate key in keystore at android.security.AndroidKeyPairGenerator.generateKeyPair(AndroidKeyPairGenerator.java:100) at java.security.KeyPairGenerator$KeyPairGeneratorImpl.generateKeyPair(KeyPairGenerator.java:275) at com.eric.demo.MainActivity.generateKeyPair(MainActivity.java:65) at com.eric.demo.MainActivity.onClickButton(MainActivity.java:43) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at android.view.View$1.onClick(View.java:3964) at android.view.View.performClick(View.java:4640) at android.view.View$PerformClick.run(View.java:19421) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5476) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084) at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132) at dalvik.system.NativeStart.main(Native Method) 

J’ai créé une petite application pour générer uniquement une clé en copiant le code ligne par ligne à partir de la page de développement Android https://developer.android.com/training/articles/keystore.html sous «Génération d’une nouvelle clé privée».

  public void onClickButton (View view) { try { generateKeyPair(this, "test3"); } catch (Exception e){ Log.wtf("exception", e); } } private void generateKeyPair(Context context, Ssortingng alias) throws Exception { Calendar cal = Calendar.getInstance(); Date now = cal.getTime(); cal.add(Calendar.YEAR, 1); Date end = cal.getTime(); KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); kpg.initialize(new KeyPairGeneratorSpec.Builder(getApplicationContext()) .setAlias(alias) .setStartDate(now) .setEndDate(end) .setSerialNumber(BigInteger.valueOf(1)) .setSubject(new X500Principal("CN=test3")) .build()); KeyPair kp = kpg.generateKeyPair(); } 

L’erreur semble se produire dans kpg.generateKeyPair (), dans AndroidKeyPairGenerator.java:

 if (!mKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF, keyType, mSpec.getKeySize(), mSpec.getFlags(), args)) { throw new IllegalStateException("could not generate key in keystore"); } 

et dans KeyStore.java:

 public boolean generate(Ssortingng key, int uid, int keyType, int keySize, int flags, byte[][] args) { try { return mBinder.generate(key, uid, keyType, keySize, flags, args) == NO_ERROR; } catch (RemoteException e) { Log.w(TAG, "Cannot connect to keystore", e); return false; } } 

L’appel mBinder.generate () semble renvoyer 2, ce qui signifie que le fichier de clés est verrouillé?

 // ResponseCodes public static final int NO_ERROR = 1; public static final int LOCKED = 2; public static final int UNINITIALIZED = 3; public static final int SYSTEM_ERROR = 4; public static final int PROTOCOL_ERROR = 5; public static final int PERMISSION_DENIED = 6; public static final int KEY_NOT_FOUND = 7; public static final int VALUE_CORRUPTED = 8; public static final int UNDEFINED_ACTION = 9; public static final int WRONG_PASSWORD = 10; 

L’erreur peut être liée à ce problème avec le fichier de clés https://code.google.com/p/android/issues/detail?id=177459&q=could%20not%20generate%20key%20in%20keystore&colspec=ID%20Type% 20Status% 20Owner% 20Summary% 20Stars

Quelques choses que j’ai essayées individuellement et des combinaisons de ce qui suit:
1. Définition du cryptage requirejs. Le résultat est une autre erreur: “Le fichier de clés Android doit être à l’état initialisé et déverrouillé si le chiffrement est requirejs”
2. Définition d’un écran de locking (modèle, code PIN, AUCUN, mot de passe, balayage). Même comportement
3. startActivity(new Intent("com.android.credentials.UNLOCK")); de délocking ou de réinitialisation du stockage d’informations d’identification avec startActivity(new Intent("com.android.credentials.UNLOCK")); ou startActivity(new Intent("com.android.credentials.RESET")); La tentative de délocking montre un message “Entrez le mot de passe pour le stockage des informations d’identification”, dans lequel aucun mot de passe raisonnable ne fonctionne, et même la suppression des informations d’identification n’aide pas.

Bien que je ne connaisse pas la réponse complète, je peux vous aider à poursuivre votre recherche. L’implémentation du classeur de l’autre côté de mBinder est le fichier de clés natif . Si je me souviens bien, son comportement consiste à 1) prendre en charge les opérations clés au niveau du logiciel, ou 2) déléguer à une bibliothèque keymaster fournie par OEM qui (vraisemblablement) interface avec le fichier de clés matérielles OEM. Plus d’infos ici , ici et ici .

Note: Je renonce à la politique habituelle de SO qui consiste à insérer le contenu du lien externe dans la réponse, car je vous associe à trois articles qui ne dépassent pas une page et que cela semble un peu ridicule d’afficher une réponse de six pages. )

 public class EncryptionApi18AndAbove{ private Context context; private KeyStore keyStore; private static Ssortingng alias = "alias"; public EncryptionApi18AndAbove(Context context) { this.context = context; try { keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); } catch (Exception e) { // bla bla } } private Ssortingng createNewKeys(Ssortingng alias, Context context) { try { if (!keyStore.containsAlias(alias)) { Calendar start = Calendar.getInstance(); Calendar end = Calendar.getInstance(); end.add(Calendar.YEAR, 1); KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context) .setAlias(alias) .setSubject(new X500Principal("CN=Sample Name, O=Android Authority")) .setSerialNumber(BigInteger.ONE) .setStartDate(start.getTime()) .setEndDate(end.getTime()) .build(); KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); generator.initialize(spec); generator.initialize(spec); generator.generateKeyPair(); } } catch (Exception e) { //bla bla } return alias; } @Override public Ssortingng encrypt(Ssortingng text) { if (text == null || text.length() == 0) { return text; } try { KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(createNewKeys(alias, context), null); PublicKey publicKey = privateKeyEntry.getCertificate().getPublicKey(); Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); inCipher.init(Cipher.ENCRYPT_MODE, publicKey); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); CipherOutputStream cipherOutputStream = new CipherOutputStream( outputStream, inCipher); cipherOutputStream.write(text.getBytes("UTF-8")); cipherOutputStream.close(); return Base64.encodeToSsortingng(outputStream.toByteArray(), Base64.DEFAULT); } catch (Exception e) { //bla bla } return text; } @Override public Ssortingng decrypt(Ssortingng text) { if (text == null || text.length() == 0) { return text; } try { KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(createNewKeys(alias, context), null); PrivateKey privateKey = privateKeyEntry.getPrivateKey(); Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding"); output.init(Cipher.DECRYPT_MODE, privateKey); CipherInputStream cipherInputStream = new CipherInputStream( new ByteArrayInputStream(Base64.decode(text, Base64.DEFAULT)), output); ArrayList values = new ArrayList<>(); int nextByte; while ((nextByte = cipherInputStream.read()) != -1) { values.add((byte) nextByte); } byte[] bytes = new byte[values.size()]; for (int i = 0; i < bytes.length; i++) { bytes[i] = values.get(i).byteValue(); } return new String(bytes, 0, bytes.length, "UTF-8"); } catch (Exception e) { // bla bla } return text; } } 

Vous pouvez utiliser cette classe. C'est le travail min SDK 18 et ci-dessus. Vous pouvez créer une clé Android Keystore, décrypter et chiffrer du texte simple.

Si votre code est correct, souvenez-vous que vous devez configurer un code PIN / PW / Fingerprint (Secure unlock) pour votre appareil afin que le fichier de clés commence à fonctionner. Un simple balayage vous donnera une telle erreur si vous essayez de générer des paires de clés.

Je pense que c’est la bonne direction: Faites un clic droit sur le projet> Outils Android> Exporter le package de l’application signée L’assistant Exporter l’application Android apparaît. Sélectionnez le projet que je veux exporter, cliquez sur Suivant. L’écran Sélection du magasin de clés apparaît.