Get authoritative profile keys from group changes only.

This commit is contained in:
Alan Evans
2020-08-03 16:12:02 -03:00
committed by Greyson Parrelli
parent 17c0364eda
commit 26868ae668
6 changed files with 425 additions and 135 deletions

View File

@@ -4,6 +4,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.profiles.ProfileKey;
@@ -30,38 +31,62 @@ public final class ProfileKeySet {
private final Map<UUID, ProfileKey> authoritativeProfileKeys = new LinkedHashMap<>();
/**
* Add new profile keys from the group state.
* Add new profile keys from a group change.
* <p>
* If the change came from the member whose profile key is changing then it is regarded as
* authoritative.
*/
public void addKeysFromGroupState(@NonNull DecryptedGroup group,
@Nullable UUID changeSource)
{
public void addKeysFromGroupChange(@NonNull DecryptedGroupChange change) {
UUID editor = UuidUtil.fromByteStringOrNull(change.getEditor());
for (DecryptedMember member : change.getNewMembersList()) {
addMemberKey(member, editor);
}
for (DecryptedMember member : change.getPromotePendingMembersList()) {
addMemberKey(member, editor);
}
for (DecryptedMember member : change.getModifiedProfileKeysList()) {
addMemberKey(member, editor);
}
}
/**
* Add new profile keys from the group state.
* <p>
* Profile keys found in group state are never authoritative as the change cannot be easily
* attributed to a member and it's possible that the group is out of date. So profile keys
* gathered from a group state can only be used to fill in gaps in knowledge.
*/
public void addKeysFromGroupState(@NonNull DecryptedGroup group) {
for (DecryptedMember member : group.getMembersList()) {
UUID memberUuid = UuidUtil.fromByteString(member.getUuid());
addMemberKey(member, null);
}
}
if (UuidUtil.UNKNOWN_UUID.equals(memberUuid)) {
Log.w(TAG, "Seen unknown member UUID");
continue;
}
private void addMemberKey(@NonNull DecryptedMember member, @Nullable UUID changeSource) {
UUID memberUuid = UuidUtil.fromByteString(member.getUuid());
ProfileKey profileKey;
try {
profileKey = new ProfileKey(member.getProfileKey().toByteArray());
} catch (InvalidInputException e) {
Log.w(TAG, "Bad profile key in group");
continue;
}
if (UuidUtil.UNKNOWN_UUID.equals(memberUuid)) {
Log.w(TAG, "Seen unknown member UUID");
return;
}
if (changeSource != null) {
Log.d(TAG, String.format("Change %s by %s", memberUuid, changeSource));
ProfileKey profileKey;
try {
profileKey = new ProfileKey(member.getProfileKey().toByteArray());
} catch (InvalidInputException e) {
Log.w(TAG, "Bad profile key in group");
return;
}
if (changeSource.equals(memberUuid)) {
authoritativeProfileKeys.put(memberUuid, profileKey);
profileKeys.remove(memberUuid);
} else {
if (!authoritativeProfileKeys.containsKey(memberUuid)) {
profileKeys.put(memberUuid, profileKey);
}
}
if (memberUuid.equals(changeSource)) {
authoritativeProfileKeys.put(memberUuid, profileKey);
profileKeys.remove(memberUuid);
} else {
if (!authoritativeProfileKeys.containsKey(memberUuid)) {
profileKeys.put(memberUuid, profileKey);
}
}
}

View File

@@ -7,8 +7,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.google.protobuf.ByteString;
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember;
@@ -16,8 +14,6 @@ import org.signal.storageservice.protos.groups.local.DecryptedPendingMember;
import org.signal.zkgroup.VerificationFailedException;
import org.signal.zkgroup.groups.GroupMasterKey;
import org.signal.zkgroup.groups.GroupSecretParams;
import org.signal.zkgroup.util.UUIDUtil;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.MmsDatabase;
@@ -320,9 +316,11 @@ public final class GroupsV2StateProcessor {
final ProfileKeySet profileKeys = new ProfileKeySet();
for (ServerGroupLogEntry entry : globalGroupState.getServerHistory()) {
Optional<UUID> editor = DecryptedGroupUtil.editorUuid(entry.getChange());
if (editor.isPresent() && entry.getGroup() != null) {
profileKeys.addKeysFromGroupState(entry.getGroup(), editor.get());
if (entry.getGroup() != null) {
profileKeys.addKeysFromGroupState(entry.getGroup());
}
if (entry.getChange() != null) {
profileKeys.addKeysFromGroupChange(entry.getChange());
}
}