web-dev-qa-db-fra.com

Erreur après avoir touché une empreinte digitale sur les téléphones Samsung: Android.security.KeyStoreException: Utilisateur clé non authentifié

Mon application utilise l'API d'empreinte digitale Android 6.0 pour protéger la clé AES dans le magasin de clés Android. La clé stockée ne peut être utilisée que lorsque l'utilisateur est authentifié par le capteur d'empreinte digitale car la variable KeyGenParameterSpec est initialisée avec setUserAuthenticationRequired(true)

Lorsque l'utilisateur touche le capteur, je reçois le chiffre initialisé à partir de la fonction de rappel onAuthenticationSucceeded(Cipher) et je l'utilise pour le déchiffrement. 

Cela fonctionne parfaitement, sauf sur les téléphones Samsung équipés d'Android 6. Lorsque j'essaie d'utiliser le code chiffré renvoyé, les téléphones Samsung lancent parfois Android.security.KeyStoreException: Key user not authenticated. Ainsi, même si le chiffre est renvoyé par la onAuthenticationSucceeded(Cipher), le KeyStore Android pense que l'utilisateur N'EST PAS authentifié par le capteur d'empreinte digitale. 

Il semble que le crash se produise plutôt lorsque l'application n'a pas été utilisée pendant plus longtemps. Lorsque l'application est verminée, tout fonctionne normalement.

Comme cette erreur se produit de manière aléatoire et uniquement sur les téléphones Samsung ... Il semble que cela soit dû à un problème de synchronisation interne dans l'implémentation Samsung d'API 6.0 Android KeyStore et FingerPrint.

Modifier : Ce problème a également été rencontré avec les téléphones OnePlus et Acer.

13
petrsyn

Comme je ne m'attends pas à ce que les fabricants mentionnés résolvent ce problème bientôt, je l'ai résolu en définissant la fonction KeyGenParameterSpec.setUserAuthenticationRequired(false) pour Samsung, OnePlus, Asus et certains autres appareils.

4
petrsyn

La définition de KeyGenParameterSpec.setUserAuthenticationRequired (false) peut être un problème de sécurité potentiel. L'erreur ci-dessus doit être gérée de la même manière que KeyPermanentlyInvalidatedException . KeyPermanentlyInvalidatedException est levée sur Initialisation du chiffrement si de nouvelles empreintes digitales sont ajoutées après la création de votre clé secrète. Toutefois, si le chiffre est initialisé avant l'ajout des nouvelles empreintes digitales, vous obtiendrez l'exception KeyStoreException ci-dessus pour l'utilisateur principal non authentifié, lorsque vous essayez de chiffrer ou déchiffrer avec ce chiffrement.

Il est facile de reproduire cette erreur. Lorsque l'écran de vérification des empreintes digitales de votre application est en arrière-plan, essayez d'ajouter une nouvelle empreinte. Retournez maintenant dans l'application et entrez l'empreinte digitale. Les méthodes de cryptage ou de décryptage génèrent cette erreur. Je pourrais résoudre ce problème en interceptant l'exception et en la traitant de la même manière que KeyPermanentlyInvalidatedException. 

15
NullPointer

N'écoutez PAS le "setUserAuthenticationRequired (false)"

J'ai pu reproduire cela sur Samsung en écoutant deux fois. Ce que je pense est en train de se passer, c’est que vous écoutez deux fois, que vous vous authentifiez lors d’un appel, mais que vous y fassiez référence.

ajoutez des journaux et vérifiez que vous ne commencez à écouter les empreintes que une fois et une fois seulement.

5
Chris Merrick

J'ai vécu ce problème aussi. Dans mon cas, cela était dû au fait que je commençais accidentellement l’authentification simultanée des empreintes digitales deux en appelant FingerprintManager.authenticate() à deux reprises. L'erreur a disparu une fois que j'ai supprimé le deuxième appel.

2
Venator85

J'ai également eu ce problème lorsque j'utilisais RSA et je pouvais le résoudre en créant une copie de la clé publique dès que je voudrais chiffrer des données.

