From 708f23a2ee0a40c6c8816281ac1cd94badbccbfc Mon Sep 17 00:00:00 2001 From: Chris Eager Date: Wed, 23 Aug 2023 11:37:42 -0500 Subject: [PATCH] Remove deprecated identity key and signed pre-key methods --- .../auth/CertificateGenerator.java | 11 +-- .../controllers/CertificateController.java | 3 +- .../controllers/DeviceController.java | 6 +- .../controllers/KeysController.java | 17 ++-- .../controllers/ProfileController.java | 5 +- .../textsecuregcm/storage/Account.java | 18 ---- .../storage/AccountsManager.java | 9 +- .../textsecuregcm/storage/Device.java | 16 ---- .../MigrateSignedECPreKeysCommand.java | 10 ++- .../auth/CertificateGeneratorTest.java | 3 +- .../controllers/AccountControllerV2Test.java | 19 +++-- .../controllers/DeviceControllerTest.java | 83 ++++++++++++------- .../controllers/KeysControllerTest.java | 70 +++++++++------- .../controllers/ProfileControllerTest.java | 4 - ...ntsManagerChangeNumberIntegrationTest.java | 5 +- ...ConcurrentModificationIntegrationTest.java | 3 +- .../storage/AccountsManagerTest.java | 31 ++++--- .../textsecuregcm/storage/AccountsTest.java | 6 +- .../tests/util/AccountsHelper.java | 4 +- .../textsecuregcm/tests/util/AuthHelper.java | 3 +- 20 files changed, 168 insertions(+), 158 deletions(-) diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/auth/CertificateGenerator.java b/service/src/main/java/org/whispersystems/textsecuregcm/auth/CertificateGenerator.java index 066ca5839..93a568ae6 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/auth/CertificateGenerator.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/auth/CertificateGenerator.java @@ -13,6 +13,7 @@ import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECPrivateKey; import org.whispersystems.textsecuregcm.entities.MessageProtos.SenderCertificate; import org.whispersystems.textsecuregcm.entities.MessageProtos.ServerCertificate; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.Device; @@ -32,11 +33,11 @@ public class CertificateGenerator { public byte[] createFor(Account account, Device device, boolean includeE164) throws InvalidKeyException { SenderCertificate.Certificate.Builder builder = SenderCertificate.Certificate.newBuilder() - .setSenderDevice(Math.toIntExact(device.getId())) - .setExpires(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(expiresDays)) - .setIdentityKey(ByteString.copyFrom(account.getIdentityKey().serialize())) - .setSigner(serverCertificate) - .setSenderUuid(account.getUuid().toString()); + .setSenderDevice(Math.toIntExact(device.getId())) + .setExpires(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(expiresDays)) + .setIdentityKey(ByteString.copyFrom(account.getIdentityKey(IdentityType.ACI).serialize())) + .setSigner(serverCertificate) + .setSenderUuid(account.getUuid().toString()); if (includeE164) { builder.setSender(account.getNumber()); diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/CertificateController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/CertificateController.java index bd849abb8..d4568216f 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/CertificateController.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/CertificateController.java @@ -38,6 +38,7 @@ import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.CertificateGenerator; import org.whispersystems.textsecuregcm.entities.DeliveryCertificate; import org.whispersystems.textsecuregcm.entities.GroupCredentials; +import org.whispersystems.textsecuregcm.identity.IdentityType; @SuppressWarnings("OptionalUsedAsFieldOrParameterType") @Path("/v1/certificate") @@ -72,7 +73,7 @@ public class CertificateController { @QueryParam("includeE164") @DefaultValue("true") boolean includeE164) throws InvalidKeyException { - if (auth.getAccount().getIdentityKey() == null) { + if (auth.getAccount().getIdentityKey(IdentityType.ACI) == null) { throw new WebApplicationException(Response.Status.BAD_REQUEST); } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/DeviceController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/DeviceController.java index c8df221ce..7c9c8575b 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/DeviceController.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/DeviceController.java @@ -57,6 +57,7 @@ import org.whispersystems.textsecuregcm.entities.DeviceInfoList; import org.whispersystems.textsecuregcm.entities.DeviceResponse; import org.whispersystems.textsecuregcm.entities.LinkDeviceRequest; import org.whispersystems.textsecuregcm.entities.PreKeySignatureValidator; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.limits.RateLimiters; import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster; import org.whispersystems.textsecuregcm.storage.Account; @@ -359,9 +360,10 @@ public class DeviceController { assert deviceActivationRequest.aciPqLastResortPreKey().isPresent(); assert deviceActivationRequest.pniPqLastResortPreKey().isPresent(); - final boolean allKeysValid = PreKeySignatureValidator.validatePreKeySignatures(account.getIdentityKey(), + final boolean allKeysValid = PreKeySignatureValidator.validatePreKeySignatures(account.getIdentityKey( + IdentityType.ACI), List.of(deviceActivationRequest.aciSignedPreKey().get(), deviceActivationRequest.aciPqLastResortPreKey().get())) - && PreKeySignatureValidator.validatePreKeySignatures(account.getPhoneNumberIdentityKey(), + && PreKeySignatureValidator.validatePreKeySignatures(account.getIdentityKey(IdentityType.PNI), List.of(deviceActivationRequest.pniSignedPreKey().get(), deviceActivationRequest.pniPqLastResortPreKey().get())); if (!allKeysValid) { diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/KeysController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/KeysController.java index 6206fd059..63fcc49b8 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/KeysController.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/KeysController.java @@ -56,6 +56,7 @@ import org.whispersystems.textsecuregcm.entities.PreKeyResponse; import org.whispersystems.textsecuregcm.entities.PreKeyResponseItem; import org.whispersystems.textsecuregcm.entities.PreKeyState; import org.whispersystems.textsecuregcm.experiment.Experiment; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.identity.ServiceIdentifier; import org.whispersystems.textsecuregcm.limits.RateLimiters; import org.whispersystems.textsecuregcm.metrics.UserAgentTagUtil; @@ -137,11 +138,13 @@ public class KeysController { final boolean usePhoneNumberIdentity = usePhoneNumberIdentity(identityType); if (preKeys.getSignedPreKey() != null && - !preKeys.getSignedPreKey().equals(usePhoneNumberIdentity ? device.getPhoneNumberIdentitySignedPreKey() : device.getSignedPreKey())) { + !preKeys.getSignedPreKey().equals(usePhoneNumberIdentity ? device.getSignedPreKey(IdentityType.PNI) + : device.getSignedPreKey(IdentityType.ACI))) { updateAccount = true; } - final IdentityKey oldIdentityKey = usePhoneNumberIdentity ? account.getPhoneNumberIdentityKey() : account.getIdentityKey(); + final IdentityKey oldIdentityKey = + usePhoneNumberIdentity ? account.getIdentityKey(IdentityType.PNI) : account.getIdentityKey(IdentityType.ACI); if (!Objects.equals(preKeys.getIdentityKey(), oldIdentityKey)) { updateAccount = true; @@ -242,10 +245,7 @@ public class KeysController { List responseItems = new ArrayList<>(devices.size()); for (Device device : devices) { - ECSignedPreKey signedECPreKey = switch (targetIdentifier.identityType()) { - case ACI -> device.getSignedPreKey(); - case PNI -> device.getPhoneNumberIdentitySignedPreKey(); - }; + ECSignedPreKey signedECPreKey = device.getSignedPreKey(targetIdentifier.identityType()); ECPreKey unsignedECPreKey = keys.takeEC(targetIdentifier.uuid(), device.getId()).join().orElse(null); KEMSignedPreKey pqPreKey = returnPqKey ? keys.takePQ(targetIdentifier.uuid(), device.getId()).join().orElse(null) : null; @@ -263,10 +263,7 @@ public class KeysController { } } - final IdentityKey identityKey = switch (targetIdentifier.identityType()) { - case ACI -> target.getIdentityKey(); - case PNI -> target.getPhoneNumberIdentityKey(); - }; + final IdentityKey identityKey = target.getIdentityKey(targetIdentifier.identityType()); if (responseItems.isEmpty()) { throw new WebApplicationException(Response.Status.NOT_FOUND); diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/ProfileController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/ProfileController.java index b2b1f8e29..481e2969b 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/ProfileController.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/ProfileController.java @@ -87,6 +87,7 @@ import org.whispersystems.textsecuregcm.entities.UserCapabilities; import org.whispersystems.textsecuregcm.entities.VersionedProfileResponse; import org.whispersystems.textsecuregcm.grpc.ProfileHelper; import org.whispersystems.textsecuregcm.identity.AciServiceIdentifier; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.identity.PniServiceIdentifier; import org.whispersystems.textsecuregcm.identity.ServiceIdentifier; import org.whispersystems.textsecuregcm.limits.RateLimiters; @@ -430,7 +431,7 @@ public class ProfileController { final boolean isSelf, final ContainerRequestContext containerRequestContext) { - return new BaseProfileResponse(account.getIdentityKey(), + return new BaseProfileResponse(account.getIdentityKey(IdentityType.ACI), UnidentifiedAccessChecksum.generateFor(account.getUnidentifiedAccessKey()), account.isUnrestrictedUnidentifiedAccess(), UserCapabilities.createForAccount(account), @@ -442,7 +443,7 @@ public class ProfileController { } private BaseProfileResponse buildBaseProfileResponseForPhoneNumberIdentity(final Account account) { - return new BaseProfileResponse(account.getPhoneNumberIdentityKey(), + return new BaseProfileResponse(account.getIdentityKey(IdentityType.PNI), null, false, UserCapabilities.createForAccount(account), diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java index e3eccd575..38d8f9ddf 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java @@ -317,24 +317,6 @@ public class Account { }; } - /** - * @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; - } - public void setPhoneNumberIdentityKey(final IdentityKey phoneNumberIdentityKey) { this.phoneNumberIdentityKey = phoneNumberIdentityKey; } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java b/service/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java index f8496b4ba..2943d8d0e 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/storage/AccountsManager.java @@ -52,6 +52,7 @@ import org.whispersystems.textsecuregcm.entities.AccountAttributes; import org.whispersystems.textsecuregcm.entities.ECSignedPreKey; import org.whispersystems.textsecuregcm.entities.KEMSignedPreKey; import org.whispersystems.textsecuregcm.experiment.ExperimentEnrollmentManager; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.identity.ServiceIdentifier; import org.whispersystems.textsecuregcm.push.ClientPresenceManager; import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster; @@ -397,8 +398,8 @@ public class AccountsManager { throw new IllegalArgumentException("PNI identity key, signed pre-keys, and registration IDs must be all null or all non-null"); } - boolean changed = !Objects.equals(pniIdentityKey, account.getPhoneNumberIdentityKey()); - + boolean changed = !Objects.equals(pniIdentityKey, account.getIdentityKey(IdentityType.PNI)); + for (Device device : account.getDevices()) { if (!device.isEnabled()) { continue; @@ -406,11 +407,11 @@ public class AccountsManager { ECSignedPreKey signedPreKey = pniSignedPreKeys.get(device.getId()); int registrationId = pniRegistrationIds.get(device.getId()); changed = changed || - !signedPreKey.equals(device.getPhoneNumberIdentitySignedPreKey()) || + !signedPreKey.equals(device.getSignedPreKey(IdentityType.PNI)) || device.getRegistrationId() != registrationId; device.setPhoneNumberIdentitySignedPreKey(signedPreKey); device.setPhoneNumberIdentityRegistrationId(registrationId); - } + } account.setPhoneNumberIdentityKey(pniIdentityKey); diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Device.java b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Device.java index 64f986409..dbad027c9 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Device.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Device.java @@ -238,26 +238,10 @@ public class Device { }; } - /** - * @deprecated Please use {@link #getSignedPreKey(IdentityType)} instead. - */ - @Deprecated - public ECSignedPreKey getSignedPreKey() { - return signedPreKey; - } - public void setSignedPreKey(ECSignedPreKey signedPreKey) { this.signedPreKey = signedPreKey; } - /** - * @deprecated Please use {@link #getSignedPreKey(IdentityType)} instead. - */ - @Deprecated - public ECSignedPreKey getPhoneNumberIdentitySignedPreKey() { - return phoneNumberIdentitySignedPreKey; - } - public void setPhoneNumberIdentitySignedPreKey(final ECSignedPreKey phoneNumberIdentitySignedPreKey) { this.phoneNumberIdentitySignedPreKey = phoneNumberIdentitySignedPreKey; } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/MigrateSignedECPreKeysCommand.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/MigrateSignedECPreKeysCommand.java index a5a4d18c2..770e23b05 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/MigrateSignedECPreKeysCommand.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/MigrateSignedECPreKeysCommand.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; import org.whispersystems.textsecuregcm.entities.ECSignedPreKey; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.metrics.MetricsUtil; import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.KeysManager; @@ -42,12 +43,13 @@ public class MigrateSignedECPreKeysCommand extends AbstractSinglePassCrawlAccoun .flatMap(device -> { final List> keys = new ArrayList<>(2); - if (device.getSignedPreKey() != null) { - keys.add(Tuples.of(account.getUuid(), device.getId(), device.getSignedPreKey())); + if (device.getSignedPreKey(IdentityType.ACI) != null) { + keys.add(Tuples.of(account.getUuid(), device.getId(), device.getSignedPreKey(IdentityType.ACI))); } - if (device.getPhoneNumberIdentitySignedPreKey() != null) { - keys.add(Tuples.of(account.getPhoneNumberIdentifier(), device.getId(), device.getPhoneNumberIdentitySignedPreKey())); + if (device.getSignedPreKey(IdentityType.PNI) != null) { + keys.add(Tuples.of(account.getPhoneNumberIdentifier(), device.getId(), + device.getSignedPreKey(IdentityType.PNI))); } return Flux.fromIterable(keys); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/auth/CertificateGeneratorTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/auth/CertificateGeneratorTest.java index 959412e3e..3e40c715a 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/auth/CertificateGeneratorTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/auth/CertificateGeneratorTest.java @@ -17,6 +17,7 @@ import org.junit.jupiter.api.Test; import org.signal.libsignal.protocol.IdentityKey; import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECPublicKey; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.Device; @@ -32,7 +33,7 @@ class CertificateGeneratorTest { final Device device = mock(Device.class); final CertificateGenerator certificateGenerator = new CertificateGenerator(Base64.getDecoder().decode(SIGNING_CERTIFICATE), Curve.decodePrivatePoint(Base64.getDecoder().decode(SIGNING_KEY)), 1); - when(account.getIdentityKey()).thenReturn(IDENTITY_KEY); + when(account.getIdentityKey(IdentityType.ACI)).thenReturn(IDENTITY_KEY); when(account.getUuid()).thenReturn(UUID.randomUUID()); when(account.getNumber()).thenReturn("+18005551234"); when(device.getId()).thenReturn(4L); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerV2Test.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerV2Test.java index 5ad94b169..e6ff0d951 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerV2Test.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerV2Test.java @@ -75,6 +75,7 @@ import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse; import org.whispersystems.textsecuregcm.entities.ChangeNumberRequest; import org.whispersystems.textsecuregcm.entities.PhoneNumberDiscoverabilityRequest; import org.whispersystems.textsecuregcm.entities.RegistrationServiceSession; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.limits.RateLimiter; import org.whispersystems.textsecuregcm.limits.RateLimiters; import org.whispersystems.textsecuregcm.mappers.ImpossiblePhoneNumberExceptionMapper; @@ -151,7 +152,7 @@ class AccountControllerV2Test { final Account updatedAccount = mock(Account.class); when(updatedAccount.getUuid()).thenReturn(uuid); when(updatedAccount.getNumber()).thenReturn(number); - when(updatedAccount.getPhoneNumberIdentityKey()).thenReturn(pniIdentityKey); + when(updatedAccount.getIdentityKey(IdentityType.PNI)).thenReturn(pniIdentityKey); if (number.equals(account.getNumber())) { when(updatedAccount.getPhoneNumberIdentifier()).thenReturn(AuthHelper.VALID_PNI); } else { @@ -205,7 +206,7 @@ class AccountControllerV2Test { .header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) .put(Entity.entity( - new ChangeNumberRequest(encodeSessionId("session"), null, AuthHelper.VALID_NUMBER, null, + new ChangeNumberRequest(encodeSessionId("session"), null, AuthHelper.VALID_NUMBER, null, new IdentityKey(Curve.generateKeyPair().getPublicKey()), Collections.emptyList(), Collections.emptyMap(), null, Collections.emptyMap()), @@ -476,7 +477,7 @@ class AccountControllerV2Test { final Account updatedAccount = mock(Account.class); when(updatedAccount.getUuid()).thenReturn(uuid); when(updatedAccount.getNumber()).thenReturn(number); - when(updatedAccount.getPhoneNumberIdentityKey()).thenReturn(pniIdentityKey); + when(updatedAccount.getIdentityKey(IdentityType.PNI)).thenReturn(pniIdentityKey); when(updatedAccount.getPhoneNumberIdentifier()).thenReturn(pni); when(updatedAccount.getDevices()).thenReturn(devices); @@ -487,12 +488,12 @@ class AccountControllerV2Test { return updatedAccount; }); - } + } @Test void pniKeyDistributionSuccess() throws Exception { when(AuthHelper.VALID_ACCOUNT.isPniSupported()).thenReturn(true); - + final AccountIdentityResponse accountIdentityResponse = resources.getJerseyTest() .target("/v2/accounts/phone_number_identity_key_distribution") @@ -506,8 +507,8 @@ class AccountControllerV2Test { assertEquals(AuthHelper.VALID_UUID, accountIdentityResponse.uuid()); assertEquals(AuthHelper.VALID_NUMBER, accountIdentityResponse.number()); assertEquals(AuthHelper.VALID_PNI, accountIdentityResponse.pni()); - } - + } + @Test void unprocessableRequestJson() { final Invocation.Builder request = resources.getJerseyTest() @@ -552,7 +553,7 @@ class AccountControllerV2Test { assertEquals(422, response.getStatus()); } } - + /** * Valid request JSON for a {@link org.whispersystems.textsecuregcm.entities.PhoneNumberIdentityKeyDistributionRequest} */ @@ -596,7 +597,7 @@ class AccountControllerV2Test { } } - + @Nested class PhoneNumberDiscoverability { diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/DeviceControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/DeviceControllerTest.java index d9e859b8e..22981fa2d 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/DeviceControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/DeviceControllerTest.java @@ -4,12 +4,40 @@ */ package org.whispersystems.textsecuregcm.controllers; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + import com.google.common.collect.ImmutableSet; import com.google.common.net.HttpHeaders; import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import io.lettuce.core.cluster.api.sync.RedisAdvancedClusterCommands; +import java.nio.charset.StandardCharsets; +import java.security.SecureRandom; +import java.time.Instant; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Stream; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -26,12 +54,22 @@ import org.signal.libsignal.protocol.ecc.ECKeyPair; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.WebsocketRefreshApplicationEventListener; -import org.whispersystems.textsecuregcm.entities.*; +import org.whispersystems.textsecuregcm.entities.AccountAttributes; +import org.whispersystems.textsecuregcm.entities.ApnRegistrationId; +import org.whispersystems.textsecuregcm.entities.DeviceActivationRequest; +import org.whispersystems.textsecuregcm.entities.DeviceResponse; +import org.whispersystems.textsecuregcm.entities.ECSignedPreKey; +import org.whispersystems.textsecuregcm.entities.GcmRegistrationId; +import org.whispersystems.textsecuregcm.entities.KEMSignedPreKey; +import org.whispersystems.textsecuregcm.entities.LinkDeviceRequest; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.limits.RateLimiter; import org.whispersystems.textsecuregcm.limits.RateLimiters; import org.whispersystems.textsecuregcm.mappers.DeviceLimitExceededExceptionMapper; import org.whispersystems.textsecuregcm.push.ClientPresenceManager; -import org.whispersystems.textsecuregcm.storage.*; +import org.whispersystems.textsecuregcm.storage.Account; +import org.whispersystems.textsecuregcm.storage.AccountsManager; +import org.whispersystems.textsecuregcm.storage.Device; import org.whispersystems.textsecuregcm.storage.Device.DeviceCapabilities; import org.whispersystems.textsecuregcm.storage.KeysManager; import org.whispersystems.textsecuregcm.storage.MessagesManager; @@ -42,23 +80,6 @@ import org.whispersystems.textsecuregcm.tests.util.RedisClusterHelper; import org.whispersystems.textsecuregcm.util.TestClock; import org.whispersystems.textsecuregcm.util.VerificationCode; -import javax.ws.rs.client.Entity; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.nio.charset.StandardCharsets; -import java.security.SecureRandom; -import java.time.Instant; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.*; - @ExtendWith(DropwizardExtensionsSupport.class) class DeviceControllerTest { @@ -272,8 +293,8 @@ class DeviceControllerTest { aciPqLastResortPreKey = Optional.of(KeysHelper.signedKEMPreKey(3, aciIdentityKeyPair)); pniPqLastResortPreKey = Optional.of(KeysHelper.signedKEMPreKey(4, pniIdentityKeyPair)); - when(account.getIdentityKey()).thenReturn(new IdentityKey(aciIdentityKeyPair.getPublicKey())); - when(account.getPhoneNumberIdentityKey()).thenReturn(new IdentityKey(pniIdentityKeyPair.getPublicKey())); + when(account.getIdentityKey(IdentityType.ACI)).thenReturn(new IdentityKey(aciIdentityKeyPair.getPublicKey())); + when(account.getIdentityKey(IdentityType.PNI)).thenReturn(new IdentityKey(pniIdentityKeyPair.getPublicKey())); when(keysManager.storeEcSignedPreKeys(any(), any())).thenReturn(CompletableFuture.completedFuture(null)); when(keysManager.storePqLastResort(any(), any())).thenReturn(CompletableFuture.completedFuture(null)); @@ -295,8 +316,8 @@ class DeviceControllerTest { final Device device = deviceCaptor.getValue(); - assertEquals(aciSignedPreKey.get(), device.getSignedPreKey()); - assertEquals(pniSignedPreKey.get(), device.getPhoneNumberIdentitySignedPreKey()); + assertEquals(aciSignedPreKey.get(), device.getSignedPreKey(IdentityType.ACI)); + assertEquals(pniSignedPreKey.get(), device.getSignedPreKey(IdentityType.PNI)); assertEquals(fetchesMessages, device.getFetchesMessages()); expectedApnsToken.ifPresentOrElse(expectedToken -> assertEquals(expectedToken, device.getApnId()), @@ -352,8 +373,8 @@ class DeviceControllerTest { aciPqLastResortPreKey = Optional.of(KeysHelper.signedKEMPreKey(3, aciIdentityKeyPair)); pniPqLastResortPreKey = Optional.of(KeysHelper.signedKEMPreKey(4, pniIdentityKeyPair)); - when(account.getIdentityKey()).thenReturn(new IdentityKey(aciIdentityKeyPair.getPublicKey())); - when(account.getPhoneNumberIdentityKey()).thenReturn(new IdentityKey(pniIdentityKeyPair.getPublicKey())); + when(account.getIdentityKey(IdentityType.ACI)).thenReturn(new IdentityKey(aciIdentityKeyPair.getPublicKey())); + when(account.getIdentityKey(IdentityType.PNI)).thenReturn(new IdentityKey(pniIdentityKeyPair.getPublicKey())); when(keysManager.storeEcSignedPreKeys(any(), any())).thenReturn(CompletableFuture.completedFuture(null)); when(keysManager.storePqLastResort(any(), any())).thenReturn(CompletableFuture.completedFuture(null)); @@ -405,8 +426,8 @@ class DeviceControllerTest { aciPqLastResortPreKey = Optional.of(KeysHelper.signedKEMPreKey(3, aciIdentityKeyPair)); pniPqLastResortPreKey = Optional.of(KeysHelper.signedKEMPreKey(4, pniIdentityKeyPair)); - when(account.getIdentityKey()).thenReturn(new IdentityKey(aciIdentityKeyPair.getPublicKey())); - when(account.getPhoneNumberIdentityKey()).thenReturn(new IdentityKey(pniIdentityKeyPair.getPublicKey())); + when(account.getIdentityKey(IdentityType.ACI)).thenReturn(new IdentityKey(aciIdentityKeyPair.getPublicKey())); + when(account.getIdentityKey(IdentityType.PNI)).thenReturn(new IdentityKey(pniIdentityKeyPair.getPublicKey())); final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(), new AccountAttributes(fetchesMessages, 1234, null, null, true, null), @@ -453,8 +474,8 @@ class DeviceControllerTest { .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) .get(VerificationCode.class); - when(account.getIdentityKey()).thenReturn(aciIdentityKey); - when(account.getPhoneNumberIdentityKey()).thenReturn(pniIdentityKey); + when(account.getIdentityKey(IdentityType.ACI)).thenReturn(aciIdentityKey); + when(account.getIdentityKey(IdentityType.PNI)).thenReturn(pniIdentityKey); final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(), new AccountAttributes(true, 1234, null, null, true, null), @@ -511,8 +532,8 @@ class DeviceControllerTest { .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) .get(VerificationCode.class); - when(account.getIdentityKey()).thenReturn(aciIdentityKey); - when(account.getPhoneNumberIdentityKey()).thenReturn(pniIdentityKey); + when(account.getIdentityKey(IdentityType.ACI)).thenReturn(aciIdentityKey); + when(account.getIdentityKey(IdentityType.PNI)).thenReturn(pniIdentityKey); final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(), new AccountAttributes(true, 1234, null, null, true, null), diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/KeysControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/KeysControllerTest.java index 5f36dde94..c230c8243 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/KeysControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/KeysControllerTest.java @@ -58,6 +58,7 @@ import org.whispersystems.textsecuregcm.entities.PreKeyResponse; import org.whispersystems.textsecuregcm.entities.PreKeyState; import org.whispersystems.textsecuregcm.entities.SignedPreKey; import org.whispersystems.textsecuregcm.identity.AciServiceIdentifier; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.identity.PniServiceIdentifier; import org.whispersystems.textsecuregcm.limits.RateLimiter; import org.whispersystems.textsecuregcm.limits.RateLimiters; @@ -89,10 +90,10 @@ class KeysControllerTest { private final ECKeyPair IDENTITY_KEY_PAIR = Curve.generateKeyPair(); private final IdentityKey IDENTITY_KEY = new IdentityKey(IDENTITY_KEY_PAIR.getPublicKey()); - + private final ECKeyPair PNI_IDENTITY_KEY_PAIR = Curve.generateKeyPair(); private final IdentityKey PNI_IDENTITY_KEY = new IdentityKey(PNI_IDENTITY_KEY_PAIR.getPublicKey()); - + private final ECPreKey SAMPLE_KEY = KeysHelper.ecPreKey(1234); private final ECPreKey SAMPLE_KEY2 = KeysHelper.ecPreKey(5667); private final ECPreKey SAMPLE_KEY3 = KeysHelper.ecPreKey(334); @@ -186,14 +187,14 @@ class KeysControllerTest { when(sampleDevice2.isEnabled()).thenReturn(true); when(sampleDevice3.isEnabled()).thenReturn(false); when(sampleDevice4.isEnabled()).thenReturn(true); - when(sampleDevice.getSignedPreKey()).thenReturn(SAMPLE_SIGNED_KEY); - when(sampleDevice2.getSignedPreKey()).thenReturn(SAMPLE_SIGNED_KEY2); - when(sampleDevice3.getSignedPreKey()).thenReturn(SAMPLE_SIGNED_KEY3); - when(sampleDevice4.getSignedPreKey()).thenReturn(null); - when(sampleDevice.getPhoneNumberIdentitySignedPreKey()).thenReturn(SAMPLE_SIGNED_PNI_KEY); - when(sampleDevice2.getPhoneNumberIdentitySignedPreKey()).thenReturn(SAMPLE_SIGNED_PNI_KEY2); - when(sampleDevice3.getPhoneNumberIdentitySignedPreKey()).thenReturn(SAMPLE_SIGNED_PNI_KEY3); - when(sampleDevice4.getPhoneNumberIdentitySignedPreKey()).thenReturn(null); + when(sampleDevice.getSignedPreKey(IdentityType.ACI)).thenReturn(SAMPLE_SIGNED_KEY); + when(sampleDevice2.getSignedPreKey(IdentityType.ACI)).thenReturn(SAMPLE_SIGNED_KEY2); + when(sampleDevice3.getSignedPreKey(IdentityType.ACI)).thenReturn(SAMPLE_SIGNED_KEY3); + when(sampleDevice4.getSignedPreKey(IdentityType.ACI)).thenReturn(null); + when(sampleDevice.getSignedPreKey(IdentityType.PNI)).thenReturn(SAMPLE_SIGNED_PNI_KEY); + when(sampleDevice2.getSignedPreKey(IdentityType.PNI)).thenReturn(SAMPLE_SIGNED_PNI_KEY2); + when(sampleDevice3.getSignedPreKey(IdentityType.PNI)).thenReturn(SAMPLE_SIGNED_PNI_KEY3); + when(sampleDevice4.getSignedPreKey(IdentityType.PNI)).thenReturn(null); when(sampleDevice.getId()).thenReturn(1L); when(sampleDevice2.getId()).thenReturn(2L); when(sampleDevice3.getId()).thenReturn(3L); @@ -208,8 +209,8 @@ class KeysControllerTest { when(existsAccount.getDevice(22L)).thenReturn(Optional.empty()); when(existsAccount.getDevices()).thenReturn(allDevices); when(existsAccount.isEnabled()).thenReturn(true); - when(existsAccount.getIdentityKey()).thenReturn(IDENTITY_KEY); - when(existsAccount.getPhoneNumberIdentityKey()).thenReturn(PNI_IDENTITY_KEY); + when(existsAccount.getIdentityKey(IdentityType.ACI)).thenReturn(IDENTITY_KEY); + when(existsAccount.getIdentityKey(IdentityType.PNI)).thenReturn(PNI_IDENTITY_KEY); when(existsAccount.getNumber()).thenReturn(EXISTS_NUMBER); when(existsAccount.getUnidentifiedAccessKey()).thenReturn(Optional.of("1337".getBytes())); @@ -232,9 +233,9 @@ class KeysControllerTest { when(KEYS.getEcCount(AuthHelper.VALID_UUID, 1)).thenReturn(CompletableFuture.completedFuture(5)); when(KEYS.getPqCount(AuthHelper.VALID_UUID, 1)).thenReturn(CompletableFuture.completedFuture(5)); - when(AuthHelper.VALID_DEVICE.getSignedPreKey()).thenReturn(VALID_DEVICE_SIGNED_KEY); - when(AuthHelper.VALID_DEVICE.getPhoneNumberIdentitySignedPreKey()).thenReturn(VALID_DEVICE_PNI_SIGNED_KEY); - when(AuthHelper.VALID_ACCOUNT.getIdentityKey()).thenReturn(null); + when(AuthHelper.VALID_DEVICE.getSignedPreKey(IdentityType.ACI)).thenReturn(VALID_DEVICE_SIGNED_KEY); + when(AuthHelper.VALID_DEVICE.getSignedPreKey(IdentityType.PNI)).thenReturn(VALID_DEVICE_PNI_SIGNED_KEY); + when(AuthHelper.VALID_ACCOUNT.getIdentityKey(IdentityType.ACI)).thenReturn(null); } @AfterEach @@ -322,12 +323,13 @@ class KeysControllerTest { .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) .get(PreKeyResponse.class); - assertThat(result.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey()); + assertThat(result.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey(IdentityType.ACI)); assertThat(result.getDevicesCount()).isEqualTo(1); assertEquals(SAMPLE_KEY, result.getDevice(1).getPreKey()); assertThat(result.getDevice(1).getPqPreKey()).isNull(); assertThat(result.getDevice(1).getRegistrationId()).isEqualTo(SAMPLE_REGISTRATION_ID); - assertEquals(existsAccount.getDevice(1).get().getSignedPreKey(), result.getDevice(1).getSignedPreKey()); + assertEquals(existsAccount.getDevice(1).get().getSignedPreKey(IdentityType.ACI), + result.getDevice(1).getSignedPreKey()); verify(KEYS).takeEC(EXISTS_UUID, 1); verify(KEYS).getEcSignedPreKey(EXISTS_UUID, 1); @@ -345,12 +347,13 @@ class KeysControllerTest { .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) .get(PreKeyResponse.class); - assertThat(result.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey()); + assertThat(result.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey(IdentityType.ACI)); assertThat(result.getDevicesCount()).isEqualTo(1); assertEquals(SAMPLE_KEY, result.getDevice(1).getPreKey()); assertThat(result.getDevice(1).getPqPreKey()).isNull(); assertThat(result.getDevice(1).getRegistrationId()).isEqualTo(SAMPLE_REGISTRATION_ID); - assertEquals(existsAccount.getDevice(1).get().getSignedPreKey(), result.getDevice(1).getSignedPreKey()); + assertEquals(existsAccount.getDevice(1).get().getSignedPreKey(IdentityType.ACI), + result.getDevice(1).getSignedPreKey()); verify(KEYS).takeEC(EXISTS_UUID, 1); verify(KEYS).takePQ(EXISTS_UUID, 1); @@ -367,12 +370,13 @@ class KeysControllerTest { .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) .get(PreKeyResponse.class); - assertThat(result.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey()); + assertThat(result.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey(IdentityType.ACI)); assertThat(result.getDevicesCount()).isEqualTo(1); assertEquals(SAMPLE_KEY, result.getDevice(1).getPreKey()); assertEquals(SAMPLE_PQ_KEY, result.getDevice(1).getPqPreKey()); assertThat(result.getDevice(1).getRegistrationId()).isEqualTo(SAMPLE_REGISTRATION_ID); - assertEquals(existsAccount.getDevice(1).get().getSignedPreKey(), result.getDevice(1).getSignedPreKey()); + assertEquals(existsAccount.getDevice(1).get().getSignedPreKey(IdentityType.ACI), + result.getDevice(1).getSignedPreKey()); verify(KEYS).takeEC(EXISTS_UUID, 1); verify(KEYS).takePQ(EXISTS_UUID, 1); @@ -388,12 +392,13 @@ class KeysControllerTest { .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) .get(PreKeyResponse.class); - assertThat(result.getIdentityKey()).isEqualTo(existsAccount.getPhoneNumberIdentityKey()); + assertThat(result.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey(IdentityType.PNI)); assertThat(result.getDevicesCount()).isEqualTo(1); assertEquals(SAMPLE_KEY_PNI, result.getDevice(1).getPreKey()); assertThat(result.getDevice(1).getPqPreKey()).isNull(); assertThat(result.getDevice(1).getRegistrationId()).isEqualTo(SAMPLE_PNI_REGISTRATION_ID); - assertEquals(existsAccount.getDevice(1).get().getPhoneNumberIdentitySignedPreKey(), result.getDevice(1).getSignedPreKey()); + assertEquals(existsAccount.getDevice(1).get().getSignedPreKey(IdentityType.PNI), + result.getDevice(1).getSignedPreKey()); verify(KEYS).takeEC(EXISTS_PNI, 1); verify(KEYS).getEcSignedPreKey(EXISTS_PNI, 1); @@ -409,12 +414,13 @@ class KeysControllerTest { .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) .get(PreKeyResponse.class); - assertThat(result.getIdentityKey()).isEqualTo(existsAccount.getPhoneNumberIdentityKey()); + assertThat(result.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey(IdentityType.PNI)); assertThat(result.getDevicesCount()).isEqualTo(1); assertEquals(SAMPLE_KEY_PNI, result.getDevice(1).getPreKey()); assertThat(result.getDevice(1).getPqPreKey()).isEqualTo(SAMPLE_PQ_KEY_PNI); assertThat(result.getDevice(1).getRegistrationId()).isEqualTo(SAMPLE_PNI_REGISTRATION_ID); - assertEquals(existsAccount.getDevice(1).get().getPhoneNumberIdentitySignedPreKey(), result.getDevice(1).getSignedPreKey()); + assertEquals(existsAccount.getDevice(1).get().getSignedPreKey(IdentityType.PNI), + result.getDevice(1).getSignedPreKey()); verify(KEYS).takeEC(EXISTS_PNI, 1); verify(KEYS).takePQ(EXISTS_PNI, 1); @@ -432,12 +438,13 @@ class KeysControllerTest { .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) .get(PreKeyResponse.class); - assertThat(result.getIdentityKey()).isEqualTo(existsAccount.getPhoneNumberIdentityKey()); + assertThat(result.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey(IdentityType.PNI)); assertThat(result.getDevicesCount()).isEqualTo(1); assertEquals(SAMPLE_KEY_PNI, result.getDevice(1).getPreKey()); assertThat(result.getDevice(1).getPqPreKey()).isNull(); assertThat(result.getDevice(1).getRegistrationId()).isEqualTo(SAMPLE_REGISTRATION_ID); - assertEquals(existsAccount.getDevice(1).get().getPhoneNumberIdentitySignedPreKey(), result.getDevice(1).getSignedPreKey()); + assertEquals(existsAccount.getDevice(1).get().getSignedPreKey(IdentityType.PNI), + result.getDevice(1).getSignedPreKey()); verify(KEYS).takeEC(EXISTS_PNI, 1); verify(KEYS).getEcSignedPreKey(EXISTS_PNI, 1); @@ -468,11 +475,12 @@ class KeysControllerTest { .header(OptionalAccess.UNIDENTIFIED, AuthHelper.getUnidentifiedAccessHeader("1337".getBytes())) .get(PreKeyResponse.class); - assertThat(result.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey()); + assertThat(result.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey(IdentityType.ACI)); assertThat(result.getDevicesCount()).isEqualTo(1); assertEquals(SAMPLE_KEY, result.getDevice(1).getPreKey()); assertEquals(SAMPLE_PQ_KEY, result.getDevice(1).getPqPreKey()); - assertEquals(existsAccount.getDevice(1).get().getSignedPreKey(), result.getDevice(1).getSignedPreKey()); + assertEquals(existsAccount.getDevice(1).get().getSignedPreKey(IdentityType.ACI), + result.getDevice(1).getSignedPreKey()); verify(KEYS).takeEC(EXISTS_UUID, 1); verify(KEYS).takePQ(EXISTS_UUID, 1); @@ -534,7 +542,7 @@ class KeysControllerTest { .get(PreKeyResponse.class); assertThat(results.getDevicesCount()).isEqualTo(3); - assertThat(results.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey()); + assertThat(results.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey(IdentityType.ACI)); ECSignedPreKey signedPreKey = results.getDevice(1).getSignedPreKey(); ECPreKey preKey = results.getDevice(1).getPreKey(); @@ -595,7 +603,7 @@ class KeysControllerTest { .get(PreKeyResponse.class); assertThat(results.getDevicesCount()).isEqualTo(3); - assertThat(results.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey()); + assertThat(results.getIdentityKey()).isEqualTo(existsAccount.getIdentityKey(IdentityType.ACI)); ECSignedPreKey signedPreKey = results.getDevice(1).getSignedPreKey(); ECPreKey preKey = results.getDevice(1).getPreKey(); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ProfileControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ProfileControllerTest.java index 072d8dd50..75e60ca01 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ProfileControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ProfileControllerTest.java @@ -193,9 +193,7 @@ class ProfileControllerTest { profileAccount = mock(Account.class); - when(profileAccount.getIdentityKey()).thenReturn(ACCOUNT_TWO_IDENTITY_KEY); when(profileAccount.getIdentityKey(IdentityType.ACI)).thenReturn(ACCOUNT_TWO_IDENTITY_KEY); - when(profileAccount.getPhoneNumberIdentityKey()).thenReturn(ACCOUNT_TWO_PHONE_NUMBER_IDENTITY_KEY); when(profileAccount.getIdentityKey(IdentityType.PNI)).thenReturn(ACCOUNT_TWO_PHONE_NUMBER_IDENTITY_KEY); when(profileAccount.getUuid()).thenReturn(AuthHelper.VALID_UUID_TWO); when(profileAccount.getPhoneNumberIdentifier()).thenReturn(AuthHelper.VALID_PNI_TWO); @@ -207,9 +205,7 @@ class ProfileControllerTest { Account capabilitiesAccount = mock(Account.class); when(capabilitiesAccount.getUuid()).thenReturn(AuthHelper.VALID_UUID); - when(capabilitiesAccount.getIdentityKey()).thenReturn(ACCOUNT_IDENTITY_KEY); when(capabilitiesAccount.getIdentityKey(IdentityType.ACI)).thenReturn(ACCOUNT_IDENTITY_KEY); - when(capabilitiesAccount.getPhoneNumberIdentityKey()).thenReturn(ACCOUNT_PHONE_NUMBER_IDENTITY_KEY); when(capabilitiesAccount.getIdentityKey(IdentityType.PNI)).thenReturn(ACCOUNT_PHONE_NUMBER_IDENTITY_KEY); when(capabilitiesAccount.isEnabled()).thenReturn(true); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerChangeNumberIntegrationTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerChangeNumberIntegrationTest.java index ca7141630..090c406de 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerChangeNumberIntegrationTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerChangeNumberIntegrationTest.java @@ -31,6 +31,7 @@ import org.whispersystems.textsecuregcm.controllers.MismatchedDevicesException; import org.whispersystems.textsecuregcm.entities.AccountAttributes; import org.whispersystems.textsecuregcm.entities.ECSignedPreKey; import org.whispersystems.textsecuregcm.experiment.ExperimentEnrollmentManager; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.push.ClientPresenceManager; import org.whispersystems.textsecuregcm.redis.RedisClusterExtension; import org.whispersystems.textsecuregcm.securebackup.SecureBackupClient; @@ -180,12 +181,12 @@ class AccountsManagerChangeNumberIntegrationTest { assertEquals(Optional.empty(), deletedAccounts.findUuid(originalNumber)); assertEquals(Optional.empty(), deletedAccounts.findUuid(secondNumber)); - assertEquals(pniIdentityKey, updatedAccount.getPhoneNumberIdentityKey()); + assertEquals(pniIdentityKey, updatedAccount.getIdentityKey(IdentityType.PNI)); assertEquals(OptionalInt.of(rotatedPniRegistrationId), updatedAccount.getMasterDevice().orElseThrow().getPhoneNumberIdentityRegistrationId()); - assertEquals(rotatedSignedPreKey, updatedAccount.getMasterDevice().orElseThrow().getPhoneNumberIdentitySignedPreKey()); + assertEquals(rotatedSignedPreKey, updatedAccount.getMasterDevice().orElseThrow().getSignedPreKey(IdentityType.PNI)); } @Test diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerConcurrentModificationIntegrationTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerConcurrentModificationIntegrationTest.java index 449744ecc..d2587e64b 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerConcurrentModificationIntegrationTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerConcurrentModificationIntegrationTest.java @@ -43,6 +43,7 @@ import org.whispersystems.textsecuregcm.auth.SaltedTokenHash; import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration; import org.whispersystems.textsecuregcm.entities.AccountAttributes; import org.whispersystems.textsecuregcm.experiment.ExperimentEnrollmentManager; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.push.ClientPresenceManager; import org.whispersystems.textsecuregcm.securebackup.SecureBackupClient; import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient; @@ -194,7 +195,7 @@ class AccountsManagerConcurrentModificationIntegrationTest { assertAll(name, () -> assertEquals(discoverableByPhoneNumber, account.isDiscoverableByPhoneNumber()), () -> assertEquals(currentProfileVersion, account.getCurrentProfileVersion().orElseThrow()), - () -> assertEquals(identityKey, account.getIdentityKey()), + () -> assertEquals(identityKey, account.getIdentityKey(IdentityType.ACI)), () -> assertArrayEquals(unidentifiedAccessKey, account.getUnidentifiedAccessKey().orElseThrow()), () -> assertTrue(account.getRegistrationLock().verify(clientRegistrationLock)), () -> assertEquals(unrestrictedUnidentifiedAccess, account.isUnrestrictedUnidentifiedAccess()) diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java index b2ec44a40..8810ca7f3 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java @@ -63,6 +63,7 @@ import org.whispersystems.textsecuregcm.entities.ECSignedPreKey; import org.whispersystems.textsecuregcm.entities.KEMSignedPreKey; import org.whispersystems.textsecuregcm.experiment.ExperimentEnrollmentManager; import org.whispersystems.textsecuregcm.identity.AciServiceIdentifier; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.identity.PniServiceIdentifier; import org.whispersystems.textsecuregcm.push.ClientPresenceManager; import org.whispersystems.textsecuregcm.securebackup.SecureBackupClient; @@ -790,7 +791,7 @@ class AccountsManagerTest { account = accountsManager.update(account, a -> a.setIdentityKey(identityKey)); assertEquals(1, account.getVersion()); - assertEquals(identityKey, account.getIdentityKey()); + assertEquals(identityKey, account.getIdentityKey(IdentityType.ACI)); verify(accounts, times(1)).getByAccountIdentifier(uuid); verify(accounts, times(2)).update(any()); @@ -817,7 +818,7 @@ class AccountsManagerTest { account = accountsManager.updateAsync(account, a -> a.setIdentityKey(identityKey)).join(); assertEquals(1, account.getVersion()); - assertEquals(identityKey, account.getIdentityKey()); + assertEquals(identityKey, account.getIdentityKey(IdentityType.ACI)); verify(accounts, times(1)).getByAccountIdentifierAsync(uuid); verify(accounts, times(2)).updateAsync(any()); @@ -1146,7 +1147,8 @@ class AccountsManagerTest { UUID oldUuid = account.getUuid(); UUID oldPni = account.getPhoneNumberIdentifier(); - Map oldSignedPreKeys = account.getDevices().stream().collect(Collectors.toMap(Device::getId, Device::getSignedPreKey)); + Map oldSignedPreKeys = account.getDevices().stream() + .collect(Collectors.toMap(Device::getId, d -> d.getSignedPreKey(IdentityType.ACI))); final IdentityKey pniIdentityKey = new IdentityKey(Curve.generateKeyPair().getPublicKey()); @@ -1159,15 +1161,17 @@ class AccountsManagerTest { assertEquals(oldUuid, updatedAccount.getUuid()); assertEquals(number, updatedAccount.getNumber()); assertEquals(oldPni, updatedAccount.getPhoneNumberIdentifier()); - assertNull(updatedAccount.getIdentityKey()); - assertEquals(oldSignedPreKeys, updatedAccount.getDevices().stream().collect(Collectors.toMap(Device::getId, Device::getSignedPreKey))); + assertNull(updatedAccount.getIdentityKey(IdentityType.ACI)); + assertEquals(oldSignedPreKeys, updatedAccount.getDevices().stream() + .collect(Collectors.toMap(Device::getId, d -> d.getSignedPreKey(IdentityType.ACI)))); assertEquals(Map.of(1L, 101, 2L, 102), updatedAccount.getDevices().stream().collect(Collectors.toMap(Device::getId, Device::getRegistrationId))); // PNI stuff should - assertEquals(pniIdentityKey, updatedAccount.getPhoneNumberIdentityKey()); + assertEquals(pniIdentityKey, updatedAccount.getIdentityKey(IdentityType.PNI)); assertEquals(newSignedKeys, - updatedAccount.getDevices().stream().collect(Collectors.toMap(Device::getId, Device::getPhoneNumberIdentitySignedPreKey))); + updatedAccount.getDevices().stream() + .collect(Collectors.toMap(Device::getId, d -> d.getSignedPreKey(IdentityType.PNI)))); assertEquals(newRegistrationIds, updatedAccount.getDevices().stream().collect(Collectors.toMap(Device::getId, d -> d.getPhoneNumberIdentityRegistrationId().getAsInt()))); @@ -1199,7 +1203,8 @@ class AccountsManagerTest { when(keysManager.storeEcSignedPreKeys(any(), any())).thenReturn(CompletableFuture.completedFuture(null)); when(keysManager.storePqLastResort(any(), any())).thenReturn(CompletableFuture.completedFuture(null)); - Map oldSignedPreKeys = account.getDevices().stream().collect(Collectors.toMap(Device::getId, Device::getSignedPreKey)); + Map oldSignedPreKeys = account.getDevices().stream() + .collect(Collectors.toMap(Device::getId, d -> d.getSignedPreKey(IdentityType.ACI))); final IdentityKey pniIdentityKey = new IdentityKey(Curve.generateKeyPair().getPublicKey()); @@ -1210,15 +1215,17 @@ class AccountsManagerTest { assertEquals(oldUuid, updatedAccount.getUuid()); assertEquals(number, updatedAccount.getNumber()); assertEquals(oldPni, updatedAccount.getPhoneNumberIdentifier()); - assertNull(updatedAccount.getIdentityKey()); - assertEquals(oldSignedPreKeys, updatedAccount.getDevices().stream().collect(Collectors.toMap(Device::getId, Device::getSignedPreKey))); + assertNull(updatedAccount.getIdentityKey(IdentityType.ACI)); + assertEquals(oldSignedPreKeys, updatedAccount.getDevices().stream() + .collect(Collectors.toMap(Device::getId, d -> d.getSignedPreKey(IdentityType.ACI)))); assertEquals(Map.of(1L, 101, 2L, 102), updatedAccount.getDevices().stream().collect(Collectors.toMap(Device::getId, Device::getRegistrationId))); // PNI keys should - assertEquals(pniIdentityKey, updatedAccount.getPhoneNumberIdentityKey()); + assertEquals(pniIdentityKey, updatedAccount.getIdentityKey(IdentityType.PNI)); assertEquals(newSignedKeys, - updatedAccount.getDevices().stream().collect(Collectors.toMap(Device::getId, Device::getPhoneNumberIdentitySignedPreKey))); + updatedAccount.getDevices().stream() + .collect(Collectors.toMap(Device::getId, d -> d.getSignedPreKey(IdentityType.PNI)))); assertEquals(newRegistrationIds, updatedAccount.getDevices().stream().collect(Collectors.toMap(Device::getId, d -> d.getPhoneNumberIdentityRegistrationId().getAsInt()))); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsTest.java index c70bffe6a..2c21df2cd 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsTest.java @@ -48,6 +48,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration; import org.whispersystems.textsecuregcm.experiment.ExperimentEnrollmentManager; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.push.ClientPresenceManager; import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster; import org.whispersystems.textsecuregcm.securebackup.SecureBackupClient; @@ -746,7 +747,7 @@ class AccountsTest { accounts.reserveUsernameHash(account, USERNAME_HASH_1, Duration.ofDays(1)); accounts.confirmUsernameHash(account, USERNAME_HASH_1, ENCRYPTED_USERNAME_1); final UUID oldHandle = account.getUsernameLinkHandle(); - + { final Optional maybeAccount = accounts.getByUsernameHash(USERNAME_HASH_1); @@ -1116,7 +1117,8 @@ class AccountsTest { assertThat(resultDevice.getApnId()).isEqualTo(expectingDevice.getApnId()); assertThat(resultDevice.getGcmId()).isEqualTo(expectingDevice.getGcmId()); assertThat(resultDevice.getLastSeen()).isEqualTo(expectingDevice.getLastSeen()); - assertThat(resultDevice.getSignedPreKey()).isEqualTo(expectingDevice.getSignedPreKey()); + assertThat(resultDevice.getSignedPreKey(IdentityType.ACI)).isEqualTo( + expectingDevice.getSignedPreKey(IdentityType.ACI)); assertThat(resultDevice.getFetchesMessages()).isEqualTo(expectingDevice.getFetchesMessages()); assertThat(resultDevice.getUserAgent()).isEqualTo(expectingDevice.getUserAgent()); assertThat(resultDevice.getName()).isEqualTo(expectingDevice.getName()); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AccountsHelper.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AccountsHelper.java index 52362d1c5..b1ff2f2db 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AccountsHelper.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AccountsHelper.java @@ -125,8 +125,8 @@ public class AccountsHelper { case "isPaymentActivationSupported" -> when(updatedAccount.isPaymentActivationSupported()).thenAnswer(stubbing); case "getEnabledDeviceCount" -> when(updatedAccount.getEnabledDeviceCount()).thenAnswer(stubbing); case "getRegistrationLock" -> when(updatedAccount.getRegistrationLock()).thenAnswer(stubbing); - case "getIdentityKey" -> when(updatedAccount.getIdentityKey()).thenAnswer(stubbing); - case "getPhoneNumberIdentityKey" -> when(updatedAccount.getPhoneNumberIdentityKey()).thenAnswer(stubbing); + case "getIdentityKey" -> + when(updatedAccount.getIdentityKey(stubbing.getInvocation().getArgument(0))).thenAnswer(stubbing); case "getBadges" -> when(updatedAccount.getBadges()).thenAnswer(stubbing); case "getLastSeen" -> when(updatedAccount.getLastSeen()).thenAnswer(stubbing); case "hasLockedCredentials" -> when(updatedAccount.hasLockedCredentials()).thenAnswer(stubbing); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AuthHelper.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AuthHelper.java index 0a92c212b..59abd528d 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AuthHelper.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AuthHelper.java @@ -27,6 +27,7 @@ import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.DisabledPermittedAccountAuthenticator; import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.SaltedTokenHash; +import org.whispersystems.textsecuregcm.identity.IdentityType; import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.AccountsManager; import org.whispersystems.textsecuregcm.storage.Device; @@ -165,7 +166,7 @@ public class AuthHelper { when(UNDISCOVERABLE_ACCOUNT.isDiscoverableByPhoneNumber()).thenReturn(false); when(VALID_ACCOUNT_3.isDiscoverableByPhoneNumber()).thenReturn(true); - when(VALID_ACCOUNT.getIdentityKey()).thenReturn(VALID_IDENTITY); + when(VALID_ACCOUNT.getIdentityKey(IdentityType.ACI)).thenReturn(VALID_IDENTITY); reset(ACCOUNTS_MANAGER);