Fix sending group message to legacy targets without group send endorsements

Fixes #1849
This commit is contained in:
AsamK 2025-09-18 18:40:05 +02:00
parent 3be0aefa20
commit 69d892e5b1

View File

@ -484,18 +484,24 @@ public class SendHelper {
final var addressesMap = recipientIds.stream() final var addressesMap = recipientIds.stream()
.collect(Collectors.toMap(id -> id, context.getRecipientHelper()::resolveSignalServiceAddress)); .collect(Collectors.toMap(id -> id, context.getRecipientHelper()::resolveSignalServiceAddress));
final var unidentifiedAccessesMap = context.getUnidentifiedAccessHelper().getAccessFor(recipientIds); final var unidentifiedAccessesMap = context.getUnidentifiedAccessHelper().getAccessFor(recipientIds);
final var groupSendEndorsements = getGroupSendEndorsements(groupInfo); final var groupSendEndorsementsResult = getGroupSendEndorsements(groupInfo);
final var groupSecretParams = groupInfo instanceof GroupInfoV2 gv2 final var groupSecretParams = groupInfo instanceof GroupInfoV2 gv2
? GroupSecretParams.deriveFromMasterKey((gv2.getMasterKey())) ? GroupSecretParams.deriveFromMasterKey((gv2.getMasterKey()))
: null; : null;
final var groupSendEndorsements = groupSendEndorsementsResult == null
? null
: groupSendEndorsementsResult.second();
final var groupSendEndorsementsExpirationMs = groupSendEndorsementsResult == null
? 0
: groupSendEndorsementsResult.first();
Set<RecipientId> senderKeyTargets = groupInfo.getDistributionId() == null || groupSendEndorsements == null Set<RecipientId> senderKeyTargets = groupInfo.getDistributionId() == null || groupSendEndorsements == null
? Set.of() ? Set.of()
: recipientIds.stream() : recipientIds.stream()
.filter(s -> this.isSenderKeyCapable(s, .filter(s -> this.isSenderKeyCapable(s,
addressesMap.get(s), addressesMap.get(s),
unidentifiedAccessesMap.get(s), unidentifiedAccessesMap.get(s),
groupSendEndorsements.second())) groupSendEndorsements))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
if (senderKeyTargets.size() < 2) { if (senderKeyTargets.size() < 2) {
logger.debug("Too few sender-key-capable users ({}). Doing all legacy sends.", senderKeyTargets.size()); logger.debug("Too few sender-key-capable users ({}). Doing all legacy sends.", senderKeyTargets.size());
@ -508,14 +514,10 @@ public class SendHelper {
if (!senderKeyTargets.isEmpty()) { if (!senderKeyTargets.isEmpty()) {
final var senderCertificate = this.context.getUnidentifiedAccessHelper().getSenderCertificateFor(null); final var senderCertificate = this.context.getUnidentifiedAccessHelper().getSenderCertificateFor(null);
final var addresses = senderKeyTargets.stream().map(addressesMap::get).toList(); final var addresses = senderKeyTargets.stream().map(addressesMap::get).toList();
final var targets = senderKeyTargets; final var requiredGroupSendEndorsements = new GroupSendEndorsements(groupSendEndorsementsExpirationMs,
final var requiredGroupSendEndorsements = new GroupSendEndorsements(groupSendEndorsements.first(), senderKeyTargets.stream()
groupSendEndorsements.second() .collect(Collectors.toMap(recipientId -> (ACI) addressesMap.get(recipientId).getServiceId(),
.entrySet() groupSendEndorsements::get)),
.stream()
.filter(entry -> targets.contains(entry.getKey()))
.collect(Collectors.toMap(entry -> (ACI) addressesMap.get(entry.getKey()).getServiceId(),
Map.Entry::getValue)),
senderCertificate, senderCertificate,
groupSecretParams); groupSecretParams);
final var results = sendGroupMessageInternalWithSenderKey(senderKeySender, final var results = sendGroupMessageInternalWithSenderKey(senderKeySender,
@ -559,16 +561,14 @@ public class SendHelper {
.findFirst() .findFirst()
.map(UnidentifiedAccess::getUnidentifiedCertificate) .map(UnidentifiedAccess::getUnidentifiedCertificate)
.orElse(null); .orElse(null);
final var groupSendTokens = groupSendEndorsements != null ? groupSendEndorsements.second() final var expirationMs = Instant.ofEpochMilli(groupSendEndorsementsExpirationMs);
.entrySet() final var groupSendTokens = groupSendEndorsements != null && groupSecretParams != null
.stream() ? legacyTargets.stream()
.filter(entry -> legacyTargets.contains(entry.getKey())) .map(groupSendEndorsements::get)
.map(Map.Entry::getValue) .map(endorsement -> Optional.ofNullable(endorsement)
.map(e -> e == null || groupSecretParams == null .map(e -> e.toFullToken(groupSecretParams, expirationMs))
? null .orElse(null))
: e.toFullToken(groupSecretParams, Instant.ofEpochMilli(groupSendEndorsements.first())))
.toList() .toList()
: null; : null;
final var sealedSenderAccesses = SealedSenderAccess.forFanOutGroupSend(groupSendTokens, final var sealedSenderAccesses = SealedSenderAccess.forFanOutGroupSend(groupSendTokens,
senderCertificate, senderCertificate,
@ -605,7 +605,7 @@ public class SendHelper {
return null; return null;
} }
} }
return new Pair(groupSendEndorsementExpirationMs, groupSendEndorsementMap); return new Pair<>(groupSendEndorsementExpirationMs, groupSendEndorsementMap);
} }
private boolean isSenderKeyCapable( private boolean isSenderKeyCapable(