Better handle identity key changes in response to storage service syncs.

This commit is contained in:
Greyson Parrelli 2020-05-15 14:14:41 -04:00 committed by Alex Hart
parent e714cb6423
commit fa5729bac6
3 changed files with 25 additions and 7 deletions

View File

@ -69,7 +69,7 @@ public class TextSecureIdentityKeyStore implements IdentityKeyStore {
} }
identityDatabase.saveIdentity(recipient.getId(), identityKey, verifiedStatus, false, System.currentTimeMillis(), nonBlockingApproval); identityDatabase.saveIdentity(recipient.getId(), identityKey, verifiedStatus, false, System.currentTimeMillis(), nonBlockingApproval);
IdentityUtil.markIdentityUpdate(context, recipient); IdentityUtil.markIdentityUpdate(context, recipient.getId());
SessionUtil.archiveSiblingSessions(context, address); SessionUtil.archiveSiblingSessions(context, address);
return true; return true;
} }

View File

@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.IdentityUtil;
import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.InvalidKeyException; import org.whispersystems.libsignal.InvalidKeyException;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
@ -145,14 +146,31 @@ public class IdentityDatabase extends Database {
} }
public void updateIdentityAfterSync(@NonNull RecipientId id, IdentityKey identityKey, VerifiedStatus verifiedStatus) { public void updateIdentityAfterSync(@NonNull RecipientId id, IdentityKey identityKey, VerifiedStatus verifiedStatus) {
if (!hasMatchingKey(id, identityKey, verifiedStatus)) { boolean keyMatches = hasMatchingKey(id, identityKey);
boolean statusMatches = keyMatches && hasMatchingStatus(id, identityKey, verifiedStatus);
if (!keyMatches || !statusMatches) {
saveIdentityInternal(id, identityKey, verifiedStatus, false, System.currentTimeMillis(), true); saveIdentityInternal(id, identityKey, verifiedStatus, false, System.currentTimeMillis(), true);
Optional<IdentityRecord> record = getIdentity(id); Optional<IdentityRecord> record = getIdentity(id);
if (record.isPresent()) EventBus.getDefault().post(record.get()); if (record.isPresent()) EventBus.getDefault().post(record.get());
} }
if (!keyMatches) {
IdentityUtil.markIdentityUpdate(context, id);
}
} }
private boolean hasMatchingKey(@NonNull RecipientId id, IdentityKey identityKey, VerifiedStatus verifiedStatus) { private boolean hasMatchingKey(@NonNull RecipientId id, IdentityKey identityKey) {
SQLiteDatabase db = databaseHelper.getReadableDatabase();
String query = RECIPIENT_ID + " = ? AND " + IDENTITY_KEY + " = ?";
String[] args = new String[]{id.serialize(), Base64.encodeBytes(identityKey.serialize())};
try (Cursor cursor = db.query(TABLE_NAME, null, query, args, null, null, null)) {
return cursor != null && cursor.moveToFirst();
}
}
private boolean hasMatchingStatus(@NonNull RecipientId id, IdentityKey identityKey, VerifiedStatus verifiedStatus) {
SQLiteDatabase db = databaseHelper.getReadableDatabase(); SQLiteDatabase db = databaseHelper.getReadableDatabase();
String query = RECIPIENT_ID + " = ? AND " + IDENTITY_KEY + " = ? AND " + VERIFIED + " = ?"; String query = RECIPIENT_ID + " = ? AND " + IDENTITY_KEY + " = ? AND " + VERIFIED + " = ?";
String[] args = new String[]{id.serialize(), Base64.encodeBytes(identityKey.serialize()), String.valueOf(verifiedStatus.toInt())}; String[] args = new String[]{id.serialize(), Base64.encodeBytes(identityKey.serialize()), String.valueOf(verifiedStatus.toInt())};

View File

@ -119,7 +119,7 @@ public class IdentityUtil {
} }
} }
public static void markIdentityUpdate(Context context, Recipient recipient) { public static void markIdentityUpdate(@NonNull Context context, @NonNull RecipientId recipientId) {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context); SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context); GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
@ -128,15 +128,15 @@ public class IdentityUtil {
GroupDatabase.GroupRecord groupRecord; GroupDatabase.GroupRecord groupRecord;
while ((groupRecord = reader.getNext()) != null) { while ((groupRecord = reader.getNext()) != null) {
if (groupRecord.getMembers().contains(recipient.getId()) && groupRecord.isActive()) { if (groupRecord.getMembers().contains(recipientId) && groupRecord.isActive()) {
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, time, null, Optional.of(groupRecord.getId()), 0, false); IncomingTextMessage incoming = new IncomingTextMessage(recipientId, 1, time, time, null, Optional.of(groupRecord.getId()), 0, false);
IncomingIdentityUpdateMessage groupUpdate = new IncomingIdentityUpdateMessage(incoming); IncomingIdentityUpdateMessage groupUpdate = new IncomingIdentityUpdateMessage(incoming);
smsDatabase.insertMessageInbox(groupUpdate); smsDatabase.insertMessageInbox(groupUpdate);
} }
} }
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, -1, null, Optional.absent(), 0, false); IncomingTextMessage incoming = new IncomingTextMessage(recipientId, 1, time, -1, null, Optional.absent(), 0, false);
IncomingIdentityUpdateMessage individualUpdate = new IncomingIdentityUpdateMessage(incoming); IncomingIdentityUpdateMessage individualUpdate = new IncomingIdentityUpdateMessage(incoming);
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(individualUpdate); Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(individualUpdate);