it-swarm.com.de

Fehler nach dem Fingerabdruck auf Samsung-Handys: Android.security.KeyStoreException: Schlüsselbenutzer nicht authentifiziert

Meine App verwendet die Android 6.0 Fingerprint API zum Schutz von AES-Schlüsseln im Android KeyStore. Der gespeicherte Schlüssel kann nur verwendet werden, wenn der Benutzer durch den Fingerabdrucksensor authentifiziert wird, da die KeyGenParameterSpec mit setUserAuthenticationRequired(true) initialisiert wird. 

Wenn der Benutzer den Sensor berührt, erhalte ich die initialisierte Verschlüsselung vom Callback onAuthenticationSucceeded(Cipher) und verwende sie zur Entschlüsselung. 

Dies funktioniert einwandfrei, außer bei Samsung-Handys mit Android 6. Wenn ich versuche, die zurückgesendete Verschlüsselung zu verwenden, werfen Samsung-Handys manchmal Android.security.KeyStoreException: Key user not authenticated. Obwohl der Schlüssel von onAuthenticationSucceeded(Cipher) zurückgegeben wird, glaubt der Android KeyStore, dass der Benutzer NICHT durch den Fingerabdrucksensor authentifiziert wurde. 

Es scheint, dass der Absturz eher geschieht, wenn die App längere Zeit nicht verwendet wurde. Wenn die App aufgewärmt ist, funktioniert normalerweise alles richtig.

Dieser Fehler tritt zufällig und nur bei Samsung-Handys auf. Er scheint an einem internen Timing-Problem in der Samsung-Implementierung von Android 6.0 KeyStore und FingerPrint API zu liegen.

Bearbeiten : Dieses Problem trat auch bei OnePlus- und Acer-Telefonen auf.

13
petrsyn

Da ich nicht damit rechne, dass die genannten Hersteller dieses Problem bald beheben werden, habe ich das Problem gelöst, indem Sie die KeyGenParameterSpec.setUserAuthenticationRequired(false) für Samsung, OnePlus, Asus und einige andere Geräte eingestellt haben.

4
petrsyn

Das Setzen von KeyGenParameterSpec.setUserAuthenticationRequired (false) kann ein potenzielles Sicherheitsproblem sein. Der obige Fehler sollte ähnlich wie KeyPermanentlyInvalidatedException behandelt werden. KeyPermanentlyInvalidatedException wird bei Cipher initialization ausgelöst, wenn nach dem Erstellen Ihres SecretKey neue Fingerabdrücke hinzugefügt werden. Wenn die Verschlüsselung jedoch vor dem Hinzufügen der neuen Fingerabdrücke initialisiert wird, wird die obige KeyStoreException für Schlüsselbenutzer nicht authentifiziert, wenn Sie versuchen, zu verschlüsseln oder mit dieser Verschlüsselung zu entschlüsseln.

Es ist leicht, diesen Fehler zu reproduzieren. Fügen Sie einen neuen Fingerabdruck hinzu, während sich der Bildschirm zur Überprüfung der Fingerabdrücke Ihrer App im Hintergrund befindet. Wechseln Sie nun wieder zur App und geben Sie den Fingerabdruck ein. Die Verschlüsselungs- oder Entschlüsselungsmethoden würden diesen Fehler auslösen. Ich könnte dieses Problem beheben, indem ich die Ausnahme abfängt und auf dieselbe Weise wie KeyPermanentlyInvalidatedException behandelt. 

15
NullPointer

Hören Sie NICHT auf "setUserAuthenticationRequired (false)"

Ich konnte dies auf Samsung durch zweimaliges Hören reproduzieren. Was ich denke, ist, dass Sie zweimal zuhören, sich bei einem Anruf authentifizieren, aber durch einen anderen verweisen.

fügen Sie Protokolle hinzu und prüfen Sie, ob Sie nur einmal und einmal nur Fingerabdrücke abhören.

5
Chris Merrick