// create a copy of the public key -> workaround for Android.security.KeyStoreException: Key user not authenticated
val publicKey = KeyFactory
    .getInstance("RSA")
    .generatePublic(X509EncodedKeySpec(keyPair.public.encoded))

// encrypt with the public key
val cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
cipher.init(Cipher.ENCRYPT_MODE, publicKey)
val encryptedData = cipher.doFinal(data)
1
BauerMitFackel

J'ai également rencontré ce problème lors de l'utilisation de Samsung Galaxy S8 avec Android 8. Pour résoudre ce problème, il suffit d'enlever la clé du magasin de clés et d'en générer de nouvelles après l'utilisation de la nouvelle clé pour chiffrer et déchiffrer les données.

try {
    keyStore.deleteEntry(KEY_ALIAS);
} catch (KeyStoreException e) {
    e.printStackTrace();
}
1
fuliozor

UPDATE: Il s'agit d'un problème connu avec Android 8.0 https://issuetracker.google.com/issues/65578763

Je viens juste de voir cette erreur sur Samsung et semble être causé par l'ajout d'une nouvelle empreinte digitale. Dans notre code, nous nous attendons à ce qu'une exception KeyPermenantlyInvalidatedException soit levée lors de signature.initSign (). Cela ne se produit pas et la signature initialisée est passée avec succès à l'intérieur de CryptoObject à FingerprintManager. L'empreinte est ensuite vérifiée et onAuthenticationSucceeded est appelée. L'erreur se produit lors d'une tentative d'appel de signature.update (byte [] bytes).

Je pense que le comportement attendu est que l'exception KeyInvalidatedException est effectivement levée, mais je ne suis pas sûr que nous puissions jamais espérer que cela soit résolu. Ma solution consiste à l'attraper du côté onAuthenticationSucceeded.

@Override
    public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
        Log.d(LOG_TAG, "Device Authentication Succeeded");
        try {
            Signature signature = result.getCryptoObject().getSignature();
            String authData = getAuthData();
            signature.update(authData.getBytes());
            // do something with signature

        } catch (SignatureException e) {
            Log.d(LOG_TAG, e.getMessage());
            if(e.getMessage() != null && e.getMessage().contains("Key user not authenticated")) {
                // handle as if were KeyPermanentlyInvalidatedException
            } else {
                Log.d(LOG_TAG, e.getMessage());
                // handle as regular error
            }
        }
    }
1
Montwell

Cela fonctionne sur mon Samsung Galaxy S8 en définissant explicitement la durée de validité de la clé authentifiée:

setUserAuthenticationValidityDurationSeconds(10);

Cela permet toutefois techniquement d'utiliser la clé plusieurs fois au cours de cette période sans nécessiter d'authentification supplémentaire de l'utilisateur.

Personnellement, je ne pense pas que ce soit un si gros risque.

Je n'ai pas testé le cryptage de gros flux pouvant prendre plusieurs secondes à l'aide de ces mesures de protection. Je me demande ce qui se passe si la tâche de chiffrement prend plus de temps que ne le permet la durée de validité.

0
whitebrow

Cela semble être un bug dans Android qui survient après une mise à jour.

Je l'avais sur un OnePlus. J'ai supprimé le verrou de l'appareil des paramètres et le redéfinis. Après cela, le problème avait disparu.

0
Derlin

Peu importe si cela se produit de manière aléatoire en raison d'un bogue dans Samsung ou non. Chaque fois qu'une clé est invalidée, soit par l'ajout d'une nouvelle empreinte digitale, soit par un autre motif. L'étape suivante consiste à supprimer la clé invalidée du KeyStore à l'aide de KeyStore.delete (keyAlias) et à effacer vos anciennes données car il n'y a aucun moyen de décrypter une fois que vous avez supprimé sa clé de cryptage. Demandez ensuite à l'utilisateur de saisir de nouvelles informations d'identification et de les chiffrer à l'aide d'une nouvelle clé. La nouvelle clé peut avoir le même alias que l'ancien. Vous pouvez voir un exemple du flux ici: Exemple d'une classe enveloppant le flux FingerprintManager dans Android

0
Pablo Valdes