Handle edge cases of Math.abs on integers.

This commit is contained in:
erik-signal 2022-12-20 12:25:04 -05:00 committed by GitHub
parent 2c2c497c12
commit d138fa45df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 5 deletions

View File

@ -7,6 +7,7 @@ package org.whispersystems.textsecuregcm.auth;
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.codec.binary.Hex;
import org.signal.libsignal.protocol.kdf.HKDF;
import org.whispersystems.textsecuregcm.util.Util;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
@ -32,13 +33,13 @@ public class AuthenticationCredentials {
}
public AuthenticationCredentials(String authenticationToken) {
this.salt = String.valueOf(Math.abs(new SecureRandom().nextInt()));
this.salt = String.valueOf(Util.ensureNonNegativeInt(new SecureRandom().nextInt()));
this.hashedAuthenticationToken = getV2HashedValue(salt, authenticationToken);
}
@VisibleForTesting
public AuthenticationCredentials v1ForTesting(String authenticationToken) {
String salt = String.valueOf(Math.abs(new SecureRandom().nextInt()));
String salt = String.valueOf(Util.ensureNonNegativeInt(new SecureRandom().nextInt()));
return new AuthenticationCredentials(getV1HashedValue(salt, authenticationToken), salt);
}

View File

@ -146,9 +146,18 @@ public class BaseAccountAuthenticator {
@VisibleForTesting
public Account updateLastSeen(Account account, Device device) {
final long lastSeenOffsetSeconds = Math.abs(account.getUuid().getLeastSignificantBits()) % ChronoUnit.DAYS.getDuration().toSeconds();
// compute a non-negative integer between 0 and 86400.
long n = Util.ensureNonNegativeLong(account.getUuid().getLeastSignificantBits());
final long lastSeenOffsetSeconds = n % ChronoUnit.DAYS.getDuration().toSeconds();
// produce a truncated timestamp which is either today at UTC midnight
// or yesterday at UTC midnight, based on per-user randomized offset used.
final long todayInMillisWithOffset = Util.todayInMillisGivenOffsetFromNow(clock, Duration.ofSeconds(lastSeenOffsetSeconds).negated());
// only update the device's last seen time when it falls behind the truncated timestamp.
// this ensure a few things:
// (1) each account will only update last-seen at most once per day
// (2) these updates will occur throughout the day rather than all occurring at UTC midnight.
if (device.getLastSeen() < todayInMillisWithOffset) {
Metrics.summary(DAYS_SINCE_LAST_SEEN_DISTRIBUTION_NAME, IS_PRIMARY_DEVICE_TAG, String.valueOf(device.isMaster()))
.record(Duration.ofMillis(todayInMillisWithOffset - device.getLastSeen()).toDays());

View File

@ -10,6 +10,7 @@ import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfigurati
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicTurnConfiguration;
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
import org.whispersystems.textsecuregcm.util.Pair;
import org.whispersystems.textsecuregcm.util.Util;
import org.whispersystems.textsecuregcm.util.WeightedRandomSelect;
import javax.crypto.Mac;
@ -36,7 +37,7 @@ public class TurnTokenGenerator {
List<String> urls = urls(e164);
Mac mac = Mac.getInstance("HmacSHA1");
long validUntilSeconds = (System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1)) / 1000;
long user = Math.abs(new SecureRandom().nextInt());
long user = Util.ensureNonNegativeInt(new SecureRandom().nextInt());
String userTime = validUntilSeconds + ":" + user;
mac.init(new SecretKeySpec(key, "HmacSHA1"));

View File

@ -41,6 +41,7 @@ import org.whispersystems.textsecuregcm.entities.UserRemoteConfigList;
import org.whispersystems.textsecuregcm.storage.RemoteConfig;
import org.whispersystems.textsecuregcm.storage.RemoteConfigsManager;
import org.whispersystems.textsecuregcm.util.Conversions;
import org.whispersystems.textsecuregcm.util.Util;
@Path("/v1/config")
public class RemoteConfigController {
@ -133,7 +134,7 @@ public class RemoteConfigController {
digest.update(bb.array());
byte[] hash = digest.digest(hashKey);
int bucket = (int)(Math.abs(Conversions.byteArrayToLong(hash)) % 100);
int bucket = (int)(Util.ensureNonNegativeLong(Conversions.byteArrayToLong(hash)) % 100);
return bucket < configPercentage;
}

View File

@ -191,4 +191,29 @@ public class Util {
public static Optional<String> findBestLocale(List<LanguageRange> priorityList, Collection<String> supportedLocales) {
return Optional.ofNullable(Locale.lookupTag(priorityList, supportedLocales));
}
/**
* Map ints to non-negative ints.
* <br>
* Unlike Math.abs this method handles Integer.MIN_VALUE correctly.
*
* @param n any int value
* @return an int value guaranteed to be non-negative
*/
public static int ensureNonNegativeInt(int n) {
return n == Integer.MIN_VALUE ? 0 : Math.abs(n);
}
/**
* Map longs to non-negative longs.
* <br>
* Unlike Math.abs this method handles Long.MIN_VALUE correctly.
*
* @param n any long value
* @return a long value guaranteed to be non-negative
*/
public static long ensureNonNegativeLong(long n) {
return n == Long.MIN_VALUE ? 0 : Math.abs(n);
}
}