Ich habe auch dieses Problem erlebt. In meinem Fall lag es daran, dass ich versehentlich zwei gleichzeitige Fingerabdruckauthentifizierungen durch zweimaliges Aufrufen von FingerprintManager.authenticate() gestartet habe. Der Fehler verschwand, als ich den zweiten Anruf entfernt hatte.

2
Venator85

Ich hatte auch dieses Problem bei der Verwendung von RSA und konnte es lösen, indem ich eine Kopie des öffentlichen Schlüssels anlegte, sobald ich einige Daten verschlüsseln möchte.

// 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

Dieses Problem hatte ich auch, wenn ich Samsung Galaxy S8 mit Android 8 verwende. Um dieses Problem zu lösen, entferne ich einfach den Schlüssel aus dem Keystore und generiere einen neuen Schlüssel, um Daten zu verschlüsseln und zu entschlüsseln

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

UPDATE: Dies ist ein bekanntes Problem mit Android 8.0 https://issuetracker.google.com/issues/65578763

Ich sehe gerade diesen Fehler auf Samsung und scheint verursacht worden zu sein, wenn ein neuer Fingerabdruck hinzugefügt wird. In unserem Code erwarten wir, dass KeyPermenantlyInvalidatedException während der Signatur von sign.initSign () ausgelöst wird. Dies tritt nicht auf und die initialisierte Signatur wird innerhalb des CryptoObject erfolgreich an den FingerprintManager übergeben. Der Fingerabdruck wird dann erfolgreich verifiziert und onAuthenticationSucceeded wird aufgerufen. Der Fehler tritt auf, wenn versucht wurde, signature.update (Byte [] Bytes) aufzurufen.

Erwartetes Verhalten würde meines Erachtens glauben, dass KeyInvalidatedException tatsächlich ausgelöst wird, aber ich bin nicht sicher, ob wir erwarten können, dass dies behoben wird. Meine Lösung ist es auf der onAuthenticationSucceeded Seite zu fangen.

@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

Es funktioniert auf meinem Samsung Galaxy S8, indem die Gültigkeitsdauer des authentifizierten Schlüssels explizit festgelegt wird:

setUserAuthenticationValidityDurationSeconds(10);

Dies macht es jedoch technisch möglich, den Schlüssel innerhalb dieser Zeitspanne mehrfach zu verwenden, ohne dass eine weitere Benutzerauthentifizierung erforderlich ist.

Ich persönlich glaube nicht, dass es ein so großes Risiko ist.

Ich habe die Verschlüsselung großer Streams nicht getestet, deren Ausführung mit diesen Schutzmaßnahmen einige Sekunden dauern kann. Ich frage mich, was passiert, wenn die Verschlüsselungsaufgabe länger dauert als die Gültigkeitsdauer zulässt.

0
whitebrow

Dies scheint ein Fehler in Android zu sein, der nach einem Update auftritt.

Ich hatte es auf einem OnePlus. Ich habe die Gerätesperre aus den Einstellungen entfernt und erneut eingestellt. Danach war das Problem weg.

0
Derlin

Unabhängig davon, ob es zufällig aufgrund eines Fehlers in Samsung geschieht oder nicht. Jedes Mal, wenn ein Schlüssel ungültig gemacht wird, entweder durch Hinzufügen eines neuen Fingerabdrucks oder aus einem anderen Grund. Der nächste Schritt besteht darin, den ungültigen Schlüssel mithilfe von KeyStore.delete (keyAlias) aus dem KeyStore zu löschen und auch Ihre alten Daten zu löschen, da nach dem Löschen des Verschlüsselungsschlüssels keine Möglichkeit zur Rückschlüsselung besteht. Bitten Sie den Benutzer, neue Anmeldeinformationen einzugeben und diese mit einem neuen Schlüssel zu verschlüsseln. Der neue Schlüssel kann denselben Alias ​​haben wie der alte. Ein Beispiel für den Fluss finden Sie hier: Beispiel für eine Klasse, die den FingerprintManager-Fluss in Android einhüllt

0
Pablo Valdes