Apply decrypted group change when receiving signed change

This commit is contained in:
AsamK 2020-12-12 11:51:38 +01:00
parent c10910e466
commit 98dee97cc6
2 changed files with 51 additions and 2 deletions

View file

@ -1534,8 +1534,18 @@ public class Manager implements Closeable {
if (groupInfoV2.getGroup() == null if (groupInfoV2.getGroup() == null
|| groupInfoV2.getGroup().getRevision() < groupContext.getRevision()) { || groupInfoV2.getGroup().getRevision() < groupContext.getRevision()) {
// TODO check if revision is only 1 behind and a signedGroupChange is available DecryptedGroup group = null;
groupInfoV2.setGroup(getDecryptedGroup(groupSecretParams)); if (groupContext.hasSignedGroupChange()
&& groupInfoV2.getGroup() != null
&& groupInfoV2.getGroup().getRevision() + 1 == groupContext.getRevision()) {
group = groupHelper.getUpdatedDecryptedGroup(groupInfoV2.getGroup(),
groupContext.getSignedGroupChange(),
groupMasterKey);
}
if (group == null) {
group = getDecryptedGroup(groupSecretParams);
}
groupInfoV2.setGroup(group);
account.getGroupStore().updateGroup(groupInfoV2); account.getGroupStore().updateGroup(groupInfoV2);
} }
} }

View file

@ -1,11 +1,21 @@
package org.asamk.signal.manager.helper; package org.asamk.signal.manager.helper;
import com.google.protobuf.InvalidProtocolBufferException;
import org.signal.storageservice.protos.groups.GroupChange;
import org.signal.storageservice.protos.groups.Member; import org.signal.storageservice.protos.groups.Member;
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
import org.signal.zkgroup.VerificationFailedException;
import org.signal.zkgroup.groups.GroupMasterKey;
import org.signal.zkgroup.groups.GroupSecretParams; import org.signal.zkgroup.groups.GroupSecretParams;
import org.signal.zkgroup.profiles.ProfileKeyCredential; import org.signal.zkgroup.profiles.ProfileKeyCredential;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
import org.whispersystems.signalservice.api.groupsv2.GroupCandidate; import org.whispersystems.signalservice.api.groupsv2.GroupCandidate;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations; import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException;
import org.whispersystems.signalservice.api.groupsv2.NotAbleToApplyGroupV2ChangeException;
import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import java.util.Collection; import java.util.Collection;
@ -80,4 +90,33 @@ public class GroupHelper {
0); 0);
} }
public DecryptedGroup getUpdatedDecryptedGroup(
DecryptedGroup group, byte[] signedGroupChange, GroupMasterKey groupMasterKey
) {
try {
final DecryptedGroupChange decryptedGroupChange = getDecryptedGroupChange(signedGroupChange,
groupMasterKey);
if (decryptedGroupChange == null) {
return null;
}
return DecryptedGroupUtil.apply(group, decryptedGroupChange);
} catch (NotAbleToApplyGroupV2ChangeException e) {
return null;
}
}
private DecryptedGroupChange getDecryptedGroupChange(byte[] signedGroupChange, GroupMasterKey groupMasterKey) {
if (signedGroupChange != null) {
GroupsV2Operations.GroupOperations groupOperations = groupsV2Operations.forGroup(GroupSecretParams.deriveFromMasterKey(
groupMasterKey));
try {
return groupOperations.decryptChange(GroupChange.parseFrom(signedGroupChange), true).orNull();
} catch (VerificationFailedException | InvalidGroupStateException | InvalidProtocolBufferException e) {
return null;
}
}
return null;
}
} }