From a2c3b5d64ef9277f511a03f8cd903505f83e6733 Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Mon, 31 Jul 2023 10:28:18 -0700 Subject: [PATCH] Adopt libsignal 0.30.0 and ServiceIds for group members. Co-authored-by: Greyson Parrelli --- .../ConversationSettingsRepository.kt | 4 +- .../conversation/ConversationUpdateItem.java | 15 +- .../securesms/database/GroupTable.kt | 54 +++-- .../securesms/database/MessageTable.kt | 4 +- .../securesms/database/model/GroupRecord.kt | 2 +- .../model/GroupsV2UpdateMessageProducer.java | 55 ++--- .../database/model/MessageRecord.java | 2 +- .../securesms/groups/GroupManager.java | 2 +- .../securesms/groups/GroupManagerV2.java | 27 ++- .../securesms/groups/GroupProtoUtil.java | 17 +- .../groups/GroupsV2Authorization.java | 4 +- .../securesms/groups/LiveGroup.java | 2 +- .../groups/v2/GroupCandidateHelper.java | 2 +- .../v2/processing/GroupsV2StateProcessor.java | 14 +- .../jobs/PushGroupSilentUpdateSendJob.java | 18 +- .../securesms/mms/MessageGroupContext.java | 23 +- .../webrtc/links/SignalCallLinkManager.kt | 6 +- .../securesms/util/ProfileUtil.java | 2 +- .../securesms/database/GV2Transformer.kt | 4 +- .../securesms/database/GroupTestUtil.kt | 6 +- .../GroupsV2UpdateMessageProducerTest.java | 2 +- .../securesms/groups/v2/ChangeBuilder.java | 4 +- .../databaseprotos/DecryptedGroupHelper.kt | 7 +- dependencies.gradle | 2 +- gradle/verification-metadata.xml | 44 +--- .../api/SignalServiceAccountManager.java | 8 +- .../api/SignalServiceMessageReceiver.java | 19 +- .../api/groupsv2/DecryptedGroupUtil.java | 135 ++++++------ .../api/groupsv2/GroupCandidate.java | 22 +- .../api/groupsv2/GroupChangeReconstruct.java | 74 +++---- .../api/groupsv2/GroupChangeUtil.java | 56 ++--- .../api/groupsv2/GroupsV2Api.java | 9 +- .../api/groupsv2/GroupsV2Operations.java | 203 ++++++++++-------- .../signalservice/api/push/ServiceId.kt | 43 ++-- .../api/services/ProfileService.java | 12 +- .../internal/push/PushServiceSocket.java | 12 +- .../src/main/proto/DecryptedGroups.proto | 18 +- .../api/groupsv2/DecryptedGroupUtilTest.java | 59 ++--- .../DecryptedGroupUtil_apply_Test.java | 2 +- .../groupsv2/GroupsV2Operations_ban_Test.java | 17 +- ...roupsV2Operations_decrypt_change_Test.java | 106 ++++----- ...GroupsV2Operations_decrypt_group_Test.java | 76 +++---- .../api/groupsv2/ProtoTestUtils.java | 6 +- .../api/groupsv2/TestZkGroupServer.java | 6 +- 44 files changed, 613 insertions(+), 592 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsRepository.kt index fe39811a00..e6fd722fde 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsRepository.kt @@ -153,8 +153,8 @@ class ConversationSettingsRepository( if (groupRecord.isV2Group) { val decryptedGroup: DecryptedGroup = groupRecord.requireV2GroupProperties().decryptedGroup val pendingMembers: List = decryptedGroup.pendingMembersList - .map(DecryptedPendingMember::getUuid) - .map(GroupProtoUtil::uuidByteStringToRecipientId) + .map(DecryptedPendingMember::getServiceIdBinary) + .map(GroupProtoUtil::serviceIdBinaryToRecipientId) val members = mutableListOf() diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java index 9e6ba2ed6e..b61aa6d0a9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java @@ -50,6 +50,7 @@ import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import org.thoughtcrime.securesms.verify.VerifyIdentityActivity; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceId.ACI; import java.util.Collection; @@ -291,11 +292,11 @@ public final class ConversationUpdateItem extends FrameLayout private final Observer updater; - private LiveGroup liveGroup; - private LiveData liveIsSelfAdmin; - private LiveData> liveBannedMembers; - private LiveData> liveFullMembers; - private Recipient conversationRecipient; + private LiveGroup liveGroup; + private LiveData liveIsSelfAdmin; + private LiveData> liveBannedMembers; + private LiveData> liveFullMembers; + private Recipient conversationRecipient; GroupDataManager() { this.updater = unused -> update(); @@ -341,9 +342,9 @@ public final class ConversationUpdateItem extends FrameLayout return false; } - Set bannedMembers = liveBannedMembers.getValue(); + Set bannedMembers = liveBannedMembers.getValue(); if (bannedMembers != null) { - return recipient.getServiceId().isPresent() && bannedMembers.contains(recipient.requireServiceId().getRawUuid()); + return recipient.getServiceId().isPresent() && bannedMembers.contains(recipient.requireServiceId()); } return false; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/GroupTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/GroupTable.kt index eb229c6dab..cac4ca9ab7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/GroupTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/GroupTable.kt @@ -60,7 +60,6 @@ import org.whispersystems.signalservice.api.util.UuidUtil import java.io.Closeable import java.security.SecureRandom import java.util.Optional -import java.util.UUID import java.util.stream.Collectors import javax.annotation.CheckReturnValue @@ -861,8 +860,8 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT writableDatabase.withinTransaction { db -> val record = getGroup(groupIdV1).get() - val newMembers: MutableList = DecryptedGroupUtil.membersToUuidList(decryptedGroup.membersList).toRecipientIds() - val pendingMembers: List = DecryptedGroupUtil.pendingToUuidList(decryptedGroup.pendingMembersList).toRecipientIds() + val newMembers: MutableList = DecryptedGroupUtil.membersToServiceIdList(decryptedGroup.membersList).toRecipientIds() + val pendingMembers: List = DecryptedGroupUtil.pendingToServiceIdList(decryptedGroup.pendingMembersList).toRecipientIds() newMembers.addAll(pendingMembers) val droppedMembers: List = SetUtil.difference(record.members, newMembers).toList() @@ -915,11 +914,11 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT val change = GroupChangeReconstruct.reconstructGroupChange(existingGroup.get().requireV2GroupProperties().decryptedGroup, decryptedGroup) - val addedMembers: Set = DecryptedGroupUtil.membersToUuidList(change.newMembersList).toRecipientIds().toSet() - val removedMembers: Set = DecryptedGroupUtil.removedMembersUuidList(change).toRecipientIds().toSet() - val addedInvites: Set = DecryptedGroupUtil.pendingToUuidList(change.newPendingMembersList).toRecipientIds().toSet() - val removedInvites: Set = DecryptedGroupUtil.removedPendingMembersUuidList(change).toRecipientIds().toSet() - val acceptedInvites: Set = DecryptedGroupUtil.membersToUuidList(change.promotePendingMembersList).toRecipientIds().toSet() + val addedMembers: Set = DecryptedGroupUtil.membersToServiceIdList(change.newMembersList).toRecipientIds().toSet() + val removedMembers: Set = DecryptedGroupUtil.removedMembersServiceIdList(change).toRecipientIds().toSet() + val addedInvites: Set = DecryptedGroupUtil.pendingToServiceIdList(change.newPendingMembersList).toRecipientIds().toSet() + val removedInvites: Set = DecryptedGroupUtil.removedPendingMembersServiceIdList(change).toRecipientIds().toSet() + val acceptedInvites: Set = DecryptedGroupUtil.membersToServiceIdList(change.promotePendingMembersList).toRecipientIds().toSet() unmigratedV1Members -= addedMembers unmigratedV1Members -= removedMembers @@ -934,7 +933,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT if (existingGroup.isPresent && existingGroup.get().isV2Group) { val change = GroupChangeReconstruct.reconstructGroupChange(existingGroup.get().requireV2GroupProperties().decryptedGroup, decryptedGroup) - val removed: List = DecryptedGroupUtil.removedMembersUuidList(change) + val removed: List = DecryptedGroupUtil.removedMembersServiceIdList(change) if (removed.isNotEmpty()) { val distributionId = existingGroup.get().distributionId!! @@ -1208,8 +1207,8 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT DecryptedGroup.parseFrom(decryptedGroupBytes) } - val bannedMembers: Set by lazy { - DecryptedGroupUtil.bannedMembersToUuidSet(decryptedGroup.bannedMembersList) + val bannedMembers: Set by lazy { + DecryptedGroupUtil.bannedMembersToServiceIdSet(decryptedGroup.bannedMembersList) } fun isAdmin(recipient: Recipient): Boolean { @@ -1243,7 +1242,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT } if (memberLevel.isAbsent()) { - memberLevel = DecryptedGroupUtil.findPendingByUuid(decryptedGroup.pendingMembersList, serviceId.get().rawUuid) + memberLevel = DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.pendingMembersList, serviceId.get()) .map { MemberLevel.PENDING_MEMBER } } @@ -1265,7 +1264,8 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT fun getMemberRecipientIds(memberSet: MemberSet): List { val includeSelf = memberSet.includeSelf - val selfAciUuid = SignalStore.account().requireAci().rawUuid + val selfAci = SignalStore.account().requireAci() + val selfAciUuid = selfAci.rawUuid val recipients: MutableList = ArrayList(decryptedGroup.membersCount + decryptedGroup.pendingMembersCount) var unknownMembers = 0 @@ -1280,11 +1280,11 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT } if (memberSet.includePending) { - for (uuid in DecryptedGroupUtil.pendingToUuidList(decryptedGroup.pendingMembersList)) { - if (UuidUtil.UNKNOWN_UUID == uuid) { + for (serviceId in DecryptedGroupUtil.pendingToServiceIdList(decryptedGroup.pendingMembersList)) { + if (serviceId.isUnknown) { unknownPending++ - } else if (includeSelf || selfAciUuid != uuid) { - recipients += RecipientId.from(ACI.from(uuid)) + } else if (includeSelf || selfAci != serviceId) { + recipients += RecipientId.from(serviceId) } } } @@ -1378,11 +1378,11 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT val aci = SignalStore.account().requireAci() return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.membersList, aci.rawUuid).isPresent || - DecryptedGroupUtil.findPendingByUuid(decryptedGroup.pendingMembersList, aci.rawUuid).isPresent + DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.pendingMembersList, aci).isPresent } - private fun List.toRecipientIds(): MutableList { - return uuidsToRecipientIds(this) + private fun List.toRecipientIds(): MutableList { + return serviceIdsToRecipientIds(this.asSequence()) } private fun Collection.serialize(): String { @@ -1398,15 +1398,14 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT } } - private fun uuidsToRecipientIds(uuids: List): MutableList { - return uuids - .asSequence() - .map { uuid -> - if (uuid == UuidUtil.UNKNOWN_UUID) { + private fun serviceIdsToRecipientIds(serviceIds: Sequence): MutableList { + return serviceIds + .map { serviceId -> + if (serviceId.isUnknown) { Log.w(TAG, "Saw an unknown UUID when mapping to RecipientIds!") null } else { - val id = RecipientId.from(ACI.from(uuid)) + val id = RecipientId.from(serviceId) val remapped = RemappedRecords.getInstance().getRecipient(id) if (remapped.isPresent) { Log.w(TAG, "Saw that $id remapped to $remapped. Using the mapping.") @@ -1422,8 +1421,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT } private fun getV2GroupMembers(decryptedGroup: DecryptedGroup, shouldRetry: Boolean): List { - val uuids: List = DecryptedGroupUtil.membersToUuidList(decryptedGroup.membersList) - val ids: List = uuidsToRecipientIds(uuids) + val ids: List = DecryptedGroupUtil.membersToServiceIdList(decryptedGroup.membersList).toRecipientIds() return if (RemappedRecords.getInstance().areAnyRemapped(ids)) { if (shouldRetry) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt index 1bd13d5684..b1417a8495 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt @@ -142,7 +142,6 @@ import org.thoughtcrime.securesms.util.Util import org.thoughtcrime.securesms.util.isStory import org.whispersystems.signalservice.api.messages.multidevice.ReadMessage import org.whispersystems.signalservice.api.push.ServiceId -import org.whispersystems.signalservice.api.push.ServiceId.ACI import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage import java.io.Closeable import java.io.IOException @@ -3089,10 +3088,9 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat val members: MutableSet = mutableSetOf() if (message.isGroupUpdate && message.isV2Group) { - // TODO [greyson][ServiceId] pending members could be ACI's or PNI's members += message.requireGroupV2Properties().allActivePendingAndRemovedMembers .distinct() - .map { uuid -> RecipientId.from(ACI.from(uuid)) } + .map { serviceId -> RecipientId.from(serviceId) } .toList() members -= Recipient.self().id diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupRecord.kt b/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupRecord.kt index 3113866d89..387c11a09b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupRecord.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupRecord.kt @@ -176,7 +176,7 @@ class GroupRecord( if (isV2Group) { val serviceId = recipient.serviceId if (serviceId.isPresent) { - return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().decryptedGroup.pendingMembersList, serviceId.get().rawUuid) + return DecryptedGroupUtil.findPendingByServiceId(requireV2GroupProperties().decryptedGroup.pendingMembersList, serviceId.get()) .isPresent } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducer.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducer.java index 684d3bb3a9..91a33d4b9f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducer.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducer.java @@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.util.ExpirationUtil; import org.thoughtcrime.securesms.util.SpanUtil; import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.api.push.ServiceIds; import org.whispersystems.signalservice.api.util.UuidUtil; @@ -72,9 +73,9 @@ final class GroupsV2UpdateMessageProducer { * When the revision of the group is 0, the change is very noisy and only the editor is useful. */ UpdateDescription describeNewGroup(@NonNull DecryptedGroup group, @NonNull DecryptedGroupChange decryptedGroupChange) { - Optional selfPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfIds.getAci().getRawUuid()); + Optional selfPending = DecryptedGroupUtil.findPendingByServiceId(group.getPendingMembersList(), selfIds.getAci()); if (!selfPending.isPresent() && selfIds.getPni() != null) { - selfPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfIds.getPni().getRawUuid()); + selfPending = DecryptedGroupUtil.findPendingByServiceId(group.getPendingMembersList(), selfIds.getPni()); } if (selfPending.isPresent()) { @@ -310,13 +311,13 @@ final class GroupsV2UpdateMessageProducer { int notYouInviteCount = 0; for (DecryptedPendingMember invitee : change.getNewPendingMembersList()) { - boolean newMemberIsYou = selfIds.matches(invitee.getUuid()); + boolean newMemberIsYou = selfIds.matches(invitee.getServiceIdBinary()); if (newMemberIsYou) { updates.add(0, updateDescription(R.string.MessageRecord_s_invited_you_to_the_group, change.getEditor(), R.drawable.ic_update_group_add_16)); } else { if (editorIsYou) { - updates.add(updateDescription(R.string.MessageRecord_you_invited_s_to_the_group, invitee.getUuid(), R.drawable.ic_update_group_add_16)); + updates.add(updateDescription(R.string.MessageRecord_you_invited_s_to_the_group, invitee.getServiceIdBinary(), R.drawable.ic_update_group_add_16)); } else { notYouInviteCount++; } @@ -332,7 +333,7 @@ final class GroupsV2UpdateMessageProducer { int notYouInviteCount = 0; for (DecryptedPendingMember invitee : change.getNewPendingMembersList()) { - boolean newMemberIsYou = selfIds.matches(invitee.getUuid()); + boolean newMemberIsYou = selfIds.matches(invitee.getServiceIdBinary()); if (newMemberIsYou) { UUID uuid = UuidUtil.fromByteStringOrUnknown(invitee.getAddedByUuid()); @@ -357,14 +358,14 @@ final class GroupsV2UpdateMessageProducer { int notDeclineCount = 0; for (DecryptedPendingMemberRemoval invitee : change.getDeletePendingMembersList()) { - boolean decline = invitee.getUuid().equals(change.getEditor()); + boolean decline = invitee.getServiceIdBinary().equals(change.getEditor()); if (decline) { if (editorIsYou) { updates.add(updateDescription(context.getString(R.string.MessageRecord_you_declined_the_invitation_to_the_group), R.drawable.ic_update_group_decline_16)); } else { updates.add(updateDescription(context.getString(R.string.MessageRecord_someone_declined_an_invitation_to_the_group), R.drawable.ic_update_group_decline_16)); } - } else if (selfIds.matches(invitee.getUuid())) { + } else if (selfIds.matches(invitee.getServiceIdBinary())) { updates.add(updateDescription(R.string.MessageRecord_s_revoked_your_invitation_to_the_group, change.getEditor(), R.drawable.ic_update_group_decline_16)); } else { notDeclineCount++; @@ -384,7 +385,7 @@ final class GroupsV2UpdateMessageProducer { int notDeclineCount = 0; for (DecryptedPendingMemberRemoval invitee : change.getDeletePendingMembersList()) { - boolean inviteeWasYou = selfIds.matches(invitee.getUuid()); + boolean inviteeWasYou = selfIds.matches(invitee.getServiceIdBinary()); if (inviteeWasYou) { updates.add(updateDescription(context.getString(R.string.MessageRecord_an_admin_revoked_your_invitation_to_the_group), R.drawable.ic_update_group_decline_16)); @@ -817,14 +818,14 @@ final class GroupsV2UpdateMessageProducer { } private UpdateDescription updateDescription(@StringRes int stringRes, - @NonNull ByteString uuid1Bytes, + @NonNull ByteString serviceId1Bytes, @DrawableRes int iconResource) { - ACI aci = ACI.parseOrUnknown(uuid1Bytes); - RecipientId recipientId = RecipientId.from(aci); + ACI serviceId = ACI.parseOrUnknown(serviceId1Bytes); + RecipientId recipientId = RecipientId.from(serviceId); return UpdateDescription.mentioning( - Collections.singletonList(aci), + Collections.singletonList(serviceId), () -> { List recipientIdList = Collections.singletonList(recipientId); String templateString = context.getString(stringRes, makePlaceholders(recipientIdList, null)); @@ -835,18 +836,18 @@ final class GroupsV2UpdateMessageProducer { } private UpdateDescription updateDescription(@StringRes int stringRes, - @NonNull ByteString uuid1Bytes, - @NonNull ByteString uuid2Bytes, + @NonNull ByteString serviceId1Bytes, + @NonNull ByteString serviceId2Bytes, @DrawableRes int iconResource) { - ACI aci1 = ACI.parseOrUnknown(uuid1Bytes); - ACI aci2 = ACI.parseOrUnknown(uuid2Bytes); + ACI serviceId1 = ACI.parseOrUnknown(serviceId1Bytes); + ACI serviceId2 = ACI.parseOrUnknown(serviceId2Bytes); - RecipientId recipientId1 = RecipientId.from(aci1); - RecipientId recipientId2 = RecipientId.from(aci2); + RecipientId recipientId1 = RecipientId.from(serviceId1); + RecipientId recipientId2 = RecipientId.from(serviceId2); return UpdateDescription.mentioning( - Arrays.asList(aci1, aci2), + Arrays.asList(serviceId1, serviceId2), () -> { List recipientIdList = Arrays.asList(recipientId1, recipientId2); String templateString = context.getString(stringRes, makePlaceholders(recipientIdList, null)); @@ -858,15 +859,15 @@ final class GroupsV2UpdateMessageProducer { } private UpdateDescription updateDescription(@StringRes int stringRes, - @NonNull ByteString uuid1Bytes, + @NonNull ByteString serviceId1Bytes, @NonNull Object formatArg, @DrawableRes int iconResource) { - ACI aci = ACI.parseOrUnknown(uuid1Bytes); - RecipientId recipientId = RecipientId.from(aci); + ACI serviceId = ACI.parseOrUnknown(serviceId1Bytes); + RecipientId recipientId = RecipientId.from(serviceId); return UpdateDescription.mentioning( - Collections.singletonList(aci), + Collections.singletonList(serviceId), () -> { List recipientIdList = Collections.singletonList(recipientId); String templateString = context.getString(stringRes, makePlaceholders(recipientIdList, Collections.singletonList(formatArg))); @@ -879,15 +880,15 @@ final class GroupsV2UpdateMessageProducer { private UpdateDescription updateDescription(@PluralsRes int stringRes, int quantity, - @NonNull ByteString uuid1Bytes, + @NonNull ByteString serviceId1Bytes, @NonNull Object formatArg, @DrawableRes int iconResource) { - ACI aci = ACI.parseOrUnknown(uuid1Bytes); - RecipientId recipientId = RecipientId.from(aci); + ACI serviceId = ACI.parseOrUnknown(serviceId1Bytes); + RecipientId recipientId = RecipientId.from(serviceId); return UpdateDescription.mentioning( - Collections.singletonList(aci), + Collections.singletonList(serviceId), () -> { List recipientIdList = Collections.singletonList(recipientId); String templateString = context.getResources().getQuantityString(stringRes, quantity, makePlaceholders(recipientIdList, Collections.singletonList(formatArg))); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java index b6d3fa4964..7d1f33b42b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java @@ -346,7 +346,7 @@ public abstract class MessageRecord extends DisplayRecord { } DecryptedGroup groupState = decryptedGroupV2Context.getGroupState(); - boolean invited = DecryptedGroupUtil.findPendingByUuid(groupState.getPendingMembersList(), SignalStore.account().requireAci().getRawUuid()).isPresent(); + boolean invited = DecryptedGroupUtil.findPendingByServiceId(groupState.getPendingMembersList(), SignalStore.account().requireAci()).isPresent(); if (decryptedGroupV2Context.hasChange()) { UUID changeEditor = UuidUtil.fromByteStringOrNull(decryptedGroupV2Context.getChange().getEditor()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java index 1a80182132..35f66a1fa3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java @@ -336,7 +336,7 @@ public final class GroupManager { throws GroupChangeBusyException, IOException, GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException { try (GroupManagerV2.GroupEditor editor = new GroupManagerV2(context).edit(groupId.requireV2())) { - editor.unban(Collections.singleton(Recipient.resolved(recipientId).requireServiceId().getRawUuid())); + editor.unban(Collections.singleton(Recipient.resolved(recipientId).requireServiceId())); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2.java index 6a113dafcc..795dccd57f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2.java @@ -176,7 +176,7 @@ final class GroupManagerV2 { Map uuidCipherTexts = new HashMap<>(); for (Recipient recipient : recipients) { - uuidCipherTexts.put(recipient.requireServiceId().getRawUuid(), clientZkGroupCipher.encryptUuid(recipient.requireServiceId().getRawUuid())); + uuidCipherTexts.put(recipient.requireServiceId().getRawUuid(), clientZkGroupCipher.encrypt(recipient.requireServiceId().getLibSignalServiceId())); } return uuidCipherTexts; @@ -343,7 +343,7 @@ final class GroupManagerV2 { } @WorkerThread - @NonNull GroupManager.GroupActionResult addMembers(@NonNull Collection newMembers, @NonNull Set bannedMembers) + @NonNull GroupManager.GroupActionResult addMembers(@NonNull Collection newMembers, @NonNull Set bannedMembers) throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException, MembershipNotSuitableForV2Exception { if (!GroupsV2CapabilityChecker.allHaveServiceId(newMembers)) { @@ -356,7 +356,7 @@ final class GroupManagerV2 { groupCandidates = GroupCandidate.withoutExpiringProfileKeyCredentials(groupCandidates); } - return commitChangeWithConflictResolution(selfAci, groupOperations.createModifyGroupMembershipChange(groupCandidates, bannedMembers, selfAci.getRawUuid())); + return commitChangeWithConflictResolution(selfAci, groupOperations.createModifyGroupMembershipChange(groupCandidates, bannedMembers, selfAci)); } @WorkerThread @@ -454,7 +454,7 @@ final class GroupManagerV2 { throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException { Recipient recipient = Recipient.resolved(recipientId); - return commitChangeWithConflictResolution(selfAci, groupOperations.createChangeMemberRole(recipient.requireServiceId().getRawUuid(), admin ? Member.Role.ADMINISTRATOR : Member.Role.DEFAULT)); + return commitChangeWithConflictResolution(selfAci, groupOperations.createChangeMemberRole(recipient.requireAci(), admin ? Member.Role.ADMINISTRATOR : Member.Role.DEFAULT)); } @WorkerThread @@ -464,8 +464,8 @@ final class GroupManagerV2 { GroupRecord groupRecord = groupDatabase.requireGroup(groupId); DecryptedGroup decryptedGroup = groupRecord.requireV2GroupProperties().getDecryptedGroup(); Optional selfMember = DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), selfAci.getRawUuid()); - Optional aciPendingMember = DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), selfAci.getRawUuid()); - Optional pniPendingMember = DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), selfPni.getRawUuid()); + Optional aciPendingMember = DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.getPendingMembersList(), selfAci); + Optional pniPendingMember = DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.getPendingMembersList(), selfPni); Optional selfPendingMember = Optional.empty(); ServiceId serviceId = selfAci; @@ -555,8 +555,8 @@ final class GroupManagerV2 { return null; } - Optional aciInPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfAci.getRawUuid()); - Optional pniInPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfPni.getRawUuid()); + Optional aciInPending = DecryptedGroupUtil.findPendingByServiceId(group.getPendingMembersList(), selfAci); + Optional pniInPending = DecryptedGroupUtil.findPendingByServiceId(group.getPendingMembersList(), selfPni); GroupCandidate groupCandidate = groupCandidateHelper.recipientIdToCandidate(Recipient.self().getId()); @@ -584,10 +584,10 @@ final class GroupManagerV2 { return commitChangeWithConflictResolution(selfAci, groupOperations.createBanUuidsChange(Collections.singleton(uuid), rejectJoinRequest, v2GroupProperties.getDecryptedGroup().getBannedMembersList())); } - public GroupManager.GroupActionResult unban(Set uuids) + public GroupManager.GroupActionResult unban(Set serviceIds) throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException { - return commitChangeWithConflictResolution(selfAci, groupOperations.createUnbanUuidsChange(uuids)); + return commitChangeWithConflictResolution(selfAci, groupOperations.createUnbanServiceIdsChange(serviceIds)); } @WorkerThread @@ -704,7 +704,7 @@ final class GroupManagerV2 { GroupChange.Actions changeActions = change.build(); return GroupChangeUtil.resolveConflict(groupUpdateResult.getLatestServer(), - groupOperations.decryptChange(changeActions, authServiceId.getRawUuid()), + groupOperations.decryptChange(changeActions, authServiceId), changeActions); } catch (VerificationFailedException | InvalidGroupStateException ex) { throw new GroupChangeFailedException(ex); @@ -1331,9 +1331,8 @@ final class GroupManagerV2 { } private static @NonNull List getPendingMemberRecipientIds(@NonNull List newPendingMembersList) { - // TODO [greyson][ServiceId] Pending members can be ACI's or PNI's - return Stream.of(DecryptedGroupUtil.pendingToUuidList(newPendingMembersList)) - .map(uuid -> RecipientId.from(ACI.from(uuid))) + return Stream.of(DecryptedGroupUtil.pendingToServiceIdList(newPendingMembersList)) + .map(serviceId -> RecipientId.from(serviceId)) .toList(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupProtoUtil.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupProtoUtil.java index 7c06d58f3c..6351e0012d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupProtoUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupProtoUtil.java @@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.whispersystems.signalservice.api.groupsv2.PartialDecryptedGroup; import org.whispersystems.signalservice.api.push.ServiceId; +import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.internal.push.SignalServiceProtos; @@ -30,17 +31,17 @@ public final class GroupProtoUtil { private GroupProtoUtil() { } - public static int findRevisionWeWereAdded(@NonNull PartialDecryptedGroup partialDecryptedGroup, @NonNull UUID uuid) + public static int findRevisionWeWereAdded(@NonNull PartialDecryptedGroup partialDecryptedGroup, @NonNull ACI self) throws GroupNotAMemberException { - ByteString bytes = UuidUtil.toByteString(uuid); + ByteString bytes = self.toByteString(); for (DecryptedMember decryptedMember : partialDecryptedGroup.getMembersList()) { if (decryptedMember.getUuid().equals(bytes)) { return decryptedMember.getJoinedAtRevision(); } } for (DecryptedPendingMember decryptedMember : partialDecryptedGroup.getPendingMembersList()) { - if (decryptedMember.getUuid().equals(bytes)) { + if (decryptedMember.getServiceIdBinary().equals(bytes)) { // Assume latest, we don't have any information about when pending members were invited return partialDecryptedGroup.getRevision(); } @@ -80,12 +81,12 @@ public final class GroupProtoUtil { @WorkerThread public static Recipient pendingMemberToRecipient(@NonNull Context context, @NonNull DecryptedPendingMember pendingMember) { - return pendingMemberServiceIdToRecipient(context, pendingMember.getUuid()); + return pendingMemberServiceIdToRecipient(context, pendingMember.getServiceIdBinary()); } @WorkerThread - public static Recipient pendingMemberServiceIdToRecipient(@NonNull Context context, @NonNull ByteString uuidByteString) { - ServiceId serviceId = ServiceId.parseOrThrow(uuidByteString); + public static Recipient pendingMemberServiceIdToRecipient(@NonNull Context context, @NonNull ByteString serviceIdBinary) { + ServiceId serviceId = ServiceId.parseOrThrow(serviceIdBinary); if (serviceId.isUnknown()) { return Recipient.UNKNOWN; @@ -95,8 +96,8 @@ public final class GroupProtoUtil { } @WorkerThread - public static @NonNull RecipientId uuidByteStringToRecipientId(@NonNull ByteString uuidByteString) { - ServiceId serviceId = ServiceId.parseOrThrow(uuidByteString); + public static @NonNull RecipientId serviceIdBinaryToRecipientId(@NonNull ByteString serviceIdBinary) { + ServiceId serviceId = ServiceId.parseOrThrow(serviceIdBinary); if (serviceId.isUnknown()) { return RecipientId.UNKNOWN; diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV2Authorization.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV2Authorization.java index 4c4de6a521..6977dcb92f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV2Authorization.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV2Authorization.java @@ -126,13 +126,13 @@ public class GroupsV2Authorization { } CallLinkAuthCredential credential = authCredentialResponse.receive( - Recipient.self().requireServiceId().getRawUuid(), + Recipient.self().requireAci().getLibSignalAci(), Instant.ofEpochSecond(todaySeconds), genericServerPublicParams ); return credential.present( - Recipient.self().requireServiceId().getRawUuid(), + Recipient.self().requireAci().getLibSignalAci(), Instant.ofEpochSecond(todaySeconds), genericServerPublicParams, callLinkSecretParams diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/LiveGroup.java b/app/src/main/java/org/thoughtcrime/securesms/groups/LiveGroup.java index e41287a6f0..51c2f39377 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/LiveGroup.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/LiveGroup.java @@ -144,7 +144,7 @@ public final class LiveGroup { return Transformations.map(groupRecord, g -> g.isAdmin(Recipient.self())); } - public LiveData> getBannedMembers() { + public LiveData> getBannedMembers() { return Transformations.map(groupRecord, g -> g.isV2Group() ? g.requireV2GroupProperties().getBannedMembers() : Collections.emptySet()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/v2/GroupCandidateHelper.java b/app/src/main/java/org/thoughtcrime/securesms/groups/v2/GroupCandidateHelper.java index 8344331aa2..8421819cf5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/v2/GroupCandidateHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/v2/GroupCandidateHelper.java @@ -51,7 +51,7 @@ public class GroupCandidateHelper { } Optional expiringProfileKeyCredential = Optional.ofNullable(recipient.getExpiringProfileKeyCredential()); - GroupCandidate candidate = new GroupCandidate(serviceId.getRawUuid(), expiringProfileKeyCredential); + GroupCandidate candidate = new GroupCandidate(serviceId, expiringProfileKeyCredential); if (!candidate.hasValidProfileKeyCredential()) { recipientTable.clearProfileKeyCredential(recipient.getId()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/v2/processing/GroupsV2StateProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/groups/v2/processing/GroupsV2StateProcessor.java index aba0807edc..409e408aa7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/v2/processing/GroupsV2StateProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/v2/processing/GroupsV2StateProcessor.java @@ -380,9 +380,7 @@ public class GroupsV2StateProcessor { boolean addedAsPendingMember = signedGroupChange.getNewPendingMembersList() .stream() - .map(DecryptedPendingMember::getUuid) - .map(UuidUtil::fromByteStringOrNull) - .filter(Objects::nonNull) + .map(DecryptedPendingMember::getServiceIdBinary) .anyMatch(serviceIds::matches); boolean addedAsRequestingMember = signedGroupChange.getNewRequestingMembersList() @@ -398,9 +396,7 @@ public class GroupsV2StateProcessor { private boolean notHavingInviteRevoked(@NonNull DecryptedGroupChange signedGroupChange) { boolean havingInviteRevoked = signedGroupChange.getDeletePendingMembersList() .stream() - .map(DecryptedPendingMemberRemoval::getUuid) - .map(UuidUtil::fromByteStringOrNull) - .filter(Objects::nonNull) + .map(DecryptedPendingMemberRemoval::getServiceIdBinary) .anyMatch(serviceIds::matches); return !havingInviteRevoked; @@ -434,7 +430,7 @@ public class GroupsV2StateProcessor { info("Latest revision or not a member, use latest only"); inputGroupState = new GlobalGroupState(localState, Collections.singletonList(new ServerGroupLogEntry(latestServerGroup.getFullyDecryptedGroup(), null))); } else { - int revisionWeWereAdded = GroupProtoUtil.findRevisionWeWereAdded(latestServerGroup, serviceIds.getAci().getRawUuid()); + int revisionWeWereAdded = GroupProtoUtil.findRevisionWeWereAdded(latestServerGroup, serviceIds.getAci()); int logsNeededFrom = localState != null ? Math.max(localState.getRevision(), revisionWeWereAdded) : revisionWeWereAdded; boolean includeFirstState = forceIncludeFirst || @@ -694,7 +690,7 @@ public class GroupsV2StateProcessor { } Optional selfAsMemberOptional = DecryptedGroupUtil.findMemberByUuid(newLocalState.getMembersList(), aci.getRawUuid()); - Optional selfAsPendingOptional = DecryptedGroupUtil.findPendingByUuid(newLocalState.getPendingMembersList(), aci.getRawUuid()); + Optional selfAsPendingOptional = DecryptedGroupUtil.findPendingByServiceId(newLocalState.getPendingMembersList(), aci); if (selfAsMemberOptional.isPresent()) { DecryptedMember selfAsMember = selfAsMemberOptional.get(); @@ -835,7 +831,7 @@ public class GroupsV2StateProcessor { if (changeEditor.isPresent()) { return changeEditor; } else { - Optional pendingByUuid = DecryptedGroupUtil.findPendingByUuid(decryptedGroupV2Context.getGroupState().getPendingMembersList(), aci.getRawUuid()); + Optional pendingByUuid = DecryptedGroupUtil.findPendingByServiceId(decryptedGroupV2Context.getGroupState().getPendingMembersList(), aci); if (pendingByUuid.isPresent()) { return Optional.ofNullable(UuidUtil.fromByteStringOrNull(pendingByUuid.get().getAddedByUuid())); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java index 6fe3e6e401..43f374823c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java @@ -33,6 +33,7 @@ import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil; import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import org.whispersystems.signalservice.api.util.UuidUtil; @@ -72,13 +73,18 @@ public final class PushGroupSilentUpdateSendJob extends BaseJob { @NonNull DecryptedGroup decryptedGroup, @NonNull OutgoingMessage groupMessage) { - List memberUuids = DecryptedGroupUtil.toUuidList(decryptedGroup.getMembersList()); - List pendingUuids = DecryptedGroupUtil.pendingToUuidList(decryptedGroup.getPendingMembersList()); + List memberUuids = DecryptedGroupUtil.toUuidList(decryptedGroup.getMembersList()); + List pendingServiceIds = DecryptedGroupUtil.pendingToServiceIdList(decryptedGroup.getPendingMembersList()); - Set recipients = Stream.concat(Stream.of(memberUuids), Stream.of(pendingUuids)) - .filter(uuid -> !UuidUtil.UNKNOWN_UUID.equals(uuid)) - .filter(uuid -> !SignalStore.account().requireAci().getRawUuid().equals(uuid)) - .map(uuid -> Recipient.externalPush(ACI.from(uuid))) + Stream memberServiceIds = Stream.of(memberUuids) + .filter(uuid -> !UuidUtil.UNKNOWN_UUID.equals(uuid)) + .filter(uuid -> !SignalStore.account().requireAci().getRawUuid().equals(uuid)) + .map(ACI::from); + Stream filteredPendingServiceIds = Stream.of(pendingServiceIds) + .filterNot(ServiceId::isUnknown); + + Set recipients = Stream.concat(memberServiceIds, filteredPendingServiceIds) + .map(serviceId -> Recipient.externalPush(serviceId)) .filter(recipient -> recipient.getRegistered() != RecipientTable.RegisteredState.NOT_REGISTERED) .map(Recipient::getId) .collect(Collectors.toSet()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java b/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java index 851d716439..b3b9f48e8a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java @@ -166,19 +166,18 @@ public final class MessageGroupContext { return decryptedGroupV2Context.getChange(); } - public @NonNull List getAllActivePendingAndRemovedMembers() { - LinkedList memberUuids = new LinkedList<>(); - DecryptedGroup groupState = decryptedGroupV2Context.getGroupState(); - DecryptedGroupChange groupChange = decryptedGroupV2Context.getChange(); + public @NonNull List getAllActivePendingAndRemovedMembers() { + DecryptedGroup groupState = decryptedGroupV2Context.getGroupState(); + DecryptedGroupChange groupChange = decryptedGroupV2Context.getChange(); - memberUuids.addAll(DecryptedGroupUtil.membersToUuidList(groupState.getMembersList())); - memberUuids.addAll(DecryptedGroupUtil.pendingToUuidList(groupState.getPendingMembersList())); - - memberUuids.addAll(DecryptedGroupUtil.removedMembersUuidList(groupChange)); - memberUuids.addAll(DecryptedGroupUtil.removedPendingMembersUuidList(groupChange)); - memberUuids.addAll(DecryptedGroupUtil.removedRequestingMembersUuidList(groupChange)); - - return UuidUtil.filterKnown(memberUuids); + return Stream.of(DecryptedGroupUtil.membersToServiceIdList(groupState.getMembersList()), + DecryptedGroupUtil.pendingToServiceIdList(groupState.getPendingMembersList()), + DecryptedGroupUtil.removedMembersServiceIdList(groupChange), + DecryptedGroupUtil.removedPendingMembersServiceIdList(groupChange), + DecryptedGroupUtil.removedRequestingMembersServiceIdList(groupChange)) + .flatMap(Stream::of) + .filterNot(ServiceId::isUnknown) + .toList(); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/links/SignalCallLinkManager.kt b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/links/SignalCallLinkManager.kt index d1fc094b44..f44a175f30 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/links/SignalCallLinkManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/links/SignalCallLinkManager.kt @@ -45,7 +45,7 @@ class SignalCallLinkManager( linkRootKey: ByteArray, roomId: ByteArray ): CreateCallLinkCredentialPresentation { - val userUuid = Recipient.self().requireAci().rawUuid + val userAci = Recipient.self().requireAci() val requestContext = CreateCallLinkCredentialRequestContext.forRoom(roomId) val request = requestContext.request @@ -60,7 +60,7 @@ class SignalCallLinkManager( val createCallLinkCredential: CreateCallLinkCredential = requestContext.receiveResponse( serviceResponse.result.get(), - userUuid, + userAci.libSignalAci, genericServerPublicParams ) @@ -68,7 +68,7 @@ class SignalCallLinkManager( return createCallLinkCredential.present( roomId, - userUuid, + userAci.libSignalAci, genericServerPublicParams, CallLinkSecretParams.deriveFromRootKey(linkRootKey) ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java index 1de5a2b211..90958d066a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java @@ -295,7 +295,7 @@ public final class ProfileUtil { Log.i(TAG, String.format("Updating profile key credential on recipient %s, fetching", recipient.getId())); Optional profileKeyCredentialOptional = ApplicationDependencies.getSignalServiceAccountManager() - .resolveProfileKeyCredential(recipient.requireServiceId(), profileKey, Locale.getDefault()); + .resolveProfileKeyCredential(recipient.requireAci(), profileKey, Locale.getDefault()); if (profileKeyCredentialOptional.isPresent()) { boolean updatedProfileKey = SignalDatabase.recipients().setProfileKeyCredential(recipient.getId(), profileKey, profileKeyCredentialOptional.get()); diff --git a/app/src/spinner/java/org/thoughtcrime/securesms/database/GV2Transformer.kt b/app/src/spinner/java/org/thoughtcrime/securesms/database/GV2Transformer.kt index 03ccbfc08d..a1eee10c3b 100644 --- a/app/src/spinner/java/org/thoughtcrime/securesms/database/GV2Transformer.kt +++ b/app/src/spinner/java/org/thoughtcrime/securesms/database/GV2Transformer.kt @@ -29,9 +29,9 @@ object GV2Transformer : ColumnTransformer { private fun DecryptedGroup.formatAsHtml(): String { val members: String = describeList(membersList, DecryptedMember::getUuid) - val pending: String = describeList(pendingMembersList, DecryptedPendingMember::getUuid) + val pending: String = describeList(pendingMembersList, DecryptedPendingMember::getServiceIdBinary) val requesting: String = describeList(requestingMembersList, DecryptedRequestingMember::getUuid) - val banned: String = describeList(bannedMembersList, DecryptedBannedMember::getUuid) + val banned: String = describeList(bannedMembersList, DecryptedBannedMember::getServiceIdBinary) return """ Revision: $revision diff --git a/app/src/test/java/org/thoughtcrime/securesms/database/GroupTestUtil.kt b/app/src/test/java/org/thoughtcrime/securesms/database/GroupTestUtil.kt index d82bf1c830..da9eb471a0 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/database/GroupTestUtil.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/database/GroupTestUtil.kt @@ -85,15 +85,15 @@ class GroupChangeData(private val revision: Int, private val groupOperations: Gr } fun source(serviceId: ServiceId) { - actionsBuilder.sourceUuid = groupOperations.encryptUuid(serviceId.rawUuid) + actionsBuilder.sourceUuid = groupOperations.encryptServiceId(serviceId) } fun deleteMember(serviceId: ServiceId) { - actionsBuilder.addDeleteMembers(GroupChange.Actions.DeleteMemberAction.newBuilder().setDeletedUserId(groupOperations.encryptUuid(serviceId.rawUuid))) + actionsBuilder.addDeleteMembers(GroupChange.Actions.DeleteMemberAction.newBuilder().setDeletedUserId(groupOperations.encryptServiceId(serviceId))) } fun modifyRole(serviceId: ServiceId, role: Member.Role) { - actionsBuilder.addModifyMemberRoles(GroupChange.Actions.ModifyMemberRoleAction.newBuilder().setUserId(groupOperations.encryptUuid(serviceId.rawUuid)).setRole(role)) + actionsBuilder.addModifyMemberRoles(GroupChange.Actions.ModifyMemberRoleAction.newBuilder().setUserId(groupOperations.encryptServiceId(serviceId)).setRole(role)) } } diff --git a/app/src/test/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducerTest.java b/app/src/test/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducerTest.java index c0c7cba479..05791d2d1b 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducerTest.java +++ b/app/src/test/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducerTest.java @@ -1475,7 +1475,7 @@ public final class GroupsV2UpdateMessageProducerTest { GroupStateBuilder invite(@NonNull UUID inviter, @NonNull UUID invitee) { builder.addPendingMembers(DecryptedPendingMember.newBuilder() - .setUuid(UuidUtil.toByteString(invitee)) + .setServiceIdBinary(UuidUtil.toByteString(invitee)) .setAddedByUuid(UuidUtil.toByteString(inviter))); return this; } diff --git a/app/src/test/java/org/thoughtcrime/securesms/groups/v2/ChangeBuilder.java b/app/src/test/java/org/thoughtcrime/securesms/groups/v2/ChangeBuilder.java index a0cf08119f..b40e95751d 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/groups/v2/ChangeBuilder.java +++ b/app/src/test/java/org/thoughtcrime/securesms/groups/v2/ChangeBuilder.java @@ -85,14 +85,14 @@ public final class ChangeBuilder { public ChangeBuilder inviteBy(@NonNull UUID potentialMember, @NonNull UUID inviter) { builder.addNewPendingMembers(DecryptedPendingMember.newBuilder() - .setUuid(UuidUtil.toByteString(potentialMember)) + .setServiceIdBinary(UuidUtil.toByteString(potentialMember)) .setAddedByUuid(UuidUtil.toByteString(inviter))); return this; } public ChangeBuilder uninvite(@NonNull UUID pendingMember) { builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() - .setUuid(UuidUtil.toByteString(pendingMember))); + .setServiceIdBinary(UuidUtil.toByteString(pendingMember))); return this; } diff --git a/app/src/testShared/org/thoughtcrime/securesms/database/model/databaseprotos/DecryptedGroupHelper.kt b/app/src/testShared/org/thoughtcrime/securesms/database/model/databaseprotos/DecryptedGroupHelper.kt index b6ff71b053..b7b8d488ba 100644 --- a/app/src/testShared/org/thoughtcrime/securesms/database/model/databaseprotos/DecryptedGroupHelper.kt +++ b/app/src/testShared/org/thoughtcrime/securesms/database/model/databaseprotos/DecryptedGroupHelper.kt @@ -9,7 +9,6 @@ import org.signal.storageservice.protos.groups.local.DecryptedPendingMember import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember import org.whispersystems.signalservice.api.push.ServiceId import org.whispersystems.signalservice.api.push.ServiceId.ACI -import org.whispersystems.signalservice.api.util.UuidUtil import org.whispersystems.signalservice.internal.push.SignalServiceProtos import java.util.UUID @@ -43,10 +42,6 @@ fun DecryptedGroupChange.Builder.addMember(aci: ACI) { addNewMembers(member(aci)) } -fun ServiceId.toByteString(): ByteString { - return UuidUtil.toByteString(rawUuid) -} - fun member(serviceId: UUID, role: Member.Role = Member.Role.DEFAULT, joinedAt: Int = 0): DecryptedMember { return member(ACI.from(serviceId), role, joinedAt) } @@ -67,6 +62,6 @@ fun requestingMember(serviceId: ServiceId): DecryptedRequestingMember { fun pendingMember(serviceId: ServiceId): DecryptedPendingMember { return DecryptedPendingMember.newBuilder() - .setUuid(serviceId.toByteString()) + .setServiceIdBinary(serviceId.toByteString()) .build() } diff --git a/dependencies.gradle b/dependencies.gradle index eb4caa57a9..60511a9b95 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -14,7 +14,7 @@ dependencyResolutionManagement { version('exoplayer', '2.19.0') version('glide', '4.13.2') version('kotlin', '1.8.10') - version('libsignal-client', '0.28.1') + version('libsignal-client', '0.30.0') version('mp4parser', '1.9.39') version('android-gradle-plugin', '8.0.2') version('accompanist', '0.28.0') diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 15f8e75895..29f3edb7ac 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -4992,44 +4992,20 @@ https://docs.gradle.org/current/userguide/dependency_verification.html - - - + + + - - + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java index 117f73b1fb..f734e48e80 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java @@ -740,23 +740,23 @@ public class SignalServiceAccountManager { new ProfileCipherOutputStreamFactory(profileKey)); } - return this.pushServiceSocket.writeProfile(new SignalServiceProfileWrite(profileKey.getProfileKeyVersion(aci.getRawUuid()).serialize(), + return this.pushServiceSocket.writeProfile(new SignalServiceProfileWrite(profileKey.getProfileKeyVersion(aci.getLibSignalAci()).serialize(), ciphertextName, ciphertextAbout, ciphertextEmoji, ciphertextMobileCoinAddress, avatar.hasAvatar, avatar.keepTheSame, - profileKey.getCommitment(aci.getRawUuid()).serialize(), + profileKey.getCommitment(aci.getLibSignalAci()).serialize(), visibleBadgeIds), profileAvatarData); } - public Optional resolveProfileKeyCredential(ServiceId serviceId, ProfileKey profileKey, Locale locale) + public Optional resolveProfileKeyCredential(ACI serviceId, ProfileKey profileKey, Locale locale) throws NonSuccessfulResponseCodeException, PushNetworkException { try { - ProfileAndCredential credential = this.pushServiceSocket.retrieveVersionedProfileAndCredential(serviceId.getRawUuid(), profileKey, Optional.empty(), locale).get(10, TimeUnit.SECONDS); + ProfileAndCredential credential = this.pushServiceSocket.retrieveVersionedProfileAndCredential(serviceId, profileKey, Optional.empty(), locale).get(10, TimeUnit.SECONDS); return credential.getExpiringProfileKeyCredential(); } catch (InterruptedException | TimeoutException e) { throw new PushNetworkException(e); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java index 61eda77ff6..c8450ee2ce 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java @@ -20,6 +20,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceStickerManifes import org.whispersystems.signalservice.api.profiles.ProfileAndCredential; import org.whispersystems.signalservice.api.profiles.SignalServiceProfile; import org.whispersystems.signalservice.api.push.ServiceId; +import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException; import org.whispersystems.signalservice.api.util.CredentialsProvider; @@ -34,6 +35,7 @@ import org.whispersystems.signalservice.internal.sticker.StickerProtos; import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.internal.util.concurrent.FutureTransformers; import org.whispersystems.signalservice.internal.util.concurrent.ListenableFuture; +import org.whispersystems.signalservice.internal.util.concurrent.SettableFuture; import org.whispersystems.signalservice.internal.websocket.ResponseMapper; import java.io.File; @@ -96,13 +98,22 @@ public class SignalServiceMessageReceiver { SignalServiceProfile.RequestType requestType, Locale locale) { - ServiceId serviceId = address.getServiceId(); if (profileKey.isPresent()) { - if (requestType == SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL) { - return socket.retrieveVersionedProfileAndCredential(serviceId.getRawUuid(), profileKey.get(), unidentifiedAccess, locale); + ACI aci; + if (address.getServiceId() instanceof ACI) { + aci = (ACI) address.getServiceId(); } else { - return FutureTransformers.map(socket.retrieveVersionedProfile(serviceId.getRawUuid(), profileKey.get(), unidentifiedAccess, locale), profile -> { + // We shouldn't ever have a profile key for a non-ACI. + SettableFuture result = new SettableFuture<>(); + result.setException(new ClassCastException("retrieving a versioned profile requires an ACI")); + return result; + } + + if (requestType == SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL) { + return socket.retrieveVersionedProfileAndCredential(aci, profileKey.get(), unidentifiedAccess, locale); + } else { + return FutureTransformers.map(socket.retrieveVersionedProfile(aci, profileKey.get(), unidentifiedAccess, locale), profile -> { return new ProfileAndCredential(profile, SignalServiceProfile.RequestType.PROFILE, Optional.empty()); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/DecryptedGroupUtil.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/DecryptedGroupUtil.java index bbd879a09f..502432ff14 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/DecryptedGroupUtil.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/DecryptedGroupUtil.java @@ -15,6 +15,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval; import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.protos.groups.local.EnabledState; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceIds; import org.whispersystems.signalservice.api.util.UuidUtil; @@ -28,6 +29,8 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; +import javax.annotation.Nullable; + public final class DecryptedGroupUtil { private static final String TAG = DecryptedGroupUtil.class.getSimpleName(); @@ -42,18 +45,18 @@ public final class DecryptedGroupUtil { return uuidList; } - public static ArrayList membersToUuidList(Collection membersList) { - ArrayList uuidList = new ArrayList<>(membersList.size()); + public static ArrayList membersToServiceIdList(Collection membersList) { + ArrayList serviceIdList = new ArrayList<>(membersList.size()); for (DecryptedMember member : membersList) { - UUID uuid = toUuid(member); + ServiceId serviceId = ServiceId.parseOrNull(member.getUuid()); - if (!UuidUtil.UNKNOWN_UUID.equals(uuid)) { - uuidList.add(uuid); + if (serviceId != null) { + serviceIdList.add(serviceId); } } - return uuidList; + return serviceIdList; } public static Set membersToUuidByteStringSet(Collection membersList) { @@ -67,98 +70,94 @@ public final class DecryptedGroupUtil { } /** - * Can return non-decryptable member UUIDs as {@link UuidUtil#UNKNOWN_UUID}. + * Can return non-decryptable member UUIDs as unknown ACIs. */ - public static ArrayList pendingToUuidList(Collection membersList) { - ArrayList uuidList = new ArrayList<>(membersList.size()); + public static ArrayList pendingToServiceIdList(Collection membersList) { + ArrayList serviceIdList = new ArrayList<>(membersList.size()); for (DecryptedPendingMember member : membersList) { - uuidList.add(toUuid(member)); + ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBinary()); + if (serviceId != null) { + serviceIdList.add(serviceId); + } else { + serviceIdList.add(ServiceId.ACI.UNKNOWN); + } } - return uuidList; + return serviceIdList; } /** * Will not return any non-decryptable member UUIDs. */ - public static ArrayList removedMembersUuidList(DecryptedGroupChange groupChange) { - List deletedMembers = groupChange.getDeleteMembersList(); - ArrayList uuidList = new ArrayList<>(deletedMembers.size()); + public static ArrayList removedMembersServiceIdList(DecryptedGroupChange groupChange) { + List deletedMembers = groupChange.getDeleteMembersList(); + ArrayList serviceIdList = new ArrayList<>(deletedMembers.size()); for (ByteString member : deletedMembers) { - UUID uuid = toUuid(member); + ServiceId serviceId = ServiceId.parseOrNull(member); - if (!UuidUtil.UNKNOWN_UUID.equals(uuid)) { - uuidList.add(uuid); + if (serviceId != null) { + serviceIdList.add(serviceId); } } - return uuidList; + return serviceIdList; } /** * Will not return any non-decryptable member UUIDs. */ - public static ArrayList removedPendingMembersUuidList(DecryptedGroupChange groupChange) { + public static ArrayList removedPendingMembersServiceIdList(DecryptedGroupChange groupChange) { List deletedPendingMembers = groupChange.getDeletePendingMembersList(); - ArrayList uuidList = new ArrayList<>(deletedPendingMembers.size()); + ArrayList serviceIdList = new ArrayList<>(deletedPendingMembers.size()); for (DecryptedPendingMemberRemoval member : deletedPendingMembers) { - UUID uuid = toUuid(member.getUuid()); + ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBinary()); - if(!UuidUtil.UNKNOWN_UUID.equals(uuid)) { - uuidList.add(uuid); + if(serviceId != null) { + serviceIdList.add(serviceId); } } - return uuidList; + return serviceIdList; } /** * Will not return any non-decryptable member UUIDs. */ - public static ArrayList removedRequestingMembersUuidList(DecryptedGroupChange groupChange) { - List deleteRequestingMembers = groupChange.getDeleteRequestingMembersList(); - ArrayList uuidList = new ArrayList<>(deleteRequestingMembers.size()); + public static ArrayList removedRequestingMembersServiceIdList(DecryptedGroupChange groupChange) { + List deleteRequestingMembers = groupChange.getDeleteRequestingMembersList(); + ArrayList serviceIdList = new ArrayList<>(deleteRequestingMembers.size()); for (ByteString member : deleteRequestingMembers) { - UUID uuid = toUuid(member); + ServiceId serviceId = ServiceId.parseOrNull(member); - if(!UuidUtil.UNKNOWN_UUID.equals(uuid)) { - uuidList.add(uuid); + if(serviceId != null) { + serviceIdList.add(serviceId); } } - return uuidList; + return serviceIdList; } - public static Set bannedMembersToUuidSet(Collection membersList) { - Set uuidSet = new HashSet<>(membersList.size()); + public static Set bannedMembersToServiceIdSet(Collection membersList) { + Set serviceIdSet = new HashSet<>(membersList.size()); for (DecryptedBannedMember member : membersList) { - UUID uuid = toUuid(member); - - if (!UuidUtil.UNKNOWN_UUID.equals(uuid)) { - uuidSet.add(uuid); + ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBinary()); + if (serviceId != null) { + serviceIdSet.add(serviceId); } } - return uuidSet; + return serviceIdSet; } public static UUID toUuid(DecryptedMember member) { return toUuid(member.getUuid()); } - public static UUID toUuid(DecryptedPendingMember member) { - return toUuid(member.getUuid()); - } - - public static UUID toUuid(DecryptedBannedMember member) { - return toUuid(member.getUuid()); - } - private static UUID toUuid(ByteString memberUuid) { return UuidUtil.fromByteStringOrUnknown(memberUuid); } @@ -182,11 +181,11 @@ public final class DecryptedGroupUtil { return Optional.empty(); } - public static Optional findPendingByUuid(Collection members, UUID uuid) { - ByteString uuidBytes = UuidUtil.toByteString(uuid); + public static Optional findPendingByServiceId(Collection members, ServiceId serviceId) { + ByteString serviceIdBinary = serviceId.toByteString(); for (DecryptedPendingMember member : members) { - if (uuidBytes.equals(member.getUuid())) { + if (serviceIdBinary.equals(member.getServiceIdBinary())) { return Optional.of(member); } } @@ -196,7 +195,7 @@ public final class DecryptedGroupUtil { public static Optional findPendingByServiceIds(Collection members, ServiceIds serviceIds) { for (DecryptedPendingMember member : members) { - if (serviceIds.matches(member.getUuid())) { + if (serviceIds.matches(member.getServiceIdBinary())) { return Optional.of(member); } } @@ -215,10 +214,10 @@ public final class DecryptedGroupUtil { return -1; } - private static int findPendingIndexByUuid(List members, ByteString uuid) { + private static int findPendingIndexByServiceId(List members, ByteString serviceIdBinary) { for (int i = 0; i < members.size(); i++) { DecryptedPendingMember member = members.get(i); - if (uuid.equals(member.getUuid())) { + if (serviceIdBinary.equals(member.getServiceIdBinary())) { return i; } } @@ -416,7 +415,7 @@ public final class DecryptedGroupUtil { Set pendingMemberCipherTexts = getPendingMemberCipherTextSet(builder.getPendingMembersList()); for (DecryptedPendingMember pendingMember : newPendingMembersList) { - if (fullMemberSet.contains(pendingMember.getUuid())) { + if (fullMemberSet.contains(pendingMember.getServiceIdBinary())) { throw new NotAbleToApplyGroupV2ChangeException(); } @@ -441,7 +440,7 @@ public final class DecryptedGroupUtil { protected static void applyPromotePendingMemberActions(DecryptedGroup.Builder builder, List promotePendingMembersList) throws NotAbleToApplyGroupV2ChangeException { for (DecryptedMember newMember : promotePendingMembersList) { - int index = findPendingIndexByUuid(builder.getPendingMembersList(), newMember.getUuid()); + int index = findPendingIndexByServiceId(builder.getPendingMembersList(), newMember.getUuid()); if (index == -1) { throw new NotAbleToApplyGroupV2ChangeException(); @@ -556,10 +555,10 @@ public final class DecryptedGroupUtil { } private static void applyAddBannedMembersActions(DecryptedGroup.Builder builder, List newBannedMembersList) { - Set bannedMemberUuidSet = getBannedMemberUuidSet(builder.getBannedMembersList()); + Set bannedMemberServiceIdSet = getBannedMemberServiceIdSet(builder.getBannedMembersList()); for (DecryptedBannedMember member : newBannedMembersList) { - if (bannedMemberUuidSet.contains(member.getUuid())) { + if (bannedMemberServiceIdSet.contains(member.getServiceIdBinary())) { Log.w(TAG, "Banned member already in banned list"); } else { builder.addBannedMembers(member); @@ -569,7 +568,7 @@ public final class DecryptedGroupUtil { private static void applyDeleteBannedMembersActions(DecryptedGroup.Builder builder, List deleteMembersList) { for (DecryptedBannedMember removedMember : deleteMembersList) { - int index = indexOfUuidInBannedMemberList(builder.getBannedMembersList(), removedMember.getUuid()); + int index = indexOfServiceIdInBannedMemberList(builder.getBannedMembersList(), removedMember.getServiceIdBinary()); if (index == -1) { Log.w(TAG, "Deleted banned member on change not found in banned list"); @@ -582,7 +581,7 @@ public final class DecryptedGroupUtil { protected static void applyPromotePendingPniAciMemberActions(DecryptedGroup.Builder builder, List promotePendingPniAciMembersList) throws NotAbleToApplyGroupV2ChangeException { for (DecryptedMember newMember : promotePendingPniAciMembersList) { - int index = findPendingIndexByUuid(builder.getPendingMembersList(), newMember.getPni()); + int index = findPendingIndexByServiceId(builder.getPendingMembersList(), newMember.getPni()); if (index == -1) { throw new NotAbleToApplyGroupV2ChangeException(); @@ -619,14 +618,14 @@ public final class DecryptedGroupUtil { return pendingMemberCipherTexts; } - private static Set getBannedMemberUuidSet(List bannedMemberList) { - Set memberUuids = new HashSet<>(bannedMemberList.size()); + private static Set getBannedMemberServiceIdSet(List bannedMemberList) { + Set memberServiceIds = new HashSet<>(bannedMemberList.size()); for (DecryptedBannedMember member : bannedMemberList) { - memberUuids.add(member.getUuid()); + memberServiceIds.add(member.getServiceIdBinary()); } - return memberUuids; + return memberServiceIds; } private static void removePendingAndRequestingMembersNowInGroup(DecryptedGroup.Builder builder) { @@ -634,7 +633,7 @@ public final class DecryptedGroupUtil { for (int i = builder.getPendingMembersCount() - 1; i >= 0; i--) { DecryptedPendingMember pendingMember = builder.getPendingMembers(i); - if (allMembers.contains(pendingMember.getUuid())) { + if (allMembers.contains(pendingMember.getServiceIdBinary())) { builder.removePendingMembers(i); } } @@ -667,19 +666,13 @@ public final class DecryptedGroupUtil { return -1; } - private static int indexOfUuidInBannedMemberList(List memberList, ByteString uuid) { + private static int indexOfServiceIdInBannedMemberList(List memberList, ByteString serviceIdBinary) { for (int i = 0; i < memberList.size(); i++) { - if (uuid.equals(memberList.get(i).getUuid())) return i; + if (serviceIdBinary.equals(memberList.get(i).getServiceIdBinary())) return i; } return -1; } - public static Optional findInviter(List pendingMembersList, UUID uuid) { - return Optional.ofNullable(findPendingByUuid(pendingMembersList, uuid).map(DecryptedPendingMember::getAddedByUuid) - .map(UuidUtil::fromByteStringOrNull) - .orElse(null)); - } - public static boolean changeIsEmpty(DecryptedGroupChange change) { return change.getModifiedProfileKeysCount() == 0 && // field 6 changeIsEmptyExceptForProfileKeyChanges(change); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupCandidate.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupCandidate.java index f326f81fc0..af1e94975e 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupCandidate.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupCandidate.java @@ -1,12 +1,12 @@ package org.whispersystems.signalservice.api.groupsv2; import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.util.ExpiringProfileCredentialUtil; import java.util.HashSet; import java.util.Optional; import java.util.Set; -import java.util.UUID; /** * Represents a potential new member of a group. @@ -15,20 +15,20 @@ import java.util.UUID; *

* If it does not, then this user can only be invited. *

- * Equality by UUID only used to makes sure Sets only contain one copy. + * Equality by ServiceId only used to makes sure Sets only contain one copy. */ public final class GroupCandidate { - private final UUID uuid; + private final ServiceId serviceId; private final Optional expiringProfileKeyCredential; - public GroupCandidate(UUID uuid, Optional expiringProfileKeyCredential) { - this.uuid = uuid; + public GroupCandidate(ServiceId serviceId, Optional expiringProfileKeyCredential) { + this.serviceId = serviceId; this.expiringProfileKeyCredential = expiringProfileKeyCredential; } - public UUID getUuid() { - return uuid; + public ServiceId getServiceId() { + return serviceId; } public Optional getExpiringProfileKeyCredential() { @@ -57,12 +57,12 @@ public final class GroupCandidate { } public GroupCandidate withoutExpiringProfileKeyCredential() { - return expiringProfileKeyCredential.isPresent() ? new GroupCandidate(uuid, Optional.empty()) + return expiringProfileKeyCredential.isPresent() ? new GroupCandidate(serviceId, Optional.empty()) : this; } public GroupCandidate withExpiringProfileKeyCredential(ExpiringProfileKeyCredential expiringProfileKeyCredential) { - return new GroupCandidate(uuid, Optional.of(expiringProfileKeyCredential)); + return new GroupCandidate(serviceId, Optional.of(expiringProfileKeyCredential)); } @Override @@ -72,11 +72,11 @@ public final class GroupCandidate { } GroupCandidate other = (GroupCandidate) obj; - return other.uuid == uuid; + return other.serviceId.equals(serviceId); } @Override public int hashCode() { - return uuid.hashCode(); + return serviceId.hashCode(); } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupChangeReconstruct.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupChangeReconstruct.java index f50ad0e87c..ec52b6fccd 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupChangeReconstruct.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupChangeReconstruct.java @@ -60,30 +60,30 @@ public final class GroupChangeReconstruct { Set fromStateMemberUuids = membersToSetOfUuids(fromState.getMembersList()); Set toStateMemberUuids = membersToSetOfUuids(toState.getMembersList()); - Set pendingMembersListA = pendingMembersToSetOfUuids(fromState.getPendingMembersList()); - Set pendingMembersListB = pendingMembersToSetOfUuids(toState.getPendingMembersList()); + Set pendingMembersListA = pendingMembersToSetOfServiceIds(fromState.getPendingMembersList()); + Set pendingMembersListB = pendingMembersToSetOfServiceIds(toState.getPendingMembersList()); Set requestingMembersListA = requestingMembersToSetOfUuids(fromState.getRequestingMembersList()); Set requestingMembersListB = requestingMembersToSetOfUuids(toState.getRequestingMembersList()); - Set bannedMembersListA = bannedMembersToSetOfUuids(fromState.getBannedMembersList()); - Set bannedMembersListB = bannedMembersToSetOfUuids(toState.getBannedMembersList()); + Set bannedMembersListA = bannedMembersToSetOfServiceIds(fromState.getBannedMembersList()); + Set bannedMembersListB = bannedMembersToSetOfServiceIds(toState.getBannedMembersList()); - Set removedPendingMemberUuids = subtract(pendingMembersListA, pendingMembersListB); - Set removedRequestingMemberUuids = subtract(requestingMembersListA, requestingMembersListB); - Set newPendingMemberUuids = subtract(pendingMembersListB, pendingMembersListA); - Set newRequestingMemberUuids = subtract(requestingMembersListB, requestingMembersListA); - Set removedMemberUuids = subtract(fromStateMemberUuids, toStateMemberUuids); - Set newMemberUuids = subtract(toStateMemberUuids, fromStateMemberUuids); - Set removedBannedMemberUuids = subtract(bannedMembersListA, bannedMembersListB); - Set newBannedMemberUuids = subtract(bannedMembersListB, bannedMembersListA); + Set removedPendingMemberServiceIds = subtract(pendingMembersListA, pendingMembersListB); + Set removedRequestingMemberUuids = subtract(requestingMembersListA, requestingMembersListB); + Set newPendingMemberServiceIds = subtract(pendingMembersListB, pendingMembersListA); + Set newRequestingMemberUuids = subtract(requestingMembersListB, requestingMembersListA); + Set removedMemberUuids = subtract(fromStateMemberUuids, toStateMemberUuids); + Set newMemberUuids = subtract(toStateMemberUuids, fromStateMemberUuids); + Set removedBannedMemberServiceIds = subtract(bannedMembersListA, bannedMembersListB); + Set newBannedMemberServiceIds = subtract(bannedMembersListB, bannedMembersListA); - Set addedByInvitationUuids = intersect(newMemberUuids, removedPendingMemberUuids); + Set addedByInvitationUuids = intersect(newMemberUuids, removedPendingMemberServiceIds); Set addedByRequestApprovalUuids = intersect(newMemberUuids, removedRequestingMemberUuids); Set addedMembersByInvitation = intersectByUUID(toState.getMembersList(), addedByInvitationUuids); Set addedMembersByRequestApproval = intersectByUUID(toState.getMembersList(), addedByRequestApprovalUuids); Set addedMembers = intersectByUUID(toState.getMembersList(), subtract(newMemberUuids, addedByInvitationUuids, addedByRequestApprovalUuids)); - Set uninvitedMembers = intersectPendingByUUID(fromState.getPendingMembersList(), subtract(removedPendingMemberUuids, addedByInvitationUuids)); + Set uninvitedMembers = intersectPendingByServiceId(fromState.getPendingMembersList(), subtract(removedPendingMemberServiceIds, addedByInvitationUuids)); Set rejectedRequestMembers = intersectRequestingByUUID(fromState.getRequestingMembersList(), subtract(removedRequestingMemberUuids, addedByRequestApprovalUuids)); for (DecryptedMember member : intersectByUUID(fromState.getMembersList(), removedMemberUuids)) { @@ -100,18 +100,18 @@ public final class GroupChangeReconstruct { for (DecryptedPendingMember uninvitedMember : uninvitedMembers) { builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() - .setUuid(uninvitedMember.getUuid()) + .setServiceIdBinary(uninvitedMember.getServiceIdBinary()) .setUuidCipherText(uninvitedMember.getUuidCipherText())); } - for (DecryptedPendingMember invitedMember : intersectPendingByUUID(toState.getPendingMembersList(), newPendingMemberUuids)) { + for (DecryptedPendingMember invitedMember : intersectPendingByServiceId(toState.getPendingMembersList(), newPendingMemberServiceIds)) { builder.addNewPendingMembers(invitedMember); } - Set consistentMemberUuids = intersect(fromStateMemberUuids, toStateMemberUuids); - Set changedMembers = intersectByUUID(subtract(toState.getMembersList(), fromState.getMembersList()), consistentMemberUuids); - Map membersUuidMap = uuidMap(fromState.getMembersList()); - Map bannedMembersUuidMap = bannedUuidMap(toState.getBannedMembersList()); + Set consistentMemberUuids = intersect(fromStateMemberUuids, toStateMemberUuids); + Set changedMembers = intersectByUUID(subtract(toState.getMembersList(), fromState.getMembersList()), consistentMemberUuids); + Map membersUuidMap = uuidMap(fromState.getMembersList()); + Map bannedMembersServiceIdMap = bannedServiceIdMap(toState.getBannedMembersList()); for (DecryptedMember newState : changedMembers) { DecryptedMember oldState = membersUuidMap.get(newState.getUuid()); @@ -148,13 +148,13 @@ public final class GroupChangeReconstruct { builder.setNewInviteLinkPassword(toState.getInviteLinkPassword()); } - for (ByteString uuid : removedBannedMemberUuids) { - builder.addDeleteBannedMembers(DecryptedBannedMember.newBuilder().setUuid(uuid).build()); + for (ByteString serviceIdBinary : removedBannedMemberServiceIds) { + builder.addDeleteBannedMembers(DecryptedBannedMember.newBuilder().setServiceIdBinary(serviceIdBinary).build()); } - for (ByteString uuid : newBannedMemberUuids) { - DecryptedBannedMember.Builder newBannedBuilder = DecryptedBannedMember.newBuilder().setUuid(uuid); - DecryptedBannedMember bannedMember = bannedMembersUuidMap.get(uuid); + for (ByteString serviceIdBinary : newBannedMemberServiceIds) { + DecryptedBannedMember.Builder newBannedBuilder = DecryptedBannedMember.newBuilder().setServiceIdBinary(serviceIdBinary); + DecryptedBannedMember bannedMember = bannedMembersServiceIdMap.get(serviceIdBinary); if (bannedMember != null) { newBannedBuilder.setTimestamp(bannedMember.getTimestamp()); } @@ -173,10 +173,10 @@ public final class GroupChangeReconstruct { return map; } - private static Map bannedUuidMap(List membersList) { + private static Map bannedServiceIdMap(List membersList) { Map map = new LinkedHashMap<>(membersList.size()); for (DecryptedBannedMember member : membersList) { - map.put(member.getUuid(), member); + map.put(member.getServiceIdBinary(), member); } return map; } @@ -190,10 +190,10 @@ public final class GroupChangeReconstruct { return result; } - private static Set intersectPendingByUUID(Collection members, Set uuids) { + private static Set intersectPendingByServiceId(Collection members, Set serviceIds) { Set result = new LinkedHashSet<>(members.size()); for (DecryptedPendingMember member : members) { - if (uuids.contains(member.getUuid())) + if (serviceIds.contains(member.getServiceIdBinary())) result.add(member); } return result; @@ -208,12 +208,12 @@ public final class GroupChangeReconstruct { return result; } - private static Set pendingMembersToSetOfUuids(Collection pendingMembers) { - Set uuids = new LinkedHashSet<>(pendingMembers.size()); + private static Set pendingMembersToSetOfServiceIds(Collection pendingMembers) { + Set serviceIds = new LinkedHashSet<>(pendingMembers.size()); for (DecryptedPendingMember pendingMember : pendingMembers) { - uuids.add(pendingMember.getUuid()); + serviceIds.add(pendingMember.getServiceIdBinary()); } - return uuids; + return serviceIds; } private static Set requestingMembersToSetOfUuids(Collection requestingMembers) { @@ -232,12 +232,12 @@ public final class GroupChangeReconstruct { return uuids; } - private static Set bannedMembersToSetOfUuids(Collection bannedMembers) { - Set uuids = new LinkedHashSet<>(bannedMembers.size()); + private static Set bannedMembersToSetOfServiceIds(Collection bannedMembers) { + Set serviceIds = new LinkedHashSet<>(bannedMembers.size()); for (DecryptedBannedMember bannedMember : bannedMembers) { - uuids.add(bannedMember.getUuid()); + serviceIds.add(bannedMember.getServiceIdBinary()); } - return uuids; + return serviceIds; } private static Set subtract(Collection a, Collection b) { diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupChangeUtil.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupChangeUtil.java index 814a957a06..23e338f86e 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupChangeUtil.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupChangeUtil.java @@ -107,17 +107,17 @@ public final class GroupChangeUtil { DecryptedGroupChange conflictingChange, ChangeSetModifier changeSetModifier) { - HashMap fullMembersByUuid = new HashMap<>(groupState.getMembersCount()); - HashMap pendingMembersByUuid = new HashMap<>(groupState.getPendingMembersCount()); - HashMap requestingMembersByUuid = new HashMap<>(groupState.getMembersCount()); - HashMap bannedMembersByUuid = new HashMap<>(groupState.getBannedMembersCount()); + HashMap fullMembersByUuid = new HashMap<>(groupState.getMembersCount()); + HashMap pendingMembersByServiceId = new HashMap<>(groupState.getPendingMembersCount()); + HashMap requestingMembersByUuid = new HashMap<>(groupState.getMembersCount()); + HashMap bannedMembersByServiceId = new HashMap<>(groupState.getBannedMembersCount()); for (DecryptedMember member : groupState.getMembersList()) { fullMembersByUuid.put(member.getUuid(), member); } for (DecryptedPendingMember member : groupState.getPendingMembersList()) { - pendingMembersByUuid.put(member.getUuid(), member); + pendingMembersByServiceId.put(member.getServiceIdBinary(), member); } for (DecryptedRequestingMember member : groupState.getRequestingMembersList()) { @@ -125,33 +125,33 @@ public final class GroupChangeUtil { } for (DecryptedBannedMember member : groupState.getBannedMembersList()) { - bannedMembersByUuid.put(member.getUuid(), member); + bannedMembersByServiceId.put(member.getServiceIdBinary(), member); } - resolveField3AddMembers (conflictingChange, changeSetModifier, fullMembersByUuid, pendingMembersByUuid); + resolveField3AddMembers (conflictingChange, changeSetModifier, fullMembersByUuid, pendingMembersByServiceId); resolveField4DeleteMembers (conflictingChange, changeSetModifier, fullMembersByUuid); resolveField5ModifyMemberRoles (conflictingChange, changeSetModifier, fullMembersByUuid); resolveField6ModifyProfileKeys (conflictingChange, changeSetModifier, fullMembersByUuid); - resolveField7AddPendingMembers (conflictingChange, changeSetModifier, fullMembersByUuid, pendingMembersByUuid); - resolveField8DeletePendingMembers (conflictingChange, changeSetModifier, pendingMembersByUuid); - resolveField9PromotePendingMembers (conflictingChange, changeSetModifier, pendingMembersByUuid); + resolveField7AddPendingMembers (conflictingChange, changeSetModifier, fullMembersByUuid, pendingMembersByServiceId); + resolveField8DeletePendingMembers (conflictingChange, changeSetModifier, pendingMembersByServiceId); + resolveField9PromotePendingMembers (conflictingChange, changeSetModifier, pendingMembersByServiceId); resolveField10ModifyTitle (groupState, conflictingChange, changeSetModifier); resolveField11ModifyAvatar (groupState, conflictingChange, changeSetModifier); resolveField12modifyDisappearingMessagesTimer(groupState, conflictingChange, changeSetModifier); resolveField13modifyAttributesAccess (groupState, conflictingChange, changeSetModifier); resolveField14modifyAttributesAccess (groupState, conflictingChange, changeSetModifier); resolveField15modifyAddFromInviteLinkAccess (groupState, conflictingChange, changeSetModifier); - resolveField16AddRequestingMembers (conflictingChange, changeSetModifier, fullMembersByUuid, pendingMembersByUuid); + resolveField16AddRequestingMembers (conflictingChange, changeSetModifier, fullMembersByUuid, pendingMembersByServiceId); resolveField17DeleteMembers (conflictingChange, changeSetModifier, requestingMembersByUuid); resolveField18PromoteRequestingMembers (conflictingChange, changeSetModifier, requestingMembersByUuid); resolveField20ModifyDescription (groupState, conflictingChange, changeSetModifier); resolveField21ModifyAnnouncementsOnly (groupState, conflictingChange, changeSetModifier); - resolveField22AddBannedMembers (conflictingChange, changeSetModifier, bannedMembersByUuid); - resolveField23DeleteBannedMembers (conflictingChange, changeSetModifier, bannedMembersByUuid); + resolveField22AddBannedMembers (conflictingChange, changeSetModifier, bannedMembersByServiceId); + resolveField23DeleteBannedMembers (conflictingChange, changeSetModifier, bannedMembersByServiceId); resolveField24PromotePendingPniAciMembers (conflictingChange, changeSetModifier, fullMembersByUuid); } - private static void resolveField3AddMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap fullMembersByUuid, HashMap pendingMembersByUuid) { + private static void resolveField3AddMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap fullMembersByUuid, HashMap pendingMembersByServiceId) { List newMembersList = conflictingChange.getNewMembersList(); for (int i = newMembersList.size() - 1; i >= 0; i--) { @@ -159,7 +159,7 @@ public final class GroupChangeUtil { if (fullMembersByUuid.containsKey(member.getUuid())) { result.removeAddMembers(i); - } else if (pendingMembersByUuid.containsKey(member.getUuid())) { + } else if (pendingMembersByServiceId.containsKey(member.getUuid())) { result.moveAddToPromote(i); } } @@ -203,37 +203,37 @@ public final class GroupChangeUtil { } } - private static void resolveField7AddPendingMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap fullMembersByUuid, HashMap pendingMembersByUuid) { + private static void resolveField7AddPendingMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap fullMembersByUuid, HashMap pendingMembersByServiceId) { List newPendingMembersList = conflictingChange.getNewPendingMembersList(); for (int i = newPendingMembersList.size() - 1; i >= 0; i--) { DecryptedPendingMember member = newPendingMembersList.get(i); - if (fullMembersByUuid.containsKey(member.getUuid()) || pendingMembersByUuid.containsKey(member.getUuid())) { + if (fullMembersByUuid.containsKey(member.getServiceIdBinary()) || pendingMembersByServiceId.containsKey(member.getServiceIdBinary())) { result.removeAddPendingMembers(i); } } } - private static void resolveField8DeletePendingMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap pendingMembersByUuid) { + private static void resolveField8DeletePendingMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap pendingMembersByServiceId) { List deletePendingMembersList = conflictingChange.getDeletePendingMembersList(); for (int i = deletePendingMembersList.size() - 1; i >= 0; i--) { DecryptedPendingMemberRemoval member = deletePendingMembersList.get(i); - if (!pendingMembersByUuid.containsKey(member.getUuid())) { + if (!pendingMembersByServiceId.containsKey(member.getServiceIdBinary())) { result.removeDeletePendingMembers(i); } } } - private static void resolveField9PromotePendingMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap pendingMembersByUuid) { + private static void resolveField9PromotePendingMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap pendingMembersByServiceId) { List promotePendingMembersList = conflictingChange.getPromotePendingMembersList(); for (int i = promotePendingMembersList.size() - 1; i >= 0; i--) { DecryptedMember member = promotePendingMembersList.get(i); - if (!pendingMembersByUuid.containsKey(member.getUuid())) { + if (!pendingMembersByServiceId.containsKey(member.getUuid())) { result.removePromotePendingMembers(i); } } @@ -275,7 +275,7 @@ public final class GroupChangeUtil { } } - private static void resolveField16AddRequestingMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap fullMembersByUuid, HashMap pendingMembersByUuid) { + private static void resolveField16AddRequestingMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap fullMembersByUuid, HashMap pendingMembersByServiceId) { List newMembersList = conflictingChange.getNewRequestingMembersList(); for (int i = newMembersList.size() - 1; i >= 0; i--) { @@ -283,8 +283,8 @@ public final class GroupChangeUtil { if (fullMembersByUuid.containsKey(member.getUuid())) { result.removeAddRequestingMembers(i); - } else if (pendingMembersByUuid.containsKey(member.getUuid())) { - result.moveAddRequestingMembersToPromote(i); + } else if (pendingMembersByServiceId.containsKey(member.getUuid())) { + result.moveAddRequestingMembersToPromote(i); } } } @@ -331,25 +331,25 @@ public final class GroupChangeUtil { } } - private static void resolveField22AddBannedMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap bannedMembersByUuid) { + private static void resolveField22AddBannedMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap bannedMembersByServiceId) { List newBannedMembersList = conflictingChange.getNewBannedMembersList(); for (int i = newBannedMembersList.size() - 1; i >= 0; i--) { DecryptedBannedMember member = newBannedMembersList.get(i); - if (bannedMembersByUuid.containsKey(member.getUuid())) { + if (bannedMembersByServiceId.containsKey(member.getServiceIdBinary())) { result.removeAddBannedMembers(i); } } } - private static void resolveField23DeleteBannedMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap bannedMembersByUuid) { + private static void resolveField23DeleteBannedMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap bannedMembersByServiceId) { List deleteBannedMembersList = conflictingChange.getDeleteBannedMembersList(); for (int i = deleteBannedMembersList.size() - 1; i >= 0; i--) { DecryptedBannedMember member = deleteBannedMembersList.get(i); - if (!bannedMembersByUuid.containsKey(member.getUuid())) { + if (!bannedMembersByServiceId.containsKey(member.getServiceIdBinary())) { result.removeDeleteBannedMembers(i); } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Api.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Api.java index 506bb2472a..ecbd372483 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Api.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Api.java @@ -21,7 +21,8 @@ import org.signal.storageservice.protos.groups.GroupJoinInfo; import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo; -import org.whispersystems.signalservice.api.push.ServiceId; +import org.whispersystems.signalservice.api.push.ServiceId.ACI; +import org.whispersystems.signalservice.api.push.ServiceId.PNI; import org.whispersystems.signalservice.internal.push.PushServiceSocket; import org.whispersystems.signalservice.internal.push.exceptions.ForbiddenException; @@ -55,15 +56,15 @@ public class GroupsV2Api { /** * Create an auth token from a credential response. */ - public GroupsV2AuthorizationString getGroupsV2AuthorizationString(ServiceId aci, - ServiceId pni, + public GroupsV2AuthorizationString getGroupsV2AuthorizationString(ACI aci, + PNI pni, long redemptionTimeSeconds, GroupSecretParams groupSecretParams, AuthCredentialWithPniResponse authCredentialWithPniResponse) throws VerificationFailedException { ClientZkAuthOperations authOperations = groupsOperations.getAuthOperations(); - AuthCredentialWithPni authCredentialWithPni = authOperations.receiveAuthCredentialWithPni(aci.getRawUuid(), pni.getRawUuid(), redemptionTimeSeconds, authCredentialWithPniResponse); + AuthCredentialWithPni authCredentialWithPni = authOperations.receiveAuthCredentialWithPniAsServiceId(aci.getLibSignalAci(), pni.getLibSignalPni(), redemptionTimeSeconds, authCredentialWithPniResponse); AuthCredentialPresentation authCredentialPresentation = authOperations.createAuthCredentialPresentation(new SecureRandom(), groupSecretParams, authCredentialWithPni); return new GroupsV2AuthorizationString(groupSecretParams, authCredentialPresentation); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations.java index e1988b45ac..44ed973ba7 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations.java @@ -40,6 +40,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedString; import org.signal.storageservice.protos.groups.local.DecryptedTimer; import org.signal.storageservice.protos.groups.local.EnabledState; import org.whispersystems.signalservice.api.push.ServiceId.ACI; +import org.whispersystems.signalservice.api.push.ServiceId.PNI; import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.util.UuidUtil; @@ -119,7 +120,7 @@ public final class GroupsV2Operations { if (expiringProfileKeyCredential != null) { group.addMembers(groupOperations.member(expiringProfileKeyCredential, memberRole)); } else { - group.addPendingMembers(groupOperations.invitee(credential.getUuid(), memberRole)); + group.addPendingMembers(groupOperations.invitee(credential.getServiceId(), memberRole)); } } @@ -165,13 +166,13 @@ public final class GroupsV2Operations { return GroupChange.Actions.newBuilder().setModifyDescription(createModifyGroupDescriptionAction(description)); } - public GroupChange.Actions.Builder createModifyGroupMembershipChange(Set membersToAdd, Set bannedMembers, UUID selfUuid) { + public GroupChange.Actions.Builder createModifyGroupMembershipChange(Set membersToAdd, Set bannedMembers, ACI selfAci) { final GroupOperations groupOperations = forGroup(groupSecretParams); - Set membersToUnban = membersToAdd.stream().map(GroupCandidate::getUuid).filter(bannedMembers::contains).collect(Collectors.toSet()); + Set membersToUnban = membersToAdd.stream().map(GroupCandidate::getServiceId).filter(bannedMembers::contains).collect(Collectors.toSet()); GroupChange.Actions.Builder actions = membersToUnban.isEmpty() ? GroupChange.Actions.newBuilder() - : createUnbanUuidsChange(membersToUnban); + : createUnbanServiceIdsChange(membersToUnban); for (GroupCandidate credential : membersToAdd) { Member.Role newMemberRole = Member.Role.DEFAULT; @@ -184,8 +185,8 @@ public final class GroupsV2Operations { } else { actions.addAddPendingMembers(GroupChange.Actions.AddPendingMemberAction .newBuilder() - .setAdded(groupOperations.invitee(credential.getUuid(), newMemberRole) - .setAddedByUserId(encryptUuid(selfUuid)))); + .setAdded(groupOperations.invitee(credential.getServiceId(), newMemberRole) + .setAddedByUserId(encryptServiceId(selfAci)))); } } @@ -221,7 +222,7 @@ public final class GroupsV2Operations { for (UUID uuid : requestsToRemove) { actions.addDeleteRequestingMembers(GroupChange.Actions.DeleteRequestingMemberAction .newBuilder() - .setDeletedUserId(encryptUuid(uuid))); + .setDeletedUserId(encryptServiceId(ACI.from(uuid)))); } return actions; @@ -234,7 +235,7 @@ public final class GroupsV2Operations { actions.addPromoteRequestingMembers(GroupChange.Actions.PromoteRequestingMemberAction .newBuilder() .setRole(Member.Role.DEFAULT) - .setUserId(encryptUuid(uuid))); + .setUserId(encryptServiceId(ACI.from(uuid)))); } return actions; @@ -247,7 +248,7 @@ public final class GroupsV2Operations { for (UUID remove: membersToRemove) { actions.addDeleteMembers(GroupChange.Actions.DeleteMemberAction .newBuilder() - .setDeletedUserId(encryptUuid(remove))); + .setDeletedUserId(encryptServiceId(ACI.from(remove)))); } return actions; @@ -259,7 +260,7 @@ public final class GroupsV2Operations { for (UUID member : membersToMakeAdmin) { actions.addModifyMemberRoles(GroupChange.Actions.ModifyMemberRoleAction .newBuilder() - .setUserId(encryptUuid(member)) + .setUserId(encryptServiceId(ACI.from(member))) .setRole(Member.Role.ADMINISTRATOR)); } @@ -361,6 +362,7 @@ public final class GroupsV2Operations { .setAnnouncementsOnly(isAnnouncementGroup)); } + /** Note that this can only ban ACIs. */ public GroupChange.Actions.Builder createBanUuidsChange(Set banUuids, boolean rejectJoinRequest, List bannedMembersList) { GroupChange.Actions.Builder builder = rejectJoinRequest ? createRefuseGroupJoinRequest(banUuids, false, Collections.emptyList()) : GroupChange.Actions.newBuilder(); @@ -370,26 +372,26 @@ public final class GroupsV2Operations { List unban = bannedMembersList.stream() .sorted(Comparator.comparingLong(DecryptedBannedMember::getTimestamp)) .limit(spacesToFree) - .map(DecryptedBannedMember::getUuid) + .map(DecryptedBannedMember::getServiceIdBinary) .collect(Collectors.toList()); - for (ByteString uuid : unban) { - builder.addDeleteBannedMembers(GroupChange.Actions.DeleteBannedMemberAction.newBuilder().setDeletedUserId(encryptUuid(UuidUtil.fromByteString(uuid)))); + for (ByteString serviceIdBinary : unban) { + builder.addDeleteBannedMembers(GroupChange.Actions.DeleteBannedMemberAction.newBuilder().setDeletedUserId(encryptServiceId(ServiceId.parseOrThrow(serviceIdBinary.toByteArray())))); } } for (UUID uuid : banUuids) { - builder.addAddBannedMembers(GroupChange.Actions.AddBannedMemberAction.newBuilder().setAdded(BannedMember.newBuilder().setUserId(encryptUuid(uuid)).build())); + builder.addAddBannedMembers(GroupChange.Actions.AddBannedMemberAction.newBuilder().setAdded(BannedMember.newBuilder().setUserId(encryptServiceId(ACI.from(uuid))).build())); } return builder; } - public GroupChange.Actions.Builder createUnbanUuidsChange(Set banUuids) { + public GroupChange.Actions.Builder createUnbanServiceIdsChange(Set serviceIds) { GroupChange.Actions.Builder builder = GroupChange.Actions.newBuilder(); - for (UUID uuid : banUuids) { - builder.addDeleteBannedMembers(GroupChange.Actions.DeleteBannedMemberAction.newBuilder().setDeletedUserId(encryptUuid(uuid)).build()); + for (ServiceId serviceId : serviceIds) { + builder.addDeleteBannedMembers(GroupChange.Actions.DeleteBannedMemberAction.newBuilder().setDeletedUserId(encryptServiceId(serviceId)).build()); } return builder; @@ -433,8 +435,8 @@ public final class GroupsV2Operations { .setPresentation(ByteString.copyFrom(presentation.serialize())); } - public PendingMember.Builder invitee(UUID uuid, Member.Role role) { - UuidCiphertext uuidCiphertext = clientZkGroupCipher.encryptUuid(uuid); + public PendingMember.Builder invitee(ServiceId serviceId, Member.Role role) { + UuidCiphertext uuidCiphertext = clientZkGroupCipher.encrypt(serviceId.getLibSignalServiceId()); Member member = Member.newBuilder() .setRole(role) @@ -454,17 +456,17 @@ public final class GroupsV2Operations { List decryptedPendingMembers = new ArrayList<>(pendingMembersList.size()); for (Member member : membersList) { - UUID memberUuid = decryptUuid(member.getUserId()); + ACI memberAci = decryptAci(member.getUserId()); decryptedMembers.add(DecryptedMember.newBuilder() - .setUuid(UuidUtil.toByteString(memberUuid)) + .setUuid(memberAci.toByteString()) .setJoinedAtRevision(member.getJoinedAtRevision()) .build()); } for (PendingMember member : pendingMembersList) { - UUID pendingMemberUuid = decryptUuidOrUnknown(member.getMember().getUserId()); + ServiceId pendingMemberServiceId = decryptServiceIdOrUnknown(member.getMember().getUserId()); decryptedPendingMembers.add(DecryptedPendingMember.newBuilder() - .setUuid(UuidUtil.toByteString(pendingMemberUuid)) + .setServiceIdBinary(pendingMemberServiceId.toByteString()) .build()); } @@ -505,7 +507,7 @@ public final class GroupsV2Operations { } for (BannedMember member : group.getBannedMembersList()) { - decryptedBannedMembers.add(DecryptedBannedMember.newBuilder().setUuid(decryptUuidToByteString(member.getUserId())).setTimestamp(member.getTimestamp()).build()); + decryptedBannedMembers.add(DecryptedBannedMember.newBuilder().setServiceIdBinary(decryptServiceIdToBinary(member.getUserId())).setTimestamp(member.getTimestamp()).build()); } return DecryptedGroup.newBuilder() @@ -551,16 +553,16 @@ public final class GroupsV2Operations { return decryptChange(actions, null); } - public DecryptedGroupChange decryptChange(GroupChange.Actions actions, UUID source) + public DecryptedGroupChange decryptChange(GroupChange.Actions actions, ServiceId source) throws VerificationFailedException, InvalidGroupStateException { DecryptedGroupChange.Builder builder = DecryptedGroupChange.newBuilder(); // Field 1 if (source != null) { - builder.setEditor(UuidUtil.toByteString(source)); + builder.setEditor(source.toByteString()); } else { - builder.setEditor(decryptUuidToByteString(actions.getSourceUuid())); + builder.setEditor(decryptServiceIdToBinary(actions.getSourceUuid())); } // Field 2 @@ -577,35 +579,35 @@ public final class GroupsV2Operations { // Field 4 for (GroupChange.Actions.DeleteMemberAction deleteMemberAction : actions.getDeleteMembersList()) { - builder.addDeleteMembers(decryptUuidToByteString(deleteMemberAction.getDeletedUserId())); + builder.addDeleteMembers(decryptServiceIdToBinary(deleteMemberAction.getDeletedUserId())); } // Field 5 for (GroupChange.Actions.ModifyMemberRoleAction modifyMemberRoleAction : actions.getModifyMemberRolesList()) { builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() .setRole(modifyMemberRoleAction.getRole()) - .setUuid(decryptUuidToByteString(modifyMemberRoleAction.getUserId()))); + .setUuid(decryptServiceIdToBinary(modifyMemberRoleAction.getUserId()))); } // Field 6 for (GroupChange.Actions.ModifyMemberProfileKeyAction modifyMemberProfileKeyAction : actions.getModifyMemberProfileKeysList()) { try { - UUID uuid; + ACI aci; ProfileKey profileKey; if (modifyMemberProfileKeyAction.getUserId().isEmpty() || modifyMemberProfileKeyAction.getProfileKey().isEmpty()) { ProfileKeyCredentialPresentation presentation = new ProfileKeyCredentialPresentation(modifyMemberProfileKeyAction.getPresentation().toByteArray()); - uuid = decryptUuid(ByteString.copyFrom(presentation.getUuidCiphertext().serialize())); - profileKey = decryptProfileKey(ByteString.copyFrom(presentation.getProfileKeyCiphertext().serialize()), uuid); + aci = decryptAci(ByteString.copyFrom(presentation.getUuidCiphertext().serialize())); + profileKey = decryptProfileKey(ByteString.copyFrom(presentation.getProfileKeyCiphertext().serialize()), aci); } else { - uuid = decryptUuid(modifyMemberProfileKeyAction.getUserId()); - profileKey = decryptProfileKey(modifyMemberProfileKeyAction.getProfileKey(), uuid); + aci = decryptAci(modifyMemberProfileKeyAction.getUserId()); + profileKey = decryptProfileKey(modifyMemberProfileKeyAction.getProfileKey(), aci); } builder.addModifiedProfileKeys(DecryptedMember.newBuilder() .setRole(Member.Role.UNKNOWN) .setJoinedAtRevision(-1) - .setUuid(UuidUtil.toByteString(uuid)) + .setUuid(aci.toByteString()) .setProfileKey(ByteString.copyFrom(profileKey.serialize()))); } catch (InvalidInputException e) { throw new InvalidGroupStateException(e); @@ -617,45 +619,45 @@ public final class GroupsV2Operations { PendingMember added = addPendingMemberAction.getAdded(); Member member = added.getMember(); ByteString uuidCipherText = member.getUserId(); - UUID uuid = decryptUuidOrUnknown(uuidCipherText); + ServiceId serviceId = decryptServiceIdOrUnknown(uuidCipherText); builder.addNewPendingMembers(DecryptedPendingMember.newBuilder() - .setUuid(UuidUtil.toByteString(uuid)) + .setServiceIdBinary(serviceId.toByteString()) .setUuidCipherText(uuidCipherText) .setRole(member.getRole()) - .setAddedByUuid(decryptUuidToByteString(added.getAddedByUserId())) + .setAddedByUuid(decryptServiceIdToBinary(added.getAddedByUserId())) .setTimestamp(added.getTimestamp())); } // Field 8 for (GroupChange.Actions.DeletePendingMemberAction deletePendingMemberAction : actions.getDeletePendingMembersList()) { ByteString uuidCipherText = deletePendingMemberAction.getDeletedUserId(); - UUID uuid = decryptUuidOrUnknown(uuidCipherText); + ServiceId serviceId = decryptServiceIdOrUnknown(uuidCipherText); builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() - .setUuid(UuidUtil.toByteString(uuid)) + .setServiceIdBinary(serviceId.toByteString()) .setUuidCipherText(uuidCipherText)); } // Field 9 for (GroupChange.Actions.PromotePendingMemberAction promotePendingMemberAction : actions.getPromotePendingMembersList()) { try { - UUID uuid; + ACI aci; ProfileKey profileKey; if (promotePendingMemberAction.getUserId().isEmpty() || promotePendingMemberAction.getProfileKey().isEmpty()) { ProfileKeyCredentialPresentation presentation = new ProfileKeyCredentialPresentation(promotePendingMemberAction.getPresentation().toByteArray()); - uuid = decryptUuid(ByteString.copyFrom(presentation.getUuidCiphertext().serialize())); - profileKey = decryptProfileKey(ByteString.copyFrom(presentation.getProfileKeyCiphertext().serialize()), uuid); + aci = decryptAci(ByteString.copyFrom(presentation.getUuidCiphertext().serialize())); + profileKey = decryptProfileKey(ByteString.copyFrom(presentation.getProfileKeyCiphertext().serialize()), aci); } else { - uuid = decryptUuid(promotePendingMemberAction.getUserId()); - profileKey = decryptProfileKey(promotePendingMemberAction.getProfileKey(), uuid); + aci = decryptAci(promotePendingMemberAction.getUserId()); + profileKey = decryptProfileKey(promotePendingMemberAction.getProfileKey(), aci); } builder.addPromotePendingMembers(DecryptedMember.newBuilder() .setJoinedAtRevision(-1) .setRole(Member.Role.DEFAULT) - .setUuid(UuidUtil.toByteString(uuid)) + .setUuid(aci.toByteString()) .setProfileKey(ByteString.copyFrom(profileKey.serialize()))); } catch (InvalidInputException e) { throw new InvalidGroupStateException(e); @@ -700,12 +702,12 @@ public final class GroupsV2Operations { // Field 17 for (GroupChange.Actions.DeleteRequestingMemberAction delete : actions.getDeleteRequestingMembersList()) { - builder.addDeleteRequestingMembers(decryptUuidToByteString(delete.getDeletedUserId())); + builder.addDeleteRequestingMembers(decryptServiceIdToBinary(delete.getDeletedUserId())); } // Field 18 for (GroupChange.Actions.PromoteRequestingMemberAction promote : actions.getPromoteRequestingMembersList()) { - builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder().setRole(promote.getRole()).setUuid(decryptUuidToByteString(promote.getUserId()))); + builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder().setRole(promote.getRole()).setUuid(decryptServiceIdToBinary(promote.getUserId()))); } // Field 19 @@ -725,27 +727,31 @@ public final class GroupsV2Operations { // Field 22 for (GroupChange.Actions.AddBannedMemberAction action : actions.getAddBannedMembersList()) { - builder.addNewBannedMembers(DecryptedBannedMember.newBuilder().setUuid(decryptUuidToByteString(action.getAdded().getUserId())).setTimestamp(action.getAdded().getTimestamp()).build()); + builder.addNewBannedMembers(DecryptedBannedMember.newBuilder().setServiceIdBinary(decryptServiceIdToBinary(action.getAdded().getUserId())).setTimestamp(action.getAdded().getTimestamp()).build()); } // Field 23 for (GroupChange.Actions.DeleteBannedMemberAction action : actions.getDeleteBannedMembersList()) { - builder.addDeleteBannedMembers(DecryptedBannedMember.newBuilder().setUuid(decryptUuidToByteString(action.getDeletedUserId())).build()); + builder.addDeleteBannedMembers(DecryptedBannedMember.newBuilder().setServiceIdBinary(decryptServiceIdToBinary(action.getDeletedUserId())).build()); } // Field 24 for (GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction promotePendingPniAciMemberAction : actions.getPromotePendingPniAciMembersList()) { - UUID uuid = decryptUuid(promotePendingPniAciMemberAction.getUserId()); - UUID pni = decryptUuid(promotePendingPniAciMemberAction.getPni()); - ProfileKey profileKey = decryptProfileKey(promotePendingPniAciMemberAction.getProfileKey(), uuid); + ACI aci = decryptAci(promotePendingPniAciMemberAction.getUserId()); + ServiceId pni = decryptServiceId(promotePendingPniAciMemberAction.getPni()); + ProfileKey profileKey = decryptProfileKey(promotePendingPniAciMemberAction.getProfileKey(), aci); - builder.setEditor(UuidUtil.toByteString(uuid)) + if (!(pni instanceof PNI)) { + throw new InvalidGroupStateException(); + } + + builder.setEditor(aci.toByteString()) .addPromotePendingPniAciMembers(DecryptedMember.newBuilder() - .setUuid(UuidUtil.toByteString(uuid)) + .setUuid(aci.toByteString()) .setRole(Member.Role.DEFAULT) .setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setJoinedAtRevision(actions.getRevision()) - .setPni(UuidUtil.toByteString(pni))); + .setPni(pni.toByteString())); } return builder.build(); @@ -767,20 +773,26 @@ public final class GroupsV2Operations { throws InvalidGroupStateException, VerificationFailedException, InvalidInputException { if (member.getPresentation().isEmpty()) { - UUID uuid = decryptUuid(member.getUserId()); + ACI aci = decryptAci(member.getUserId()); return DecryptedMember.newBuilder() - .setUuid(UuidUtil.toByteString(uuid)) + .setUuid(aci.toByteString()) .setJoinedAtRevision(member.getJoinedAtRevision()) - .setProfileKey(decryptProfileKeyToByteString(member.getProfileKey(), uuid)) + .setProfileKey(decryptProfileKeyToByteString(member.getProfileKey(), aci)) .setRole(member.getRole()); } else { ProfileKeyCredentialPresentation profileKeyCredentialPresentation = new ProfileKeyCredentialPresentation(member.getPresentation().toByteArray()); - UUID uuid = clientZkGroupCipher.decryptUuid(profileKeyCredentialPresentation.getUuidCiphertext()); - ProfileKey profileKey = clientZkGroupCipher.decryptProfileKey(profileKeyCredentialPresentation.getProfileKeyCiphertext(), uuid); + + ServiceId serviceId = ServiceId.fromLibSignal(clientZkGroupCipher.decrypt(profileKeyCredentialPresentation.getUuidCiphertext())); + if (!(serviceId instanceof ACI)) { + throw new InvalidGroupStateException(); + } + ACI serviceIdAsAci = (ACI)serviceId; + + ProfileKey profileKey = clientZkGroupCipher.decryptProfileKey(profileKeyCredentialPresentation.getProfileKeyCiphertext(), serviceIdAsAci.getLibSignalAci()); return DecryptedMember.newBuilder() - .setUuid(UuidUtil.toByteString(uuid)) + .setUuid(serviceIdAsAci.toByteString()) .setJoinedAtRevision(member.getJoinedAtRevision()) .setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setRole(member.getRole()); @@ -791,8 +803,8 @@ public final class GroupsV2Operations { throws InvalidGroupStateException, VerificationFailedException { ByteString userIdCipherText = member.getMember().getUserId(); - UUID uuid = decryptUuidOrUnknown(userIdCipherText); - UUID addedBy = decryptUuid(member.getAddedByUserId()); + ServiceId serviceId = decryptServiceIdOrUnknown(userIdCipherText); + ACI addedBy = decryptAci(member.getAddedByUserId()); Member.Role role = member.getMember().getRole(); @@ -801,9 +813,9 @@ public final class GroupsV2Operations { } return DecryptedPendingMember.newBuilder() - .setUuid(UuidUtil.toByteString(uuid)) + .setServiceIdBinary(serviceId.toByteString()) .setUuidCipherText(userIdCipherText) - .setAddedByUuid(UuidUtil.toByteString(addedBy)) + .setAddedByUuid(addedBy.toByteString()) .setRole(role) .setTimestamp(member.getTimestamp()) .build(); @@ -813,11 +825,11 @@ public final class GroupsV2Operations { throws InvalidGroupStateException, VerificationFailedException { if (member.getPresentation().isEmpty()) { - UUID uuid = decryptUuid(member.getUserId()); + ACI aci = decryptAci(member.getUserId()); return DecryptedRequestingMember.newBuilder() - .setUuid(UuidUtil.toByteString(uuid)) - .setProfileKey(decryptProfileKeyToByteString(member.getProfileKey(), uuid)) + .setUuid(aci.toByteString()) + .setProfileKey(decryptProfileKeyToByteString(member.getProfileKey(), aci)) .setTimestamp(member.getTimestamp()) .build(); } else { @@ -828,54 +840,67 @@ public final class GroupsV2Operations { throw new InvalidGroupStateException(e); } - UUID uuid = clientZkGroupCipher.decryptUuid(profileKeyCredentialPresentation.getUuidCiphertext()); - ProfileKey profileKey = clientZkGroupCipher.decryptProfileKey(profileKeyCredentialPresentation.getProfileKeyCiphertext(), uuid); + ServiceId serviceId = ServiceId.fromLibSignal(clientZkGroupCipher.decrypt(profileKeyCredentialPresentation.getUuidCiphertext())); + if (!(serviceId instanceof ACI)) { + throw new InvalidGroupStateException(); + } + ACI serviceIdAsAci = (ACI)serviceId; + + ProfileKey profileKey = clientZkGroupCipher.decryptProfileKey(profileKeyCredentialPresentation.getProfileKeyCiphertext(), serviceIdAsAci.getLibSignalAci()); return DecryptedRequestingMember.newBuilder() - .setUuid(UuidUtil.toByteString(uuid)) + .setUuid(serviceIdAsAci.toByteString()) .setProfileKey(ByteString.copyFrom(profileKey.serialize())) .build(); } } - private ProfileKey decryptProfileKey(ByteString profileKey, UUID uuid) throws VerificationFailedException, InvalidGroupStateException { + private ProfileKey decryptProfileKey(ByteString profileKey, ACI aci) throws VerificationFailedException, InvalidGroupStateException { try { ProfileKeyCiphertext profileKeyCiphertext = new ProfileKeyCiphertext(profileKey.toByteArray()); - return clientZkGroupCipher.decryptProfileKey(profileKeyCiphertext, uuid); + return clientZkGroupCipher.decryptProfileKey(profileKeyCiphertext, aci.getLibSignalAci()); } catch (InvalidInputException e) { throw new InvalidGroupStateException(e); } } - private ByteString decryptProfileKeyToByteString(ByteString profileKey, UUID uuid) throws VerificationFailedException, InvalidGroupStateException { - return ByteString.copyFrom(decryptProfileKey(profileKey, uuid).serialize()); + private ByteString decryptProfileKeyToByteString(ByteString profileKey, ACI aci) throws VerificationFailedException, InvalidGroupStateException { + return ByteString.copyFrom(decryptProfileKey(profileKey, aci).serialize()); } - private ByteString decryptUuidToByteString(ByteString userId) throws InvalidGroupStateException, VerificationFailedException { - return UuidUtil.toByteString(decryptUuid(userId)); + private ByteString decryptServiceIdToBinary(ByteString userId) throws InvalidGroupStateException, VerificationFailedException { + return decryptServiceId(userId).toByteString(); } // Visible for Testing - public ByteString encryptUuid(UUID uuid) { - return ByteString.copyFrom(clientZkGroupCipher.encryptUuid(uuid).serialize()); + public ByteString encryptServiceId(ServiceId serviceId) { + return ByteString.copyFrom(clientZkGroupCipher.encrypt(serviceId.getLibSignalServiceId()).serialize()); } - private UUID decryptUuid(ByteString userId) throws InvalidGroupStateException, VerificationFailedException { + private ServiceId decryptServiceId(ByteString userId) throws InvalidGroupStateException, VerificationFailedException { try { - return clientZkGroupCipher.decryptUuid(new UuidCiphertext(userId.toByteArray())); + return ServiceId.fromLibSignal(clientZkGroupCipher.decrypt(new UuidCiphertext(userId.toByteArray()))); } catch (InvalidInputException e) { throw new InvalidGroupStateException(e); } } + private ACI decryptAci(ByteString userId) throws InvalidGroupStateException, VerificationFailedException { + ServiceId result = decryptServiceId(userId); + if (result instanceof ACI) { + return (ACI)result; + } + throw new InvalidGroupStateException(); + } + /** - * Attempts to decrypt a UUID, but will return {@link #UNKNOWN_UUID} if it cannot. + * Attempts to decrypt a UUID, but will return an ACI of {@link #UNKNOWN_UUID} if it cannot. */ - private UUID decryptUuidOrUnknown(ByteString userId) { + private ServiceId decryptServiceIdOrUnknown(ByteString userId) { try { - return clientZkGroupCipher.decryptUuid(new UuidCiphertext(userId.toByteArray())); + return ServiceId.fromLibSignal(clientZkGroupCipher.decrypt(new UuidCiphertext(userId.toByteArray()))); } catch (InvalidInputException | VerificationFailedException e) { - return UNKNOWN_UUID; + return ACI.UNKNOWN; } } @@ -977,10 +1002,10 @@ public final class GroupsV2Operations { return GroupChange.Actions.parseFrom(groupChange.getActions()); } - public GroupChange.Actions.Builder createChangeMemberRole(UUID uuid, Member.Role role) { + public GroupChange.Actions.Builder createChangeMemberRole(ACI memberAci, Member.Role role) { return GroupChange.Actions.newBuilder() .addModifyMemberRoles(GroupChange.Actions.ModifyMemberRoleAction.newBuilder() - .setUserId(encryptUuid(uuid)) + .setUserId(encryptServiceId(memberAci)) .setRole(role)); } @@ -990,7 +1015,7 @@ public final class GroupsV2Operations { GroupChange.Actions.AddMemberAction addMember = addMembers.get(i); ProfileKeyCredentialPresentation profileKeyCredentialPresentation = new ProfileKeyCredentialPresentation(addMember.getAdded().getPresentation().toByteArray()); - ids.add(ACI.from(clientZkGroupCipher.decryptUuid(profileKeyCredentialPresentation.getUuidCiphertext()))); + ids.add(ServiceId.fromLibSignal(clientZkGroupCipher.decrypt(profileKeyCredentialPresentation.getUuidCiphertext()))); } return ids; } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ServiceId.kt b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ServiceId.kt index fc0a433f38..a1ac6fd270 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ServiceId.kt +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ServiceId.kt @@ -19,8 +19,17 @@ import org.signal.libsignal.protocol.ServiceId.Pni as LibSignalPni * The only times you truly know, and the only times you should actually care, is during CDS refreshes or specific inbound messages * that link them together. */ -sealed class ServiceId(@JvmField protected val libsignalServiceId: LibSignalServiceId) { +sealed class ServiceId(val libSignalServiceId: LibSignalServiceId) { companion object { + @JvmStatic + fun fromLibSignal(serviceId: LibSignalServiceId): ServiceId { + return when (serviceId) { + is LibSignalAci -> ACI(serviceId) + is LibSignalPni -> PNI(serviceId) + else -> throw IllegalArgumentException("Unknown libsignal ServiceId type!") + } + } + /** Parses a ServiceId serialized as a string. Returns null if the ServiceId is invalid. */ @JvmStatic fun parseOrNull(raw: String?): ServiceId? { @@ -29,11 +38,7 @@ sealed class ServiceId(@JvmField protected val libsignalServiceId: LibSignalServ } return try { - when (val serviceId = LibSignalServiceId.parseFromString(raw)) { - is LibSignalAci -> ACI(serviceId) - is LibSignalPni -> PNI(serviceId) - else -> null - } + fromLibSignal(LibSignalServiceId.parseFromString(raw)) } catch (e: IllegalArgumentException) { null } catch (e: InvalidServiceIdException) { @@ -49,11 +54,7 @@ sealed class ServiceId(@JvmField protected val libsignalServiceId: LibSignalServ } return try { - return when (val serviceId = LibSignalServiceId.parseFromBinary(raw)) { - is LibSignalAci -> ACI.from(serviceId.rawUUID) - is LibSignalPni -> PNI.from(serviceId.rawUUID) - else -> null - } + fromLibSignal(LibSignalServiceId.parseFromBinary(raw)) } catch (e: IllegalArgumentException) { null } catch (e: InvalidServiceIdException) { @@ -61,6 +62,10 @@ sealed class ServiceId(@JvmField protected val libsignalServiceId: LibSignalServ } } + /** Parses a ServiceId serialized as a ByteString. Returns null if the ServiceId is invalid. */ + @JvmStatic + fun parseOrNull(bytes: ByteString): ServiceId? = parseOrNull(bytes.toByteArray()) + /** Parses a ServiceId serialized as a string. Crashes if the ServiceId is invalid. */ @JvmStatic @Throws(IllegalArgumentException::class) @@ -77,27 +82,27 @@ sealed class ServiceId(@JvmField protected val libsignalServiceId: LibSignalServ fun parseOrThrow(bytes: ByteString): ServiceId = parseOrThrow(bytes.toByteArray()) } - val rawUuid: UUID = libsignalServiceId.rawUUID + val rawUuid: UUID = libSignalServiceId.rawUUID val isUnknown: Boolean = rawUuid == UuidUtil.UNKNOWN_UUID val isValid: Boolean = !isUnknown - fun toProtocolAddress(deviceId: Int): SignalProtocolAddress = SignalProtocolAddress(libsignalServiceId.toServiceIdString(), deviceId) + fun toProtocolAddress(deviceId: Int): SignalProtocolAddress = SignalProtocolAddress(libSignalServiceId.toServiceIdString(), deviceId) - fun toByteString(): ByteString = ByteString.copyFrom(libsignalServiceId.toServiceIdBinary()) + fun toByteString(): ByteString = ByteString.copyFrom(libSignalServiceId.toServiceIdBinary()) - fun toByteArray(): ByteArray = libsignalServiceId.toServiceIdBinary() + fun toByteArray(): ByteArray = libSignalServiceId.toServiceIdBinary() - fun logString(): String = libsignalServiceId.toLogString() + fun logString(): String = libSignalServiceId.toLogString() /** * A serialized string that can be parsed via [parseOrThrow], for instance. * Basically ACI's are just normal UUIDs, and PNI's are UUIDs with a `PNI:` prefix. */ - override fun toString(): String = libsignalServiceId.toServiceIdString() + override fun toString(): String = libSignalServiceId.toServiceIdString() - data class ACI(val libsignalAci: LibSignalAci) : ServiceId(libsignalAci) { + data class ACI(val libSignalAci: LibSignalAci) : ServiceId(libSignalAci) { companion object { @JvmField val UNKNOWN = from(UuidUtil.UNKNOWN_UUID) @@ -133,7 +138,7 @@ sealed class ServiceId(@JvmField protected val libsignalServiceId: LibSignalServ override fun toString(): String = super.toString() } - data class PNI(private val libsignalPni: LibSignalPni) : ServiceId(libsignalPni) { + data class PNI(val libSignalPni: LibSignalPni) : ServiceId(libSignalPni) { companion object { @JvmField var UNKNOWN = from(UuidUtil.UNKNOWN_UUID) diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/services/ProfileService.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/services/ProfileService.java index 550d4cc00e..8043613647 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/services/ProfileService.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/services/ProfileService.java @@ -1,6 +1,7 @@ package org.whispersystems.signalservice.api.services; import org.signal.libsignal.protocol.IdentityKey; +import org.signal.libsignal.protocol.logging.Log; import org.signal.libsignal.protocol.util.Pair; import org.signal.libsignal.zkgroup.VerificationFailedException; import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations; @@ -15,6 +16,7 @@ import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess; import org.whispersystems.signalservice.api.profiles.ProfileAndCredential; import org.whispersystems.signalservice.api.profiles.SignalServiceProfile; import org.whispersystems.signalservice.api.push.ServiceId; +import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException; import org.whispersystems.signalservice.internal.ServiceResponse; @@ -81,11 +83,17 @@ public final class ProfileService { .setVerb("GET"); if (profileKey.isPresent()) { - ProfileKeyVersion profileKeyIdentifier = profileKey.get().getProfileKeyVersion(serviceId.getRawUuid()); + if (!(serviceId instanceof ACI)) { + Log.w(TAG, "ServiceId must be an ACI if a profile key is available!"); + return Single.just(ServiceResponse.forUnknownError(new IllegalArgumentException("ServiceId must be an ACI if a profile key is available!"))); + } + + ACI aci = (ACI) serviceId; + ProfileKeyVersion profileKeyIdentifier = profileKey.get().getProfileKeyVersion(aci.getLibSignalAci()); String version = profileKeyIdentifier.serialize(); if (requestType == SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL) { - requestContext = clientZkProfileOperations.createProfileKeyCredentialRequestContext(random, serviceId.getRawUuid(), profileKey.get()); + requestContext = clientZkProfileOperations.createProfileKeyCredentialRequestContext(random, aci.getLibSignalAci(), profileKey.get()); ProfileKeyCredentialRequest request = requestContext.getRequest(); String credentialRequest = Hex.toStringCondensed(request.serialize()); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java index 5a33de0359..01a5b34fe5 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java @@ -258,7 +258,7 @@ public class PushServiceSocket { private static final String STICKER_MANIFEST_PATH = "stickers/%s/manifest.proto"; private static final String STICKER_PATH = "stickers/%s/full/%d"; - private static final String GROUPSV2_CREDENTIAL = "/v1/certificate/auth/group?redemptionStartSeconds=%d&redemptionEndSeconds=%d"; + private static final String GROUPSV2_CREDENTIAL = "/v1/certificate/auth/group?redemptionStartSeconds=%d&redemptionEndSeconds=%d&pniAsServiceId=true"; private static final String GROUPSV2_GROUP = "/v1/groups/"; private static final String GROUPSV2_GROUP_PASSWORD = "/v1/groups/?inviteLinkPassword=%s"; private static final String GROUPSV2_GROUP_CHANGES = "/v1/groups/logs/%s?maxSupportedChangeEpoch=%d&includeFirstState=%s&includeLastState=false"; @@ -853,9 +853,9 @@ public class PushServiceSocket { }); } - public ListenableFuture retrieveVersionedProfileAndCredential(UUID target, ProfileKey profileKey, Optional unidentifiedAccess, Locale locale) { - ProfileKeyVersion profileKeyIdentifier = profileKey.getProfileKeyVersion(target); - ProfileKeyCredentialRequestContext requestContext = clientZkProfileOperations.createProfileKeyCredentialRequestContext(random, target, profileKey); + public ListenableFuture retrieveVersionedProfileAndCredential(ACI target, ProfileKey profileKey, Optional unidentifiedAccess, Locale locale) { + ProfileKeyVersion profileKeyIdentifier = profileKey.getProfileKeyVersion(target.getLibSignalAci()); + ProfileKeyCredentialRequestContext requestContext = clientZkProfileOperations.createProfileKeyCredentialRequestContext(random, target.getLibSignalAci(), profileKey); ProfileKeyCredentialRequest request = requestContext.getRequest(); String version = profileKeyIdentifier.serialize(); @@ -889,8 +889,8 @@ public class PushServiceSocket { } } - public ListenableFuture retrieveVersionedProfile(UUID target, ProfileKey profileKey, Optional unidentifiedAccess, Locale locale) { - ProfileKeyVersion profileKeyIdentifier = profileKey.getProfileKeyVersion(target); + public ListenableFuture retrieveVersionedProfile(ACI target, ProfileKey profileKey, Optional unidentifiedAccess, Locale locale) { + ProfileKeyVersion profileKeyIdentifier = profileKey.getProfileKeyVersion(target.getLibSignalAci()); String version = profileKeyIdentifier.serialize(); String subPath = String.format("%s/%s", target, version); diff --git a/libsignal/service/src/main/proto/DecryptedGroups.proto b/libsignal/service/src/main/proto/DecryptedGroups.proto index 45e6cde52b..235e133373 100644 --- a/libsignal/service/src/main/proto/DecryptedGroups.proto +++ b/libsignal/service/src/main/proto/DecryptedGroups.proto @@ -21,11 +21,11 @@ message DecryptedMember { } message DecryptedPendingMember { - bytes uuid = 1; - Member.Role role = 2; - bytes addedByUuid = 3; - uint64 timestamp = 4; - bytes uuidCipherText = 5; + bytes serviceIdBinary = 1; + Member.Role role = 2; + bytes addedByUuid = 3; + uint64 timestamp = 4; + bytes uuidCipherText = 5; } message DecryptedRequestingMember { @@ -35,13 +35,13 @@ message DecryptedRequestingMember { } message DecryptedBannedMember { - bytes uuid = 1; - uint64 timestamp = 2; + bytes serviceIdBinary = 1; + uint64 timestamp = 2; } message DecryptedPendingMemberRemoval { - bytes uuid = 1; - bytes uuidCipherText = 2; + bytes serviceIdBinary = 1; + bytes uuidCipherText = 2; } message DecryptedApproveMember { diff --git a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/DecryptedGroupUtilTest.java b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/DecryptedGroupUtilTest.java index 7cd09c5f17..f66d311f3e 100644 --- a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/DecryptedGroupUtilTest.java +++ b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/DecryptedGroupUtilTest.java @@ -7,6 +7,8 @@ import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval; +import org.whispersystems.signalservice.api.push.ServiceId; +import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.internal.util.Util; @@ -15,6 +17,7 @@ import java.util.UUID; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static java.util.Arrays.asList; @@ -58,39 +61,39 @@ public final class DecryptedGroupUtilTest { @Test public void can_extract_uuid_from_decrypted_pending_member() { - UUID uuid = UUID.randomUUID(); + ACI aci = ACI.from(UUID.randomUUID()); DecryptedPendingMember decryptedMember = DecryptedPendingMember.newBuilder() - .setUuid(UuidUtil.toByteString(uuid)) + .setServiceIdBinary(aci.toByteString()) .build(); - UUID parsed = DecryptedGroupUtil.toUuid(decryptedMember); + ServiceId parsed = ServiceId.parseOrNull(decryptedMember.getServiceIdBinary()); - assertEquals(uuid, parsed); + assertEquals(aci, parsed); } @Test public void can_extract_uuid_from_bad_decrypted_pending_member() { DecryptedPendingMember decryptedMember = DecryptedPendingMember.newBuilder() - .setUuid(ByteString.copyFrom(Util.getSecretBytes(17))) + .setServiceIdBinary(ByteString.copyFrom(Util.getSecretBytes(18))) .build(); - UUID parsed = DecryptedGroupUtil.toUuid(decryptedMember); + ServiceId parsed = ServiceId.parseOrNull(decryptedMember.getServiceIdBinary()); - assertEquals(UuidUtil.UNKNOWN_UUID, parsed); + assertNull(parsed); } @Test public void can_extract_uuids_for_all_pending_including_bad_entries() { - UUID uuid1 = UUID.randomUUID(); - UUID uuid2 = UUID.randomUUID(); + ACI aci1 = ACI.from(UUID.randomUUID()); + ACI aci2 = ACI.from(UUID.randomUUID()); DecryptedPendingMember decryptedMember1 = DecryptedPendingMember.newBuilder() - .setUuid(UuidUtil.toByteString(uuid1)) + .setServiceIdBinary(aci1.toByteString()) .build(); DecryptedPendingMember decryptedMember2 = DecryptedPendingMember.newBuilder() - .setUuid(UuidUtil.toByteString(uuid2)) + .setServiceIdBinary(aci2.toByteString()) .build(); DecryptedPendingMember decryptedMember3 = DecryptedPendingMember.newBuilder() - .setUuid(ByteString.copyFrom(Util.getSecretBytes(17))) + .setServiceIdBinary(ByteString.copyFrom(Util.getSecretBytes(18))) .build(); DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder() @@ -99,23 +102,23 @@ public final class DecryptedGroupUtilTest { .addNewPendingMembers(decryptedMember3) .build(); - List pendingUuids = DecryptedGroupUtil.pendingToUuidList(groupChange.getNewPendingMembersList()); + List pendingUuids = DecryptedGroupUtil.pendingToServiceIdList(groupChange.getNewPendingMembersList()); - assertThat(pendingUuids, is(asList(uuid1, uuid2, UuidUtil.UNKNOWN_UUID))); + assertThat(pendingUuids, is(asList(aci1, aci2, ACI.UNKNOWN))); } @Test public void can_extract_uuids_for_all_deleted_pending_excluding_bad_entries() { - UUID uuid1 = UUID.randomUUID(); - UUID uuid2 = UUID.randomUUID(); + ACI aci1 = ACI.from(UUID.randomUUID()); + ACI aci2 = ACI.from(UUID.randomUUID()); DecryptedPendingMemberRemoval decryptedMember1 = DecryptedPendingMemberRemoval.newBuilder() - .setUuid(UuidUtil.toByteString(uuid1)) + .setServiceIdBinary(aci1.toByteString()) .build(); DecryptedPendingMemberRemoval decryptedMember2 = DecryptedPendingMemberRemoval.newBuilder() - .setUuid(UuidUtil.toByteString(uuid2)) + .setServiceIdBinary(aci2.toByteString()) .build(); DecryptedPendingMemberRemoval decryptedMember3 = DecryptedPendingMemberRemoval.newBuilder() - .setUuid(ByteString.copyFrom(Util.getSecretBytes(17))) + .setServiceIdBinary(ByteString.copyFrom(Util.getSecretBytes(18))) .build(); DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder() @@ -124,23 +127,23 @@ public final class DecryptedGroupUtilTest { .addDeletePendingMembers(decryptedMember3) .build(); - List removedUuids = DecryptedGroupUtil.removedPendingMembersUuidList(groupChange); + List removedUuids = DecryptedGroupUtil.removedPendingMembersServiceIdList(groupChange); - assertThat(removedUuids, is(asList(uuid1, uuid2))); + assertThat(removedUuids, is(asList(aci1, aci2))); } @Test public void can_extract_uuids_for_all_deleted_members_excluding_bad_entries() { - UUID uuid1 = UUID.randomUUID(); - UUID uuid2 = UUID.randomUUID(); + ACI aci1 = ACI.from(UUID.randomUUID()); + ACI aci2 = ACI.from(UUID.randomUUID()); DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder() - .addDeleteMembers(UuidUtil.toByteString(uuid1)) - .addDeleteMembers(UuidUtil.toByteString(uuid2)) - .addDeleteMembers(ByteString.copyFrom(Util.getSecretBytes(17))) + .addDeleteMembers(aci1.toByteString()) + .addDeleteMembers(aci2.toByteString()) + .addDeleteMembers(ByteString.copyFrom(Util.getSecretBytes(18))) .build(); - List removedUuids = DecryptedGroupUtil.removedMembersUuidList(groupChange); + List removedServiceIds = DecryptedGroupUtil.removedMembersServiceIdList(groupChange); - assertThat(removedUuids, is(asList(uuid1, uuid2))); + assertThat(removedServiceIds, is(asList(aci1, aci2))); } } diff --git a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/DecryptedGroupUtil_apply_Test.java b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/DecryptedGroupUtil_apply_Test.java index 18c8c79866..36c6562c24 100644 --- a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/DecryptedGroupUtil_apply_Test.java +++ b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/DecryptedGroupUtil_apply_Test.java @@ -949,7 +949,7 @@ public final class DecryptedGroupUtil_apply_Test { DecryptedGroupChange.newBuilder() .setRevision(11) .addDeleteBannedMembers(DecryptedBannedMember.newBuilder() - .setUuid(UuidUtil.toByteString(bannedUuid)) + .setServiceIdBinary(UuidUtil.toByteString(bannedUuid)) .build()) .build()); diff --git a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations_ban_Test.java b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations_ban_Test.java index 5deeba25f5..7514fa01ef 100644 --- a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations_ban_Test.java +++ b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations_ban_Test.java @@ -12,6 +12,8 @@ import org.signal.storageservice.protos.groups.GroupChange; import org.signal.storageservice.protos.groups.GroupChange.Actions.AddBannedMemberAction; import org.signal.storageservice.protos.groups.GroupChange.Actions.DeleteBannedMemberAction; import org.signal.storageservice.protos.groups.local.DecryptedBannedMember; +import org.whispersystems.signalservice.api.push.ServiceId; +import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.testutil.LibSignalLibraryUtil; @@ -52,7 +54,7 @@ public final class GroupsV2Operations_ban_Test { Collections.emptyList()); assertThat(banUuidsChange.getAddBannedMembersCount(), is(1)); - assertThat(banUuidsChange.getAddBannedMembers(0).getAdded().getUserId(), is(groupOperations.encryptUuid(ban))); + assertThat(banUuidsChange.getAddBannedMembers(0).getAdded().getUserId(), is(groupOperations.encryptServiceId(ACI.from(ban)))); } @Test @@ -69,7 +71,7 @@ public final class GroupsV2Operations_ban_Test { alreadyBanned); assertThat(banUuidsChange.getAddBannedMembersCount(), is(1)); - assertThat(banUuidsChange.getAddBannedMembers(0).getAdded().getUserId(), is(groupOperations.encryptUuid(toBan))); + assertThat(banUuidsChange.getAddBannedMembers(0).getAdded().getUserId(), is(groupOperations.encryptServiceId(ACI.from(toBan)))); } @Test @@ -93,11 +95,11 @@ public final class GroupsV2Operations_ban_Test { alreadyBanned); assertThat(banUuidsChange.getDeleteBannedMembersCount(), is(1)); - assertThat(banUuidsChange.getDeleteBannedMembers(0).getDeletedUserId(), is(groupOperations.encryptUuid(UuidUtil.fromByteString(oldest.getUuid())))); + assertThat(banUuidsChange.getDeleteBannedMembers(0).getDeletedUserId(), is(groupOperations.encryptServiceId(ServiceId.parseOrThrow(oldest.getServiceIdBinary())))); assertThat(banUuidsChange.getAddBannedMembersCount(), is(1)); - assertThat(banUuidsChange.getAddBannedMembers(0).getAdded().getUserId(), is(groupOperations.encryptUuid(toBan))); + assertThat(banUuidsChange.getAddBannedMembers(0).getAdded().getUserId(), is(groupOperations.encryptServiceId(ACI.from(toBan)))); } @Test @@ -112,8 +114,8 @@ public final class GroupsV2Operations_ban_Test { } List oldest = new ArrayList<>(2); - oldest.add(groupOperations.encryptUuid(UuidUtil.fromByteString(alreadyBanned.get(0).getUuid()))); - oldest.add(groupOperations.encryptUuid(UuidUtil.fromByteString(alreadyBanned.get(1).getUuid()))); + oldest.add(groupOperations.encryptServiceId(ServiceId.parseOrThrow(alreadyBanned.get(0).getServiceIdBinary()))); + oldest.add(groupOperations.encryptServiceId(ServiceId.parseOrThrow(alreadyBanned.get(1).getServiceIdBinary()))); Collections.shuffle(alreadyBanned); @@ -135,6 +137,7 @@ public final class GroupsV2Operations_ban_Test { .map(AddBannedMemberAction::getAdded) .map(BannedMember::getUserId) .collect(Collectors.toList()), - hasItems(groupOperations.encryptUuid(toBan.get(0)), groupOperations.encryptUuid(toBan.get(1)))); + hasItems(groupOperations.encryptServiceId(ACI.from(toBan.get(0))), + groupOperations.encryptServiceId(ACI.from(toBan.get(1))))); } } diff --git a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations_decrypt_change_Test.java b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations_decrypt_change_Test.java index 8398586dde..258696f705 100644 --- a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations_decrypt_change_Test.java +++ b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations_decrypt_change_Test.java @@ -33,6 +33,8 @@ import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.protos.groups.local.DecryptedString; import org.signal.storageservice.protos.groups.local.DecryptedTimer; import org.signal.storageservice.protos.groups.local.EnabledState; +import org.whispersystems.signalservice.api.push.ServiceId.ACI; +import org.whispersystems.signalservice.api.push.ServiceId.PNI; import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.testutil.LibSignalLibraryUtil; @@ -94,8 +96,8 @@ public final class GroupsV2Operations_decrypt_change_Test { @Test public void can_decrypt_member_additions_field3() { - UUID self = UUID.randomUUID(); - UUID newMember = UUID.randomUUID(); + ACI self = ACI.from(UUID.randomUUID()); + ACI newMember = ACI.from(UUID.randomUUID()); ProfileKey profileKey = newProfileKey(); GroupCandidate groupCandidate = groupCandidate(newMember, profileKey); @@ -107,12 +109,12 @@ public final class GroupsV2Operations_decrypt_change_Test { .setRole(Member.Role.DEFAULT) .setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setJoinedAtRevision(10) - .setUuid(UuidUtil.toByteString(newMember)))); + .setUuid(newMember.toByteString()))); } @Test public void can_decrypt_member_direct_join_field3() { - UUID newMember = UUID.randomUUID(); + ACI newMember = ACI.from(UUID.randomUUID()); ProfileKey profileKey = newProfileKey(); GroupCandidate groupCandidate = groupCandidate(newMember, profileKey); @@ -124,13 +126,13 @@ public final class GroupsV2Operations_decrypt_change_Test { .setRole(Member.Role.DEFAULT) .setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setJoinedAtRevision(10) - .setUuid(UuidUtil.toByteString(newMember)))); + .setUuid(newMember.toByteString()))); } @Test public void can_decrypt_member_additions_direct_to_admin_field3() { - UUID self = UUID.randomUUID(); - UUID newMember = UUID.randomUUID(); + ACI self = ACI.from(UUID.randomUUID()); + ACI newMember = ACI.from(UUID.randomUUID()); ProfileKey profileKey = newProfileKey(); GroupCandidate groupCandidate = groupCandidate(newMember, profileKey); @@ -142,7 +144,7 @@ public final class GroupsV2Operations_decrypt_change_Test { .setRole(Member.Role.DEFAULT) .setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setJoinedAtRevision(10) - .setUuid(UuidUtil.toByteString(newMember)))); + .setUuid(newMember.toByteString()))); } @Test(expected = InvalidGroupStateException.class) @@ -181,29 +183,29 @@ public final class GroupsV2Operations_decrypt_change_Test { @Test public void can_decrypt_modify_member_action_role_to_admin_field5() { - UUID member = UUID.randomUUID(); + ACI member = ACI.from(UUID.randomUUID()); assertDecryption(groupOperations.createChangeMemberRole(member, Member.Role.ADMINISTRATOR), DecryptedGroupChange.newBuilder() .addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() - .setUuid(UuidUtil.toByteString(member)) + .setUuid(member.toByteString()) .setRole(Member.Role.ADMINISTRATOR))); } @Test public void can_decrypt_modify_member_action_role_to_member_field5() { - UUID member = UUID.randomUUID(); + ACI member = ACI.from(UUID.randomUUID()); assertDecryption(groupOperations.createChangeMemberRole(member, Member.Role.DEFAULT), DecryptedGroupChange.newBuilder() .addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() - .setUuid(UuidUtil.toByteString(member)) + .setUuid(member.toByteString()) .setRole(Member.Role.DEFAULT))); } @Test public void can_decrypt_modify_member_profile_key_action_field6() { - UUID self = UUID.randomUUID(); + ACI self = ACI.from(UUID.randomUUID()); ProfileKey profileKey = newProfileKey(); GroupCandidate groupCandidate = groupCandidate(self, profileKey); @@ -215,35 +217,35 @@ public final class GroupsV2Operations_decrypt_change_Test { .setRole(Member.Role.UNKNOWN) .setJoinedAtRevision(-1) .setProfileKey(ByteString.copyFrom(profileKey.serialize())) - .setUuid(UuidUtil.toByteString(self)))); + .setUuid(self.toByteString()))); } @Test public void can_decrypt_member_invitations_field7() { - UUID self = UUID.randomUUID(); - UUID newMember = UUID.randomUUID(); - GroupCandidate groupCandidate = groupCandidate(newMember); + ACI self = ACI.from(UUID.randomUUID()); + ACI newMember = ACI.from(UUID.randomUUID()); + GroupCandidate groupCandidate = new GroupCandidate(newMember, Optional.empty()); assertDecryption(groupOperations.createModifyGroupMembershipChange(Collections.singleton(groupCandidate), Collections.emptySet(), self) .setRevision(13), DecryptedGroupChange.newBuilder() .setRevision(13) .addNewPendingMembers(DecryptedPendingMember.newBuilder() - .setAddedByUuid(UuidUtil.toByteString(self)) - .setUuidCipherText(groupOperations.encryptUuid(newMember)) + .setAddedByUuid(self.toByteString()) + .setUuidCipherText(groupOperations.encryptServiceId(newMember)) .setRole(Member.Role.DEFAULT) - .setUuid(UuidUtil.toByteString(newMember)))); + .setServiceIdBinary(newMember.toByteString()))); } @Test public void can_decrypt_pending_member_removals_field8() throws InvalidInputException { - UUID oldMember = UUID.randomUUID(); - UuidCiphertext uuidCiphertext = new UuidCiphertext(groupOperations.encryptUuid(oldMember).toByteArray()); + ACI oldMember = ACI.from(UUID.randomUUID()); + UuidCiphertext uuidCiphertext = new UuidCiphertext(groupOperations.encryptServiceId(oldMember).toByteArray()); assertDecryption(groupOperations.createRemoveInvitationChange(Collections.singleton(uuidCiphertext)), DecryptedGroupChange.newBuilder() .addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() - .setUuid(UuidUtil.toByteString(oldMember)) + .setServiceIdBinary(oldMember.toByteString()) .setUuidCipherText(ByteString.copyFrom(uuidCiphertext.serialize())))); } @@ -257,20 +259,20 @@ public final class GroupsV2Operations_decrypt_change_Test { .setDeletedUserId(ByteString.copyFrom(uuidCiphertext))), DecryptedGroupChange.newBuilder() .addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() - .setUuid(UuidUtil.toByteString(UuidUtil.UNKNOWN_UUID)) + .setServiceIdBinary(UuidUtil.toByteString(UuidUtil.UNKNOWN_UUID)) .setUuidCipherText(ByteString.copyFrom(uuidCiphertext)))); } @Test public void can_decrypt_promote_pending_member_field9() { - UUID newMember = UUID.randomUUID(); + ACI newMember = ACI.from(UUID.randomUUID()); ProfileKey profileKey = newProfileKey(); GroupCandidate groupCandidate = groupCandidate(newMember, profileKey); assertDecryption(groupOperations.createAcceptInviteChange(groupCandidate.getExpiringProfileKeyCredential().get()), DecryptedGroupChange.newBuilder() .addPromotePendingMembers(DecryptedMember.newBuilder() - .setUuid(UuidUtil.toByteString(newMember)) + .setUuid(newMember.toByteString()) .setRole(Member.Role.DEFAULT) .setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setJoinedAtRevision(-1))); @@ -328,7 +330,7 @@ public final class GroupsV2Operations_decrypt_change_Test { @Test public void can_decrypt_member_requests_field16() { - UUID newRequestingMember = UUID.randomUUID(); + ACI newRequestingMember = ACI.from(UUID.randomUUID()); ProfileKey profileKey = newProfileKey(); GroupCandidate groupCandidate = groupCandidate(newRequestingMember, profileKey); @@ -337,7 +339,7 @@ public final class GroupsV2Operations_decrypt_change_Test { DecryptedGroupChange.newBuilder() .setRevision(10) .addNewRequestingMembers(DecryptedRequestingMember.newBuilder() - .setUuid(UuidUtil.toByteString(newRequestingMember)) + .setUuid(newRequestingMember.toByteString()) .setProfileKey(ByteString.copyFrom(profileKey.serialize())))); } @@ -350,7 +352,7 @@ public final class GroupsV2Operations_decrypt_change_Test { DecryptedGroupChange.newBuilder() .setRevision(10) .addDeleteRequestingMembers(UuidUtil.toByteString(newRequestingMember)) - .addNewBannedMembers(DecryptedBannedMember.newBuilder().setUuid(UuidUtil.toByteString(newRequestingMember)).build())); + .addNewBannedMembers(DecryptedBannedMember.newBuilder().setServiceIdBinary(UuidUtil.toByteString(newRequestingMember)).build())); } @Test @@ -402,42 +404,42 @@ public final class GroupsV2Operations_decrypt_change_Test { DecryptedGroupChange.newBuilder() .setRevision(13) .addNewBannedMembers(DecryptedBannedMember.newBuilder() - .setUuid(UuidUtil.toByteString(ban)))); + .setServiceIdBinary(UuidUtil.toByteString(ban)))); } @Test public void can_decrypt_banned_member_removals_field23() { - UUID ban = UUID.randomUUID(); + ACI ban = ACI.from(UUID.randomUUID()); - assertDecryption(groupOperations.createUnbanUuidsChange(Collections.singleton(ban)) + assertDecryption(groupOperations.createUnbanServiceIdsChange(Collections.singleton(ban)) .setRevision(13), DecryptedGroupChange.newBuilder() .setRevision(13) .addDeleteBannedMembers(DecryptedBannedMember.newBuilder() - .setUuid(UuidUtil.toByteString(ban)))); + .setServiceIdBinary(ban.toByteString()))); } @Test public void can_decrypt_promote_pending_pni_aci_member_field24() { - UUID memberUuid = UUID.randomUUID(); - UUID memberPni = UUID.randomUUID(); + ACI memberAci = ACI.from(UUID.randomUUID()); + PNI memberPni = PNI.from(UUID.randomUUID()); ProfileKey profileKey = newProfileKey(); GroupChange.Actions.Builder builder = GroupChange.Actions.newBuilder() - .setSourceUuid(groupOperations.encryptUuid(memberPni)) + .setSourceUuid(groupOperations.encryptServiceId(memberPni)) .setRevision(5) .addPromotePendingPniAciMembers(GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction.newBuilder() - .setUserId(groupOperations.encryptUuid(memberUuid)) - .setPni(groupOperations.encryptUuid(memberPni)) - .setProfileKey(encryptProfileKey(memberUuid, profileKey))); + .setUserId(groupOperations.encryptServiceId(memberAci)) + .setPni(groupOperations.encryptServiceId(memberPni)) + .setProfileKey(encryptProfileKey(memberAci, profileKey))); assertDecryptionWithEditorSet(builder, DecryptedGroupChange.newBuilder() - .setEditor(UuidUtil.toByteString(memberUuid)) + .setEditor(memberAci.toByteString()) .setRevision(5) .addPromotePendingPniAciMembers(DecryptedMember.newBuilder() - .setUuid(UuidUtil.toByteString(memberUuid)) - .setPni(UuidUtil.toByteString(memberPni)) + .setUuid(memberAci.toByteString()) + .setPni(memberPni.toByteString()) .setRole(Member.Role.DEFAULT) .setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setJoinedAtRevision(5))); @@ -451,23 +453,23 @@ public final class GroupsV2Operations_decrypt_change_Test { } } - private ByteString encryptProfileKey(UUID uuid, ProfileKey profileKey) { - return ByteString.copyFrom(new ClientZkGroupCipher(groupSecretParams).encryptProfileKey(profileKey, uuid).serialize()); + private ByteString encryptProfileKey(ACI aci, ProfileKey profileKey) { + return ByteString.copyFrom(new ClientZkGroupCipher(groupSecretParams).encryptProfileKey(profileKey, aci.getLibSignalAci()).serialize()); } static GroupCandidate groupCandidate(UUID uuid) { - return new GroupCandidate(uuid, Optional.empty()); + return new GroupCandidate(ACI.from(uuid), Optional.empty()); } - GroupCandidate groupCandidate(UUID uuid, ProfileKey profileKey) { + GroupCandidate groupCandidate(ACI aci, ProfileKey profileKey) { try { ClientZkProfileOperations profileOperations = clientZkOperations.getProfileOperations(); - ProfileKeyCommitment commitment = profileKey.getCommitment(uuid); - ProfileKeyCredentialRequestContext requestContext = profileOperations.createProfileKeyCredentialRequestContext(uuid, profileKey); + ProfileKeyCommitment commitment = profileKey.getCommitment(aci.getLibSignalAci()); + ProfileKeyCredentialRequestContext requestContext = profileOperations.createProfileKeyCredentialRequestContext(aci.getLibSignalAci(), profileKey); ProfileKeyCredentialRequest request = requestContext.getRequest(); - ExpiringProfileKeyCredentialResponse expiringProfileKeyCredentialResponse = server.getExpiringProfileKeyCredentialResponse(request, uuid, commitment, Instant.now().plus(7, ChronoUnit.DAYS).truncatedTo(ChronoUnit.DAYS)); + ExpiringProfileKeyCredentialResponse expiringProfileKeyCredentialResponse = server.getExpiringProfileKeyCredentialResponse(request, aci, commitment, Instant.now().plus(7, ChronoUnit.DAYS).truncatedTo(ChronoUnit.DAYS)); ExpiringProfileKeyCredential profileKeyCredential = profileOperations.receiveExpiringProfileKeyCredential(requestContext, expiringProfileKeyCredentialResponse); - GroupCandidate groupCandidate = new GroupCandidate(uuid, Optional.of(profileKeyCredential)); + GroupCandidate groupCandidate = new GroupCandidate(aci, Optional.of(profileKeyCredential)); ProfileKeyCredentialPresentation presentation = profileOperations.createProfileKeyCredentialPresentation(groupSecretParams, profileKeyCredential); server.assertProfileKeyCredentialPresentation(groupSecretParams.getPublicParams(), presentation, Instant.now()); @@ -481,8 +483,8 @@ public final class GroupsV2Operations_decrypt_change_Test { void assertDecryption(GroupChange.Actions.Builder inputChange, DecryptedGroupChange.Builder expectedDecrypted) { - UUID editor = UUID.randomUUID(); - assertDecryptionWithEditorSet(inputChange.setSourceUuid(groupOperations.encryptUuid(editor)), expectedDecrypted.setEditor(UuidUtil.toByteString(editor))); + ACI editor = ACI.from(UUID.randomUUID()); + assertDecryptionWithEditorSet(inputChange.setSourceUuid(groupOperations.encryptServiceId(editor)), expectedDecrypted.setEditor(editor.toByteString())); } void assertDecryptionWithEditorSet(GroupChange.Actions.Builder inputChange, diff --git a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations_decrypt_group_Test.java b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations_decrypt_group_Test.java index 769ee3fcee..cd9c3c87be 100644 --- a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations_decrypt_group_Test.java +++ b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/GroupsV2Operations_decrypt_group_Test.java @@ -22,7 +22,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.protos.groups.local.EnabledState; -import org.whispersystems.signalservice.api.util.UuidUtil; +import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.testutil.LibSignalLibraryUtil; @@ -122,20 +122,20 @@ public final class GroupsV2Operations_decrypt_group_Test { @Test public void decrypt_full_members_field_7() throws VerificationFailedException, InvalidGroupStateException { - UUID admin1 = UUID.randomUUID(); - UUID member1 = UUID.randomUUID(); + ACI admin1 = ACI.from(UUID.randomUUID()); + ACI member1 = ACI.from(UUID.randomUUID()); ProfileKey adminProfileKey = newProfileKey(); ProfileKey memberProfileKey = newProfileKey(); Group group = Group.newBuilder() .addMembers(Member.newBuilder() .setRole(Member.Role.ADMINISTRATOR) - .setUserId(groupOperations.encryptUuid(admin1)) + .setUserId(groupOperations.encryptServiceId(admin1)) .setJoinedAtRevision(4) .setProfileKey(encryptProfileKey(admin1, adminProfileKey))) .addMembers(Member.newBuilder() .setRole(Member.Role.DEFAULT) - .setUserId(groupOperations.encryptUuid(member1)) + .setUserId(groupOperations.encryptServiceId(member1)) .setJoinedAtRevision(7) .setProfileKey(encryptProfileKey(member1, memberProfileKey))) .build(); @@ -145,13 +145,13 @@ public final class GroupsV2Operations_decrypt_group_Test { assertEquals(DecryptedGroup.newBuilder() .addMembers(DecryptedMember.newBuilder() .setJoinedAtRevision(4) - .setUuid(UuidUtil.toByteString(admin1)) + .setUuid(admin1.toByteString()) .setRole(Member.Role.ADMINISTRATOR) .setProfileKey(ByteString.copyFrom(adminProfileKey.serialize()))) .addMembers(DecryptedMember.newBuilder() .setJoinedAtRevision(7) .setRole(Member.Role.DEFAULT) - .setUuid(UuidUtil.toByteString(member1)) + .setUuid(member1.toByteString()) .setProfileKey(ByteString.copyFrom(memberProfileKey.serialize()))) .build().getMembersList(), decryptedGroup.getMembersList()); @@ -159,52 +159,52 @@ public final class GroupsV2Operations_decrypt_group_Test { @Test public void decrypt_pending_members_field_8() throws VerificationFailedException, InvalidGroupStateException { - UUID admin1 = UUID.randomUUID(); - UUID member1 = UUID.randomUUID(); - UUID member2 = UUID.randomUUID(); - UUID inviter1 = UUID.randomUUID(); - UUID inviter2 = UUID.randomUUID(); + ACI admin1 = ACI.from(UUID.randomUUID()); + ACI member1 = ACI.from(UUID.randomUUID()); + ACI member2 = ACI.from(UUID.randomUUID()); + ACI inviter1 = ACI.from(UUID.randomUUID()); + ACI inviter2 = ACI.from(UUID.randomUUID()); Group group = Group.newBuilder() .addPendingMembers(PendingMember.newBuilder() - .setAddedByUserId(groupOperations.encryptUuid(inviter1)) + .setAddedByUserId(groupOperations.encryptServiceId(inviter1)) .setTimestamp(100) .setMember(Member.newBuilder() .setRole(Member.Role.ADMINISTRATOR) - .setUserId(groupOperations.encryptUuid(admin1)))) + .setUserId(groupOperations.encryptServiceId(admin1)))) .addPendingMembers(PendingMember.newBuilder() - .setAddedByUserId(groupOperations.encryptUuid(inviter1)) + .setAddedByUserId(groupOperations.encryptServiceId(inviter1)) .setTimestamp(200) .setMember(Member.newBuilder() .setRole(Member.Role.DEFAULT) - .setUserId(groupOperations.encryptUuid(member1)))) + .setUserId(groupOperations.encryptServiceId(member1)))) .addPendingMembers(PendingMember.newBuilder() - .setAddedByUserId(groupOperations.encryptUuid(inviter2)) + .setAddedByUserId(groupOperations.encryptServiceId(inviter2)) .setTimestamp(1500) .setMember(Member.newBuilder() - .setUserId(groupOperations.encryptUuid(member2)))) + .setUserId(groupOperations.encryptServiceId(member2)))) .build(); DecryptedGroup decryptedGroup = groupOperations.decryptGroup(group); assertEquals(DecryptedGroup.newBuilder() .addPendingMembers(DecryptedPendingMember.newBuilder() - .setUuid(UuidUtil.toByteString(admin1)) - .setUuidCipherText(groupOperations.encryptUuid(admin1)) + .setServiceIdBinary(admin1.toByteString()) + .setUuidCipherText(groupOperations.encryptServiceId(admin1)) .setTimestamp(100) - .setAddedByUuid(UuidUtil.toByteString(inviter1)) + .setAddedByUuid(inviter1.toByteString()) .setRole(Member.Role.ADMINISTRATOR)) .addPendingMembers(DecryptedPendingMember.newBuilder() - .setUuid(UuidUtil.toByteString(member1)) - .setUuidCipherText(groupOperations.encryptUuid(member1)) + .setServiceIdBinary(member1.toByteString()) + .setUuidCipherText(groupOperations.encryptServiceId(member1)) .setTimestamp(200) - .setAddedByUuid(UuidUtil.toByteString(inviter1)) + .setAddedByUuid(inviter1.toByteString()) .setRole(Member.Role.DEFAULT)) .addPendingMembers(DecryptedPendingMember.newBuilder() - .setUuid(UuidUtil.toByteString(member2)) - .setUuidCipherText(groupOperations.encryptUuid(member2)) + .setServiceIdBinary(member2.toByteString()) + .setUuidCipherText(groupOperations.encryptServiceId(member2)) .setTimestamp(1500) - .setAddedByUuid(UuidUtil.toByteString(inviter2)) + .setAddedByUuid(inviter2.toByteString()) .setRole(Member.Role.DEFAULT)) .build().getPendingMembersList(), decryptedGroup.getPendingMembersList()); @@ -212,18 +212,18 @@ public final class GroupsV2Operations_decrypt_group_Test { @Test public void decrypt_requesting_members_field_9() throws VerificationFailedException, InvalidGroupStateException { - UUID admin1 = UUID.randomUUID(); - UUID member1 = UUID.randomUUID(); + ACI admin1 = ACI.from(UUID.randomUUID()); + ACI member1 = ACI.from(UUID.randomUUID()); ProfileKey adminProfileKey = newProfileKey(); ProfileKey memberProfileKey = newProfileKey(); Group group = Group.newBuilder() .addRequestingMembers(RequestingMember.newBuilder() - .setUserId(groupOperations.encryptUuid(admin1)) + .setUserId(groupOperations.encryptServiceId(admin1)) .setProfileKey(encryptProfileKey(admin1, adminProfileKey)) .setTimestamp(5000)) .addRequestingMembers(RequestingMember.newBuilder() - .setUserId(groupOperations.encryptUuid(member1)) + .setUserId(groupOperations.encryptServiceId(member1)) .setProfileKey(encryptProfileKey(member1, memberProfileKey)) .setTimestamp(15000)) .build(); @@ -232,11 +232,11 @@ public final class GroupsV2Operations_decrypt_group_Test { assertEquals(DecryptedGroup.newBuilder() .addRequestingMembers(DecryptedRequestingMember.newBuilder() - .setUuid(UuidUtil.toByteString(admin1)) + .setUuid(admin1.toByteString()) .setProfileKey(ByteString.copyFrom(adminProfileKey.serialize())) .setTimestamp(5000)) .addRequestingMembers(DecryptedRequestingMember.newBuilder() - .setUuid(UuidUtil.toByteString(member1)) + .setUuid(member1.toByteString()) .setProfileKey(ByteString.copyFrom(memberProfileKey.serialize())) .setTimestamp(15000)) .build().getRequestingMembersList(), @@ -279,20 +279,20 @@ public final class GroupsV2Operations_decrypt_group_Test { @Test public void decrypt_banned_members_field_13() throws VerificationFailedException, InvalidGroupStateException { - UUID member1 = UUID.randomUUID(); + ACI member1 = ACI.from(UUID.randomUUID()); Group group = Group.newBuilder() - .addBannedMembers(BannedMember.newBuilder().setUserId(groupOperations.encryptUuid(member1))) + .addBannedMembers(BannedMember.newBuilder().setUserId(groupOperations.encryptServiceId(member1))) .build(); DecryptedGroup decryptedGroup = groupOperations.decryptGroup(group); assertEquals(1, decryptedGroup.getBannedMembersCount()); - assertEquals(DecryptedBannedMember.newBuilder().setUuid(UuidUtil.toByteString(member1)).build(), decryptedGroup.getBannedMembers(0)); + assertEquals(DecryptedBannedMember.newBuilder().setServiceIdBinary(member1.toByteString()).build(), decryptedGroup.getBannedMembers(0)); } - private ByteString encryptProfileKey(UUID uuid, ProfileKey profileKey) { - return ByteString.copyFrom(new ClientZkGroupCipher(groupSecretParams).encryptProfileKey(profileKey, uuid).serialize()); + private ByteString encryptProfileKey(ACI aci, ProfileKey profileKey) { + return ByteString.copyFrom(new ClientZkGroupCipher(groupSecretParams).encryptProfileKey(profileKey, aci.getLibSignalAci()).serialize()); } private static ProfileKey newProfileKey() { diff --git a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/ProtoTestUtils.java b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/ProtoTestUtils.java index 7feece9c2c..d2b43cf9ef 100644 --- a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/ProtoTestUtils.java +++ b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/ProtoTestUtils.java @@ -107,14 +107,14 @@ final class ProtoTestUtils { static DecryptedPendingMemberRemoval pendingMemberRemoval(UUID uuid) { return DecryptedPendingMemberRemoval.newBuilder() - .setUuid(UuidUtil.toByteString(uuid)) + .setServiceIdBinary(UuidUtil.toByteString(uuid)) .setUuidCipherText(encrypt(uuid)) .build(); } static DecryptedPendingMember pendingMember(UUID uuid) { return DecryptedPendingMember.newBuilder() - .setUuid(UuidUtil.toByteString(uuid)) + .setServiceIdBinary(UuidUtil.toByteString(uuid)) .setUuidCipherText(encrypt(uuid)) .setRole(Member.Role.DEFAULT) .build(); @@ -133,7 +133,7 @@ final class ProtoTestUtils { static DecryptedBannedMember bannedMember(UUID uuid) { return DecryptedBannedMember.newBuilder() - .setUuid(UuidUtil.toByteString(uuid)) + .setServiceIdBinary(UuidUtil.toByteString(uuid)) .build(); } diff --git a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/TestZkGroupServer.java b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/TestZkGroupServer.java index a416a026b9..bd074e5a14 100644 --- a/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/TestZkGroupServer.java +++ b/libsignal/service/src/test/java/org/whispersystems/signalservice/api/groupsv2/TestZkGroupServer.java @@ -9,10 +9,10 @@ import org.signal.libsignal.zkgroup.profiles.ProfileKeyCommitment; import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredentialPresentation; import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredentialRequest; import org.signal.libsignal.zkgroup.profiles.ServerZkProfileOperations; +import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.testutil.LibSignalLibraryUtil; import java.time.Instant; -import java.util.UUID; /** * Provides Zk group operations that the server would provide. @@ -35,8 +35,8 @@ final class TestZkGroupServer { return serverPublicParams; } - public ExpiringProfileKeyCredentialResponse getExpiringProfileKeyCredentialResponse(ProfileKeyCredentialRequest request, UUID uuid, ProfileKeyCommitment commitment, Instant expiration) throws VerificationFailedException { - return serverZkProfileOperations.issueExpiringProfileKeyCredential(request, uuid, commitment, expiration); + public ExpiringProfileKeyCredentialResponse getExpiringProfileKeyCredentialResponse(ProfileKeyCredentialRequest request, ACI aci, ProfileKeyCommitment commitment, Instant expiration) throws VerificationFailedException { + return serverZkProfileOperations.issueExpiringProfileKeyCredential(request, aci.getLibSignalAci(), commitment, expiration); } public void assertProfileKeyCredentialPresentation(GroupPublicParams publicParams, ProfileKeyCredentialPresentation profileKeyCredentialPresentation, Instant now) {