mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-20 00:58:25 +00:00
fix: fallback on biometric key failures and retry creating key, fix up notification issues
This commit is contained in:
parent
58dfd3b7cd
commit
ba60e8a8ee
@ -159,8 +159,8 @@ dependencies {
|
|||||||
testImplementation 'org.robolectric:shadows-multidex:4.4'
|
testImplementation 'org.robolectric:shadows-multidex:4.4'
|
||||||
}
|
}
|
||||||
|
|
||||||
def canonicalVersionCode = 286
|
def canonicalVersionCode = 287
|
||||||
def canonicalVersionName = "1.13.5"
|
def canonicalVersionName = "1.13.6"
|
||||||
|
|
||||||
def postFixSize = 10
|
def postFixSize = 10
|
||||||
def abiPostFix = ['armeabi-v7a' : 1,
|
def abiPostFix = ['armeabi-v7a' : 1,
|
||||||
|
@ -46,6 +46,7 @@ import org.thoughtcrime.securesms.crypto.BiometricSecretProvider;
|
|||||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||||
import org.thoughtcrime.securesms.util.AnimationCompleteListener;
|
import org.thoughtcrime.securesms.util.AnimationCompleteListener;
|
||||||
|
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
@ -68,6 +69,7 @@ public class PassphrasePromptActivity extends BaseActionBarActivity {
|
|||||||
|
|
||||||
private boolean authenticated;
|
private boolean authenticated;
|
||||||
private boolean failure;
|
private boolean failure;
|
||||||
|
private boolean hasSignatureObject = true;
|
||||||
|
|
||||||
private KeyCachingService keyCachingService;
|
private KeyCachingService keyCachingService;
|
||||||
|
|
||||||
@ -205,7 +207,23 @@ public class PassphrasePromptActivity extends BaseActionBarActivity {
|
|||||||
if (fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints()) {
|
if (fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints()) {
|
||||||
Log.i(TAG, "Listening for fingerprints...");
|
Log.i(TAG, "Listening for fingerprints...");
|
||||||
fingerprintCancellationSignal = new CancellationSignal();
|
fingerprintCancellationSignal = new CancellationSignal();
|
||||||
fingerprintManager.authenticate(new FingerprintManagerCompat.CryptoObject(biometricSecretProvider.getOrCreateBiometricSignature(this)), 0, fingerprintCancellationSignal, fingerprintListener, null);
|
Signature signature;
|
||||||
|
try {
|
||||||
|
signature = biometricSecretProvider.getOrCreateBiometricSignature(this);
|
||||||
|
hasSignatureObject = true;
|
||||||
|
throw new InvalidKeyException("e");
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
signature = null;
|
||||||
|
hasSignatureObject = false;
|
||||||
|
Log.e(TAG, "Error getting / creating signature", e);
|
||||||
|
}
|
||||||
|
fingerprintManager.authenticate(
|
||||||
|
signature == null ? null : new FingerprintManagerCompat.CryptoObject(signature),
|
||||||
|
0,
|
||||||
|
fingerprintCancellationSignal,
|
||||||
|
fingerprintListener,
|
||||||
|
null
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "firing intent...");
|
Log.i(TAG, "firing intent...");
|
||||||
Intent intent = keyguardManager.createConfirmDeviceCredentialIntent("Unlock Session", "");
|
Intent intent = keyguardManager.createConfirmDeviceCredentialIntent("Unlock Session", "");
|
||||||
@ -230,8 +248,22 @@ public class PassphrasePromptActivity extends BaseActionBarActivity {
|
|||||||
public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
|
public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
|
||||||
Log.i(TAG, "onAuthenticationSucceeded");
|
Log.i(TAG, "onAuthenticationSucceeded");
|
||||||
if (result.getCryptoObject() == null || result.getCryptoObject().getSignature() == null) {
|
if (result.getCryptoObject() == null || result.getCryptoObject().getSignature() == null) {
|
||||||
// authentication failed
|
if (hasSignatureObject) {
|
||||||
onAuthenticationFailed();
|
// authentication failed
|
||||||
|
onAuthenticationFailed();
|
||||||
|
} else {
|
||||||
|
fingerprintPrompt.setImageResource(R.drawable.ic_check_white_48dp);
|
||||||
|
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.green_500), PorterDuff.Mode.SRC_IN);
|
||||||
|
fingerprintPrompt.animate().setInterpolator(new BounceInterpolator()).scaleX(1.1f).scaleY(1.1f).setDuration(500).setListener(new AnimationCompleteListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
handleAuthenticated();
|
||||||
|
|
||||||
|
fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp);
|
||||||
|
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.signal_primary), PorterDuff.Mode.SRC_IN);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Signature object now successfully unlocked
|
// Signature object now successfully unlocked
|
||||||
|
@ -6,6 +6,7 @@ import android.security.keystore.KeyGenParameterSpec
|
|||||||
import android.security.keystore.KeyProperties
|
import android.security.keystore.KeyProperties
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsession.utilities.Util
|
import org.session.libsession.utilities.Util
|
||||||
|
import java.security.InvalidKeyException
|
||||||
import java.security.KeyPairGenerator
|
import java.security.KeyPairGenerator
|
||||||
import java.security.KeyStore
|
import java.security.KeyStore
|
||||||
import java.security.PrivateKey
|
import java.security.PrivateKey
|
||||||
@ -58,9 +59,20 @@ class BiometricSecretProvider {
|
|||||||
createAsymmetricKey(context)
|
createAsymmetricKey(context)
|
||||||
TextSecurePreferences.setFingerprintKeyGenerated(context)
|
TextSecurePreferences.setFingerprintKeyGenerated(context)
|
||||||
}
|
}
|
||||||
val key = ks.getKey(BIOMETRIC_ASYM_KEY_ALIAS, null) as PrivateKey
|
val signature = try {
|
||||||
val signature = Signature.getInstance(SIGNATURE_ALGORITHM)
|
val key = ks.getKey(BIOMETRIC_ASYM_KEY_ALIAS, null) as PrivateKey
|
||||||
signature.initSign(key)
|
val signature = Signature.getInstance(SIGNATURE_ALGORITHM)
|
||||||
|
signature.initSign(key)
|
||||||
|
signature
|
||||||
|
} catch (e: InvalidKeyException) {
|
||||||
|
ks.deleteEntry(BIOMETRIC_ASYM_KEY_ALIAS)
|
||||||
|
createAsymmetricKey(context)
|
||||||
|
TextSecurePreferences.setFingerprintKeyGenerated(context)
|
||||||
|
val key = ks.getKey(BIOMETRIC_ASYM_KEY_ALIAS, null) as PrivateKey
|
||||||
|
val signature = Signature.getInstance(SIGNATURE_ALGORITHM)
|
||||||
|
signature.initSign(key)
|
||||||
|
signature
|
||||||
|
}
|
||||||
return signature
|
return signature
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,10 +278,10 @@ public class DefaultMessageNotifier implements MessageNotifier {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (notificationState.hasMultipleThreads()) {
|
if (notificationState.hasMultipleThreads()) {
|
||||||
sendMultipleThreadNotification(context, notificationState, signal);
|
|
||||||
for (long threadId : notificationState.getThreads()) {
|
for (long threadId : notificationState.getThreads()) {
|
||||||
sendSingleThreadNotification(context, new NotificationState(notificationState.getNotificationsForThread(threadId)), false, true);
|
sendSingleThreadNotification(context, new NotificationState(notificationState.getNotificationsForThread(threadId)), false, true);
|
||||||
}
|
}
|
||||||
|
sendMultipleThreadNotification(context, notificationState, signal);
|
||||||
} else if (notificationState.getMessageCount() > 0){
|
} else if (notificationState.getMessageCount() > 0){
|
||||||
sendSingleThreadNotification(context, notificationState, signal, false);
|
sendSingleThreadNotification(context, notificationState, signal, false);
|
||||||
} else {
|
} else {
|
||||||
@ -305,7 +305,7 @@ public class DefaultMessageNotifier implements MessageNotifier {
|
|||||||
String trimmedText = "";
|
String trimmedText = "";
|
||||||
if (text != null) {
|
if (text != null) {
|
||||||
int trimEnd = Math.min(text.length(), 50);
|
int trimEnd = Math.min(text.length(), 50);
|
||||||
trimmedText = text.subSequence(0,trimEnd) + (text.length() > 50 ? "..." : "");
|
trimmedText = text.subSequence(0,trimEnd) + (text.length() >= 50 ? "..." : "");
|
||||||
}
|
}
|
||||||
return trimmedText;
|
return trimmedText;
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,9 @@ import androidx.core.app.NotificationCompat
|
|||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import com.google.firebase.messaging.FirebaseMessagingService
|
import com.google.firebase.messaging.FirebaseMessagingService
|
||||||
import com.google.firebase.messaging.RemoteMessage
|
import com.google.firebase.messaging.RemoteMessage
|
||||||
|
import org.session.libsession.messaging.jobs.BatchMessageReceiveJob
|
||||||
import org.session.libsession.messaging.jobs.JobQueue
|
import org.session.libsession.messaging.jobs.JobQueue
|
||||||
import org.session.libsession.messaging.jobs.MessageReceiveJob
|
import org.session.libsession.messaging.jobs.MessageReceiveParameters
|
||||||
import org.session.libsession.messaging.utilities.MessageWrapper
|
import org.session.libsession.messaging.utilities.MessageWrapper
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsignal.utilities.Base64
|
import org.session.libsignal.utilities.Base64
|
||||||
@ -27,7 +28,7 @@ class PushNotificationService : FirebaseMessagingService() {
|
|||||||
if (data != null) {
|
if (data != null) {
|
||||||
try {
|
try {
|
||||||
val envelopeAsData = MessageWrapper.unwrap(data).toByteArray()
|
val envelopeAsData = MessageWrapper.unwrap(data).toByteArray()
|
||||||
val job = MessageReceiveJob(envelopeAsData)
|
val job = BatchMessageReceiveJob(listOf(MessageReceiveParameters(envelopeAsData)), null)
|
||||||
JobQueue.shared.add(job)
|
JobQueue.shared.add(job)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d("Loki", "Failed to unwrap data for message due to error: $e.")
|
Log.d("Loki", "Failed to unwrap data for message due to error: $e.")
|
||||||
|
@ -135,14 +135,12 @@ class BatchMessageReceiveJob(
|
|||||||
}
|
}
|
||||||
storage.incrementUnread(threadId, trueUnreadCount)
|
storage.incrementUnread(threadId, trueUnreadCount)
|
||||||
storage.updateThread(threadId, true)
|
storage.updateThread(threadId, true)
|
||||||
SSKEnvironment.shared.notificationManager.updateNotification(context, threadId)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// await all thread processing
|
// await all thread processing
|
||||||
deferredThreadMap.awaitAll()
|
deferredThreadMap.awaitAll()
|
||||||
}
|
}
|
||||||
|
SSKEnvironment.shared.notificationManager.updateNotification(context)
|
||||||
if (failures.isEmpty()) {
|
if (failures.isEmpty()) {
|
||||||
handleSuccess()
|
handleSuccess()
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user