mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-21 00:38:04 +01:00
Update keys gRPC endpoint to use service identifiers
This commit is contained in:
@@ -6,15 +6,17 @@
|
||||
package org.whispersystems.textsecuregcm.grpc;
|
||||
|
||||
import io.grpc.Status;
|
||||
import org.whispersystems.textsecuregcm.identity.IdentityType;
|
||||
|
||||
public enum IdentityType {
|
||||
ACI,
|
||||
PNI;
|
||||
public class IdentityTypeUtil {
|
||||
|
||||
private IdentityTypeUtil() {
|
||||
}
|
||||
|
||||
public static IdentityType fromGrpcIdentityType(final org.signal.chat.common.IdentityType grpcIdentityType) {
|
||||
return switch (grpcIdentityType) {
|
||||
case IDENTITY_TYPE_ACI -> ACI;
|
||||
case IDENTITY_TYPE_PNI -> PNI;
|
||||
case IDENTITY_TYPE_ACI -> IdentityType.ACI;
|
||||
case IDENTITY_TYPE_PNI -> IdentityType.PNI;
|
||||
case IDENTITY_TYPE_UNSPECIFIED, UNRECOGNIZED -> throw Status.INVALID_ARGUMENT.asRuntimeException();
|
||||
};
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import org.signal.chat.keys.GetPreKeysAnonymousRequest;
|
||||
import org.signal.chat.keys.GetPreKeysResponse;
|
||||
import org.signal.chat.keys.ReactorKeysAnonymousGrpc;
|
||||
import org.whispersystems.textsecuregcm.auth.UnidentifiedAccessUtil;
|
||||
import org.whispersystems.textsecuregcm.identity.ServiceIdentifier;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.KeysManager;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -26,15 +27,15 @@ public class KeysAnonymousGrpcService extends ReactorKeysAnonymousGrpc.KeysAnony
|
||||
|
||||
@Override
|
||||
public Mono<GetPreKeysResponse> getPreKeys(final GetPreKeysAnonymousRequest request) {
|
||||
return KeysGrpcHelper.findAccount(request.getTargetIdentifier(), accountsManager)
|
||||
.switchIfEmpty(Mono.error(Status.UNAUTHENTICATED.asException()))
|
||||
.flatMap(targetAccount -> {
|
||||
final IdentityType identityType =
|
||||
IdentityType.fromGrpcIdentityType(request.getTargetIdentifier().getIdentityType());
|
||||
final ServiceIdentifier serviceIdentifier =
|
||||
ServiceIdentifierUtil.fromGrpcServiceIdentifier(request.getTargetIdentifier());
|
||||
|
||||
return UnidentifiedAccessUtil.checkUnidentifiedAccess(targetAccount, request.getUnidentifiedAccessKey().toByteArray())
|
||||
? KeysGrpcHelper.getPreKeys(targetAccount, identityType, request.getDeviceId(), keysManager)
|
||||
: Mono.error(Status.UNAUTHENTICATED.asException());
|
||||
});
|
||||
return Mono.fromFuture(accountsManager.getByServiceIdentifierAsync(serviceIdentifier))
|
||||
.flatMap(Mono::justOrEmpty)
|
||||
.switchIfEmpty(Mono.error(Status.UNAUTHENTICATED.asException()))
|
||||
.flatMap(targetAccount ->
|
||||
UnidentifiedAccessUtil.checkUnidentifiedAccess(targetAccount, request.getUnidentifiedAccessKey().toByteArray())
|
||||
? KeysGrpcHelper.getPreKeys(targetAccount, serviceIdentifier.identityType(), request.getDeviceId(), keysManager)
|
||||
: Mono.error(Status.UNAUTHENTICATED.asException()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,19 +8,17 @@ package org.whispersystems.textsecuregcm.grpc;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.protobuf.ByteString;
|
||||
import io.grpc.Status;
|
||||
import java.util.UUID;
|
||||
import org.signal.chat.common.EcPreKey;
|
||||
import org.signal.chat.common.EcSignedPreKey;
|
||||
import org.signal.chat.common.KemSignedPreKey;
|
||||
import org.signal.chat.common.ServiceIdentifier;
|
||||
import org.signal.chat.keys.GetPreKeysResponse;
|
||||
import org.signal.libsignal.protocol.IdentityKey;
|
||||
import org.whispersystems.textsecuregcm.entities.ECPreKey;
|
||||
import org.whispersystems.textsecuregcm.entities.ECSignedPreKey;
|
||||
import org.whispersystems.textsecuregcm.entities.KEMSignedPreKey;
|
||||
import org.whispersystems.textsecuregcm.identity.IdentityType;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
import org.whispersystems.textsecuregcm.storage.KeysManager;
|
||||
import org.whispersystems.textsecuregcm.util.UUIDUtil;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuple2;
|
||||
@@ -31,37 +29,10 @@ class KeysGrpcHelper {
|
||||
@VisibleForTesting
|
||||
static final long ALL_DEVICES = 0;
|
||||
|
||||
static Mono<Account> findAccount(final ServiceIdentifier targetIdentifier, final AccountsManager accountsManager) {
|
||||
|
||||
return Mono.just(IdentityType.fromGrpcIdentityType(targetIdentifier.getIdentityType()))
|
||||
.flatMap(identityType -> {
|
||||
final UUID uuid = UUIDUtil.fromByteString(targetIdentifier.getUuid());
|
||||
|
||||
return Mono.fromFuture(switch (identityType) {
|
||||
case ACI -> accountsManager.getByAccountIdentifierAsync(uuid);
|
||||
case PNI -> accountsManager.getByPhoneNumberIdentifierAsync(uuid);
|
||||
});
|
||||
})
|
||||
.flatMap(Mono::justOrEmpty)
|
||||
.onErrorMap(IllegalArgumentException.class, throwable -> Status.INVALID_ARGUMENT.asException());
|
||||
}
|
||||
|
||||
static Tuple2<UUID, IdentityKey> getIdentifierAndIdentityKey(final Account account, final IdentityType identityType) {
|
||||
final UUID identifier = switch (identityType) {
|
||||
case ACI -> account.getUuid();
|
||||
case PNI -> account.getPhoneNumberIdentifier();
|
||||
};
|
||||
|
||||
final IdentityKey identityKey = switch (identityType) {
|
||||
case ACI -> account.getIdentityKey();
|
||||
case PNI -> account.getPhoneNumberIdentityKey();
|
||||
};
|
||||
|
||||
return Tuples.of(identifier, identityKey);
|
||||
}
|
||||
|
||||
static Mono<GetPreKeysResponse> getPreKeys(final Account targetAccount, final IdentityType identityType, final long targetDeviceId, final KeysManager keysManager) {
|
||||
final Tuple2<UUID, IdentityKey> identifierAndIdentityKey = getIdentifierAndIdentityKey(targetAccount, identityType);
|
||||
static Mono<GetPreKeysResponse> getPreKeys(final Account targetAccount,
|
||||
final IdentityType identityType,
|
||||
final long targetDeviceId,
|
||||
final KeysManager keysManager) {
|
||||
|
||||
final Flux<Device> devices = targetDeviceId == ALL_DEVICES
|
||||
? Flux.fromIterable(targetAccount.getDevices())
|
||||
@@ -70,37 +41,43 @@ class KeysGrpcHelper {
|
||||
return devices
|
||||
.filter(Device::isEnabled)
|
||||
.switchIfEmpty(Mono.error(Status.NOT_FOUND.asException()))
|
||||
.flatMap(device -> Mono.zip(Mono.fromFuture(keysManager.takeEC(identifierAndIdentityKey.getT1(), device.getId())),
|
||||
Mono.fromFuture(keysManager.takePQ(identifierAndIdentityKey.getT1(), device.getId())))
|
||||
.map(oneTimePreKeys -> {
|
||||
final ECSignedPreKey ecSignedPreKey = switch (identityType) {
|
||||
case ACI -> device.getSignedPreKey();
|
||||
case PNI -> device.getPhoneNumberIdentitySignedPreKey();
|
||||
};
|
||||
.flatMap(device -> {
|
||||
final ECSignedPreKey ecSignedPreKey = device.getSignedPreKey(identityType);
|
||||
|
||||
final GetPreKeysResponse.PreKeyBundle.Builder preKeyBundleBuilder = GetPreKeysResponse.PreKeyBundle.newBuilder()
|
||||
.setEcSignedPreKey(EcSignedPreKey.newBuilder()
|
||||
.setKeyId(ecSignedPreKey.keyId())
|
||||
.setPublicKey(ByteString.copyFrom(ecSignedPreKey.serializedPublicKey()))
|
||||
.setSignature(ByteString.copyFrom(ecSignedPreKey.signature()))
|
||||
final GetPreKeysResponse.PreKeyBundle.Builder preKeyBundleBuilder = GetPreKeysResponse.PreKeyBundle.newBuilder()
|
||||
.setEcSignedPreKey(EcSignedPreKey.newBuilder()
|
||||
.setKeyId(ecSignedPreKey.keyId())
|
||||
.setPublicKey(ByteString.copyFrom(ecSignedPreKey.serializedPublicKey()))
|
||||
.setSignature(ByteString.copyFrom(ecSignedPreKey.signature()))
|
||||
.build());
|
||||
|
||||
return Flux.merge(
|
||||
Mono.fromFuture(keysManager.takeEC(targetAccount.getIdentifier(identityType), device.getId())),
|
||||
Mono.fromFuture(keysManager.takePQ(targetAccount.getIdentifier(identityType), device.getId())))
|
||||
.flatMap(Mono::justOrEmpty)
|
||||
.reduce(preKeyBundleBuilder, (builder, preKey) -> {
|
||||
if (preKey instanceof ECPreKey ecPreKey) {
|
||||
builder.setEcOneTimePreKey(EcPreKey.newBuilder()
|
||||
.setKeyId(ecPreKey.keyId())
|
||||
.setPublicKey(ByteString.copyFrom(ecPreKey.serializedPublicKey()))
|
||||
.build());
|
||||
} else if (preKey instanceof KEMSignedPreKey kemSignedPreKey) {
|
||||
preKeyBundleBuilder.setKemOneTimePreKey(KemSignedPreKey.newBuilder()
|
||||
.setKeyId(kemSignedPreKey.keyId())
|
||||
.setPublicKey(ByteString.copyFrom(kemSignedPreKey.serializedPublicKey()))
|
||||
.setSignature(ByteString.copyFrom(kemSignedPreKey.signature()))
|
||||
.build());
|
||||
} else {
|
||||
throw new AssertionError("Unexpected pre-key type: " + preKey.getClass());
|
||||
}
|
||||
|
||||
oneTimePreKeys.getT1().ifPresent(ecPreKey -> preKeyBundleBuilder.setEcOneTimePreKey(EcPreKey.newBuilder()
|
||||
.setKeyId(ecPreKey.keyId())
|
||||
.setPublicKey(ByteString.copyFrom(ecPreKey.serializedPublicKey()))
|
||||
.build()));
|
||||
|
||||
oneTimePreKeys.getT2().ifPresent(kemSignedPreKey -> preKeyBundleBuilder.setKemOneTimePreKey(KemSignedPreKey.newBuilder()
|
||||
.setKeyId(kemSignedPreKey.keyId())
|
||||
.setPublicKey(ByteString.copyFrom(kemSignedPreKey.serializedPublicKey()))
|
||||
.setSignature(ByteString.copyFrom(kemSignedPreKey.signature()))
|
||||
.build()));
|
||||
|
||||
return Tuples.of(device.getId(), preKeyBundleBuilder.build());
|
||||
}))
|
||||
return builder;
|
||||
})
|
||||
.map(builder -> Tuples.of(device.getId(), builder.build()));
|
||||
})
|
||||
.collectMap(Tuple2::getT1, Tuple2::getT2)
|
||||
.map(preKeyBundles -> GetPreKeysResponse.newBuilder()
|
||||
.setIdentityKey(ByteString.copyFrom(identifierAndIdentityKey.getT2().serialize()))
|
||||
.setIdentityKey(ByteString.copyFrom(targetAccount.getIdentityKey(identityType).serialize()))
|
||||
.putAllPreKeys(preKeyBundles)
|
||||
.build());
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
package org.whispersystems.textsecuregcm.grpc;
|
||||
|
||||
import static org.whispersystems.textsecuregcm.grpc.IdentityType.ACI;
|
||||
|
||||
import io.grpc.Status;
|
||||
import io.grpc.StatusRuntimeException;
|
||||
import java.util.List;
|
||||
@@ -37,15 +35,15 @@ import org.whispersystems.textsecuregcm.auth.grpc.AuthenticationUtil;
|
||||
import org.whispersystems.textsecuregcm.entities.ECPreKey;
|
||||
import org.whispersystems.textsecuregcm.entities.ECSignedPreKey;
|
||||
import org.whispersystems.textsecuregcm.entities.KEMSignedPreKey;
|
||||
import org.whispersystems.textsecuregcm.identity.IdentityType;
|
||||
import org.whispersystems.textsecuregcm.identity.ServiceIdentifier;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
import org.whispersystems.textsecuregcm.storage.KeysManager;
|
||||
import org.whispersystems.textsecuregcm.util.UUIDUtil;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuple2;
|
||||
import reactor.util.function.Tuples;
|
||||
|
||||
public class KeysGrpcService extends ReactorKeysGrpc.KeysImplBase {
|
||||
@@ -89,7 +87,7 @@ public class KeysGrpcService extends ReactorKeysGrpc.KeysImplBase {
|
||||
.map(account -> Tuples.of(account, authenticatedDevice.deviceId()))
|
||||
.orElseThrow(Status.UNAUTHENTICATED::asRuntimeException)))
|
||||
.flatMapMany(accountAndDeviceId -> Flux.just(
|
||||
Tuples.of(ACI, accountAndDeviceId.getT1().getUuid(), accountAndDeviceId.getT2()),
|
||||
Tuples.of(IdentityType.ACI, accountAndDeviceId.getT1().getUuid(), accountAndDeviceId.getT2()),
|
||||
Tuples.of(IdentityType.PNI, accountAndDeviceId.getT1().getPhoneNumberIdentifier(), accountAndDeviceId.getT2())
|
||||
))
|
||||
.flatMap(identityTypeUuidAndDeviceId -> Flux.merge(
|
||||
@@ -128,31 +126,20 @@ public class KeysGrpcService extends ReactorKeysGrpc.KeysImplBase {
|
||||
public Mono<GetPreKeysResponse> getPreKeys(final GetPreKeysRequest request) {
|
||||
final AuthenticatedDevice authenticatedDevice = AuthenticationUtil.requireAuthenticatedDevice();
|
||||
|
||||
final String rateLimitKey;
|
||||
{
|
||||
final UUID targetUuid;
|
||||
final ServiceIdentifier targetIdentifier =
|
||||
ServiceIdentifierUtil.fromGrpcServiceIdentifier(request.getTargetIdentifier());
|
||||
|
||||
try {
|
||||
targetUuid = UUIDUtil.fromByteString(request.getTargetIdentifier().getUuid());
|
||||
} catch (final IllegalArgumentException e) {
|
||||
throw Status.INVALID_ARGUMENT.asRuntimeException();
|
||||
}
|
||||
|
||||
rateLimitKey = authenticatedDevice.accountIdentifier() + "." +
|
||||
authenticatedDevice.deviceId() + "__" +
|
||||
targetUuid + "." +
|
||||
request.getDeviceId();
|
||||
}
|
||||
final String rateLimitKey = authenticatedDevice.accountIdentifier() + "." +
|
||||
authenticatedDevice.deviceId() + "__" +
|
||||
targetIdentifier.uuid() + "." +
|
||||
request.getDeviceId();
|
||||
|
||||
return rateLimiters.getPreKeysLimiter().validateReactive(rateLimitKey)
|
||||
.then(KeysGrpcHelper.findAccount(request.getTargetIdentifier(), accountsManager))
|
||||
.then(Mono.fromFuture(accountsManager.getByServiceIdentifierAsync(targetIdentifier))
|
||||
.flatMap(Mono::justOrEmpty))
|
||||
.switchIfEmpty(Mono.error(Status.NOT_FOUND.asException()))
|
||||
.flatMap(targetAccount -> {
|
||||
final IdentityType identityType =
|
||||
IdentityType.fromGrpcIdentityType(request.getTargetIdentifier().getIdentityType());
|
||||
|
||||
return KeysGrpcHelper.getPreKeys(targetAccount, identityType, request.getDeviceId(), keysManager);
|
||||
});
|
||||
.flatMap(targetAccount ->
|
||||
KeysGrpcHelper.getPreKeys(targetAccount, targetIdentifier.identityType(), request.getDeviceId(), keysManager));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -160,7 +147,7 @@ public class KeysGrpcService extends ReactorKeysGrpc.KeysImplBase {
|
||||
return Mono.fromSupplier(AuthenticationUtil::requireAuthenticatedDevice)
|
||||
.flatMap(authenticatedDevice -> storeOneTimePreKeys(authenticatedDevice.accountIdentifier(),
|
||||
request.getPreKeysList(),
|
||||
IdentityType.fromGrpcIdentityType(request.getIdentityType()),
|
||||
IdentityTypeUtil.fromGrpcIdentityType(request.getIdentityType()),
|
||||
(requestPreKey, ignored) -> checkEcPreKey(requestPreKey),
|
||||
(identifier, preKeys) -> keysManager.storeEcOneTimePreKeys(identifier, authenticatedDevice.deviceId(), preKeys)));
|
||||
}
|
||||
@@ -170,7 +157,7 @@ public class KeysGrpcService extends ReactorKeysGrpc.KeysImplBase {
|
||||
return Mono.fromSupplier(AuthenticationUtil::requireAuthenticatedDevice)
|
||||
.flatMap(authenticatedDevice -> storeOneTimePreKeys(authenticatedDevice.accountIdentifier(),
|
||||
request.getPreKeysList(),
|
||||
IdentityType.fromGrpcIdentityType(request.getIdentityType()),
|
||||
IdentityTypeUtil.fromGrpcIdentityType(request.getIdentityType()),
|
||||
KeysGrpcService::checkKemSignedPreKey,
|
||||
(identifier, preKeys) -> keysManager.storeKemOneTimePreKeys(identifier, authenticatedDevice.deviceId(), preKeys)));
|
||||
}
|
||||
@@ -184,18 +171,15 @@ public class KeysGrpcService extends ReactorKeysGrpc.KeysImplBase {
|
||||
return Mono.fromFuture(accountsManager.getByAccountIdentifierAsync(authenticatedAccountUuid))
|
||||
.map(maybeAccount -> maybeAccount.orElseThrow(Status.UNAUTHENTICATED::asRuntimeException))
|
||||
.map(account -> {
|
||||
final Tuple2<UUID, IdentityKey> identifierAndIdentityKey =
|
||||
KeysGrpcHelper.getIdentifierAndIdentityKey(account, identityType);
|
||||
|
||||
final List<K> preKeys = requestPreKeys.stream()
|
||||
.map(requestPreKey -> extractPreKeyFunction.apply(requestPreKey, identifierAndIdentityKey.getT2()))
|
||||
.map(requestPreKey -> extractPreKeyFunction.apply(requestPreKey, account.getIdentityKey(identityType)))
|
||||
.toList();
|
||||
|
||||
if (preKeys.isEmpty()) {
|
||||
throw Status.INVALID_ARGUMENT.asRuntimeException();
|
||||
}
|
||||
|
||||
return Tuples.of(identifierAndIdentityKey.getT1(), preKeys);
|
||||
return Tuples.of(account.getIdentifier(identityType), preKeys);
|
||||
})
|
||||
.flatMap(identifierAndPreKeys -> Mono.fromFuture(storeKeysFunction.apply(identifierAndPreKeys.getT1(), identifierAndPreKeys.getT2())))
|
||||
.thenReturn(SetPreKeyResponse.newBuilder().build());
|
||||
@@ -209,15 +193,14 @@ public class KeysGrpcService extends ReactorKeysGrpc.KeysImplBase {
|
||||
request.getSignedPreKey(),
|
||||
KeysGrpcService::checkEcSignedPreKey,
|
||||
(account, signedPreKey) -> {
|
||||
final Consumer<Device> deviceUpdater = switch (IdentityType.fromGrpcIdentityType(request.getIdentityType())) {
|
||||
final IdentityType identityType = IdentityTypeUtil.fromGrpcIdentityType(request.getIdentityType());
|
||||
|
||||
final Consumer<Device> deviceUpdater = switch (identityType) {
|
||||
case ACI -> device -> device.setSignedPreKey(signedPreKey);
|
||||
case PNI -> device -> device.setPhoneNumberIdentitySignedPreKey(signedPreKey);
|
||||
};
|
||||
|
||||
final UUID identifier = switch (IdentityType.fromGrpcIdentityType(request.getIdentityType())) {
|
||||
case ACI -> account.getUuid();
|
||||
case PNI -> account.getPhoneNumberIdentifier();
|
||||
};
|
||||
final UUID identifier = account.getIdentifier(identityType);
|
||||
|
||||
return Flux.merge(
|
||||
Mono.fromFuture(keysManager.storeEcSignedPreKeys(identifier, Map.of(authenticatedDevice.deviceId(), signedPreKey))),
|
||||
@@ -234,10 +217,8 @@ public class KeysGrpcService extends ReactorKeysGrpc.KeysImplBase {
|
||||
request.getSignedPreKey(),
|
||||
KeysGrpcService::checkKemSignedPreKey,
|
||||
(account, lastResortKey) -> {
|
||||
final UUID identifier = switch (IdentityType.fromGrpcIdentityType(request.getIdentityType())) {
|
||||
case ACI -> account.getUuid();
|
||||
case PNI -> account.getPhoneNumberIdentifier();
|
||||
};
|
||||
final UUID identifier =
|
||||
account.getIdentifier(IdentityTypeUtil.fromGrpcIdentityType(request.getIdentityType()));
|
||||
|
||||
return Mono.fromFuture(keysManager.storePqLastResort(identifier, Map.of(authenticatedDevice.deviceId(), lastResortKey)));
|
||||
}));
|
||||
@@ -252,11 +233,7 @@ public class KeysGrpcService extends ReactorKeysGrpc.KeysImplBase {
|
||||
return Mono.fromFuture(accountsManager.getByAccountIdentifierAsync(authenticatedAccountUuid))
|
||||
.map(maybeAccount -> maybeAccount.orElseThrow(Status.UNAUTHENTICATED::asRuntimeException))
|
||||
.map(account -> {
|
||||
final IdentityKey identityKey = switch (IdentityType.fromGrpcIdentityType(identityType)) {
|
||||
case ACI -> account.getIdentityKey();
|
||||
case PNI -> account.getPhoneNumberIdentityKey();
|
||||
};
|
||||
|
||||
final IdentityKey identityKey = account.getIdentityKey(IdentityTypeUtil.fromGrpcIdentityType(identityType));
|
||||
final K key = extractKeyFunction.apply(storeKeyRequest, identityKey);
|
||||
|
||||
return Tuples.of(account, key);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.grpc;
|
||||
|
||||
import io.grpc.Status;
|
||||
import java.util.UUID;
|
||||
import org.whispersystems.textsecuregcm.identity.AciServiceIdentifier;
|
||||
import org.whispersystems.textsecuregcm.identity.PniServiceIdentifier;
|
||||
import org.whispersystems.textsecuregcm.identity.ServiceIdentifier;
|
||||
import org.whispersystems.textsecuregcm.util.UUIDUtil;
|
||||
|
||||
public class ServiceIdentifierUtil {
|
||||
|
||||
private ServiceIdentifierUtil() {
|
||||
}
|
||||
|
||||
public static ServiceIdentifier fromGrpcServiceIdentifier(final org.signal.chat.common.ServiceIdentifier serviceIdentifier) {
|
||||
final UUID uuid;
|
||||
|
||||
try {
|
||||
uuid = UUIDUtil.fromByteString(serviceIdentifier.getUuid());
|
||||
} catch (final IllegalArgumentException e) {
|
||||
throw Status.INVALID_ARGUMENT.asRuntimeException();
|
||||
}
|
||||
|
||||
return switch (IdentityTypeUtil.fromGrpcIdentityType(serviceIdentifier.getIdentityType())) {
|
||||
case ACI -> new AciServiceIdentifier(uuid);
|
||||
case PNI -> new PniServiceIdentifier(uuid);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.textsecuregcm.auth.SaltedTokenHash;
|
||||
import org.whispersystems.textsecuregcm.auth.StoredRegistrationLock;
|
||||
import org.whispersystems.textsecuregcm.entities.AccountAttributes;
|
||||
import org.whispersystems.textsecuregcm.identity.IdentityType;
|
||||
import org.whispersystems.textsecuregcm.identity.ServiceIdentifier;
|
||||
import org.whispersystems.textsecuregcm.storage.Device.DeviceCapabilities;
|
||||
import org.whispersystems.textsecuregcm.util.ByteArrayBase64UrlAdapter;
|
||||
@@ -105,6 +106,12 @@ public class Account {
|
||||
@JsonIgnore
|
||||
private boolean stale;
|
||||
|
||||
public UUID getIdentifier(final IdentityType identityType) {
|
||||
return switch (identityType) {
|
||||
case ACI -> getUuid();
|
||||
case PNI -> getPhoneNumberIdentifier();
|
||||
};
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
// this is the one method that may be called on a stale account
|
||||
@@ -325,12 +332,29 @@ public class Account {
|
||||
this.identityKey = identityKey;
|
||||
}
|
||||
|
||||
public IdentityKey getIdentityKey(final IdentityType identityType) {
|
||||
requireNotStale();
|
||||
|
||||
return switch (identityType) {
|
||||
case ACI -> identityKey;
|
||||
case PNI -> phoneNumberIdentityKey;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Please use {@link #getIdentityKey(IdentityType)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public IdentityKey getIdentityKey() {
|
||||
requireNotStale();
|
||||
|
||||
return identityKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Please use {@link #getIdentityKey(IdentityType)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public IdentityKey getPhoneNumberIdentityKey() {
|
||||
return phoneNumberIdentityKey;
|
||||
}
|
||||
|
||||
@@ -811,6 +811,13 @@ public class AccountsManager {
|
||||
};
|
||||
}
|
||||
|
||||
public CompletableFuture<Optional<Account>> getByServiceIdentifierAsync(final ServiceIdentifier serviceIdentifier) {
|
||||
return switch (serviceIdentifier.identityType()) {
|
||||
case ACI -> getByAccountIdentifierAsync(serviceIdentifier.uuid());
|
||||
case PNI -> getByPhoneNumberIdentifierAsync(serviceIdentifier.uuid());
|
||||
};
|
||||
}
|
||||
|
||||
public Optional<Account> getByAccountIdentifier(final UUID uuid) {
|
||||
return checkRedisThenAccounts(
|
||||
getByUuidTimer,
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.util.stream.LongStream;
|
||||
import javax.annotation.Nullable;
|
||||
import org.whispersystems.textsecuregcm.auth.SaltedTokenHash;
|
||||
import org.whispersystems.textsecuregcm.entities.ECSignedPreKey;
|
||||
import org.whispersystems.textsecuregcm.identity.IdentityType;
|
||||
import org.whispersystems.textsecuregcm.util.Util;
|
||||
|
||||
public class Device {
|
||||
@@ -230,6 +231,17 @@ public class Device {
|
||||
this.phoneNumberIdentityRegistrationId = phoneNumberIdentityRegistrationId;
|
||||
}
|
||||
|
||||
public ECSignedPreKey getSignedPreKey(final IdentityType identityType) {
|
||||
return switch (identityType) {
|
||||
case ACI -> signedPreKey;
|
||||
case PNI -> phoneNumberIdentitySignedPreKey;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Please use {@link #getSignedPreKey(IdentityType)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public ECSignedPreKey getSignedPreKey() {
|
||||
return signedPreKey;
|
||||
}
|
||||
@@ -238,6 +250,10 @@ public class Device {
|
||||
this.signedPreKey = signedPreKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Please use {@link #getSignedPreKey(IdentityType)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public ECSignedPreKey getPhoneNumberIdentitySignedPreKey() {
|
||||
return phoneNumberIdentitySignedPreKey;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user