Clarify roles/responsibilities of components in the message-handling pathway

This commit is contained in:
Jon Chambers
2025-01-31 10:24:50 -05:00
committed by GitHub
parent 282bcf6f34
commit 48ada8e8ca
33 changed files with 1338 additions and 1199 deletions

View File

@@ -7,6 +7,9 @@ package org.whispersystems.textsecuregcm.auth;
import org.whispersystems.textsecuregcm.storage.Account;
import java.security.MessageDigest;
import java.util.Collection;
import java.util.function.Predicate;
import java.util.stream.IntStream;
public class UnidentifiedAccessUtil {
@@ -31,4 +34,42 @@ public class UnidentifiedAccessUtil {
.map(targetUnidentifiedAccessKey -> MessageDigest.isEqual(targetUnidentifiedAccessKey, unidentifiedAccessKey))
.orElse(false);
}
/**
* Checks whether an action (e.g. sending a message or retrieving pre-keys) may be taken on the collection of target
* accounts by an actor presenting the given combined unidentified access key.
*
* @param targetAccounts the accounts on which an actor wishes to take an action
* @param combinedUnidentifiedAccessKey the unidentified access key presented by the actor
*
* @return {@code true} if an actor presenting the given unidentified access key has permission to take an action on
* the target accounts or {@code false} otherwise
*/
public static boolean checkUnidentifiedAccess(final Collection<Account> targetAccounts, final byte[] combinedUnidentifiedAccessKey) {
return MessageDigest.isEqual(getCombinedUnidentifiedAccessKey(targetAccounts), combinedUnidentifiedAccessKey);
}
/**
* Calculates a combined unidentified access key for the given collection of accounts.
*
* @param accounts the accounts from which to derive a combined unidentified access key
* @return a combined unidentified access key
*
* @throws IllegalArgumentException if one or more of the given accounts had an unidentified access key with an
* unexpected length
*/
public static byte[] getCombinedUnidentifiedAccessKey(final Collection<Account> accounts) {
return accounts.stream()
.filter(Predicate.not(Account::isUnrestrictedUnidentifiedAccess))
.map(account ->
account.getUnidentifiedAccessKey()
.filter(b -> b.length == UnidentifiedAccessUtil.UNIDENTIFIED_ACCESS_KEY_LENGTH)
.orElseThrow(IllegalArgumentException::new))
.reduce(new byte[UnidentifiedAccessUtil.UNIDENTIFIED_ACCESS_KEY_LENGTH],
(a, b) -> {
final byte[] xor = new byte[UnidentifiedAccessUtil.UNIDENTIFIED_ACCESS_KEY_LENGTH];
IntStream.range(0, UnidentifiedAccessUtil.UNIDENTIFIED_ACCESS_KEY_LENGTH).forEach(i -> xor[i] = (byte) (a[i] ^ b[i]));
return xor;
});
}
}