Update error model in keys.proto

This commit is contained in:
Ravi Khadiwala
2026-02-02 08:39:40 -06:00
parent 8804f28cb8
commit 1009f3ba51
8 changed files with 236 additions and 172 deletions

View File

@@ -6,6 +6,7 @@
package org.whispersystems.textsecuregcm.grpc;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyByte;
import static org.mockito.ArgumentMatchers.eq;
@@ -33,10 +34,12 @@ 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.AccountPreKeyBundles;
import org.signal.chat.keys.CheckIdentityKeyRequest;
import org.signal.chat.keys.DevicePreKeyBundle;
import org.signal.chat.keys.GetPreKeysAnonymousRequest;
import org.signal.chat.keys.GetPreKeysAnonymousResponse;
import org.signal.chat.keys.GetPreKeysRequest;
import org.signal.chat.keys.GetPreKeysResponse;
import org.signal.chat.keys.KeysAnonymousGrpc;
import org.signal.chat.keys.ReactorKeysAnonymousGrpc;
import org.signal.libsignal.protocol.IdentityKey;
@@ -107,20 +110,21 @@ class KeysAnonymousGrpcServiceTest extends SimpleBaseGrpcTest<KeysAnonymousGrpcS
when(keysManager.takeDevicePreKeys(eq(Device.PRIMARY_ID), eq(identifier), any()))
.thenReturn(CompletableFuture.completedFuture(Optional.of(devicePreKeys)));
final GetPreKeysResponse response = unauthenticatedServiceStub().getPreKeys(GetPreKeysAnonymousRequest.newBuilder()
final GetPreKeysAnonymousResponse response = unauthenticatedServiceStub().getPreKeys(GetPreKeysAnonymousRequest.newBuilder()
.setUnidentifiedAccessKey(ByteString.copyFrom(unidentifiedAccessKey))
.setRequest(GetPreKeysRequest.newBuilder()
.setTargetIdentifier(ServiceIdentifierUtil.toGrpcServiceIdentifier(identifier))
.setDeviceId(Device.PRIMARY_ID))
.build());
final GetPreKeysResponse expectedResponse = GetPreKeysResponse.newBuilder()
.setIdentityKey(ByteString.copyFrom(identityKey.serialize()))
.putPreKeys(Device.PRIMARY_ID, GetPreKeysResponse.PreKeyBundle.newBuilder()
.setEcOneTimePreKey(toGrpcEcPreKey(ecPreKey))
.setEcSignedPreKey(toGrpcEcSignedPreKey(ecSignedPreKey))
.setKemOneTimePreKey(toGrpcKemSignedPreKey(kemSignedPreKey))
.build())
final GetPreKeysAnonymousResponse expectedResponse = GetPreKeysAnonymousResponse.newBuilder()
.setPreKeys(AccountPreKeyBundles.newBuilder()
.setIdentityKey(ByteString.copyFrom(identityKey.serialize()))
.putDevicePreKeys(Device.PRIMARY_ID, DevicePreKeyBundle.newBuilder()
.setEcOneTimePreKey(toGrpcEcPreKey(ecPreKey))
.setEcSignedPreKey(toGrpcEcSignedPreKey(ecSignedPreKey))
.setKemOneTimePreKey(toGrpcKemSignedPreKey(kemSignedPreKey))
.build()))
.build();
assertEquals(expectedResponse, response);
@@ -159,20 +163,21 @@ class KeysAnonymousGrpcServiceTest extends SimpleBaseGrpcTest<KeysAnonymousGrpcS
CLOCK.pin(expiration.minus(Duration.ofHours(1))); // set time so the credential isn't expired yet
final byte[] token = AuthHelper.validGroupSendToken(SERVER_SECRET_PARAMS, List.of(identifier), expiration);
final GetPreKeysResponse response = unauthenticatedServiceStub().getPreKeys(GetPreKeysAnonymousRequest.newBuilder()
final GetPreKeysAnonymousResponse response = unauthenticatedServiceStub().getPreKeys(GetPreKeysAnonymousRequest.newBuilder()
.setGroupSendToken(ByteString.copyFrom(token))
.setRequest(GetPreKeysRequest.newBuilder()
.setTargetIdentifier(ServiceIdentifierUtil.toGrpcServiceIdentifier(identifier))
.setDeviceId(Device.PRIMARY_ID))
.build());
final GetPreKeysResponse expectedResponse = GetPreKeysResponse.newBuilder()
.setIdentityKey(ByteString.copyFrom(identityKey.serialize()))
.putPreKeys(Device.PRIMARY_ID, GetPreKeysResponse.PreKeyBundle.newBuilder()
.setEcOneTimePreKey(toGrpcEcPreKey(ecPreKey))
.setEcSignedPreKey(toGrpcEcSignedPreKey(ecSignedPreKey))
.setKemOneTimePreKey(toGrpcKemSignedPreKey(kemSignedPreKey))
.build())
final GetPreKeysAnonymousResponse expectedResponse = GetPreKeysAnonymousResponse.newBuilder()
.setPreKeys(AccountPreKeyBundles.newBuilder()
.setIdentityKey(ByteString.copyFrom(identityKey.serialize()))
.putDevicePreKeys(Device.PRIMARY_ID, DevicePreKeyBundle.newBuilder()
.setEcOneTimePreKey(toGrpcEcPreKey(ecPreKey))
.setEcSignedPreKey(toGrpcEcSignedPreKey(ecSignedPreKey))
.setKemOneTimePreKey(toGrpcKemSignedPreKey(kemSignedPreKey))
.build()))
.build();
assertEquals(expectedResponse, response);
@@ -202,13 +207,15 @@ class KeysAnonymousGrpcServiceTest extends SimpleBaseGrpcTest<KeysAnonymousGrpcS
when(accountsManager.getByServiceIdentifierAsync(identifier))
.thenReturn(CompletableFuture.completedFuture(Optional.of(targetAccount)));
assertGetKeysFailure(Status.UNAUTHENTICATED, GetPreKeysAnonymousRequest.newBuilder()
.setUnidentifiedAccessKey(UUIDUtil.toByteString(UUID.randomUUID()))
.setRequest(GetPreKeysRequest.newBuilder()
.setTargetIdentifier(ServiceIdentifierUtil.toGrpcServiceIdentifier(identifier))
.setDeviceId(Device.PRIMARY_ID))
.build());
final GetPreKeysAnonymousResponse response = unauthenticatedServiceStub().getPreKeys(
GetPreKeysAnonymousRequest.newBuilder()
.setUnidentifiedAccessKey(UUIDUtil.toByteString(UUID.randomUUID()))
.setRequest(GetPreKeysRequest.newBuilder()
.setTargetIdentifier(ServiceIdentifierUtil.toGrpcServiceIdentifier(identifier))
.setDeviceId(Device.PRIMARY_ID))
.build());
assertTrue(response.hasFailedUnidentifiedAuthorization());
verifyNoInteractions(keysManager);
}
@@ -223,12 +230,14 @@ class KeysAnonymousGrpcServiceTest extends SimpleBaseGrpcTest<KeysAnonymousGrpcS
final byte[] token = AuthHelper.validGroupSendToken(SERVER_SECRET_PARAMS, List.of(identifier), expiration);
assertGetKeysFailure(Status.UNAUTHENTICATED, GetPreKeysAnonymousRequest.newBuilder()
.setGroupSendToken(ByteString.copyFrom(token))
.setRequest(GetPreKeysRequest.newBuilder()
.setTargetIdentifier(ServiceIdentifierUtil.toGrpcServiceIdentifier(identifier))
.setDeviceId(Device.PRIMARY_ID))
.build());
final GetPreKeysAnonymousResponse preKeysResponse =
unauthenticatedServiceStub().getPreKeys(GetPreKeysAnonymousRequest.newBuilder()
.setGroupSendToken(ByteString.copyFrom(token))
.setRequest(GetPreKeysRequest.newBuilder()
.setTargetIdentifier(ServiceIdentifierUtil.toGrpcServiceIdentifier(identifier))
.setDeviceId(Device.PRIMARY_ID))
.build());
assertTrue(preKeysResponse.hasFailedUnidentifiedAuthorization());
verifyNoInteractions(accountsManager);
verifyNoInteractions(keysManager);
@@ -246,13 +255,14 @@ class KeysAnonymousGrpcServiceTest extends SimpleBaseGrpcTest<KeysAnonymousGrpcS
final AciServiceIdentifier wrongAci = new AciServiceIdentifier(UUID.randomUUID());
final byte[] token = AuthHelper.validGroupSendToken(SERVER_SECRET_PARAMS, List.of(authorizedIdentifier), expiration);
assertGetKeysFailure(Status.UNAUTHENTICATED, GetPreKeysAnonymousRequest.newBuilder()
.setGroupSendToken(ByteString.copyFrom(token))
.setRequest(GetPreKeysRequest.newBuilder()
.setTargetIdentifier(ServiceIdentifierUtil.toGrpcServiceIdentifier(targetIdentifier))
.setDeviceId(Device.PRIMARY_ID))
.build());
final GetPreKeysAnonymousResponse response = unauthenticatedServiceStub().getPreKeys(
GetPreKeysAnonymousRequest.newBuilder()
.setGroupSendToken(ByteString.copyFrom(token))
.setRequest(GetPreKeysRequest.newBuilder()
.setTargetIdentifier(ServiceIdentifierUtil.toGrpcServiceIdentifier(targetIdentifier))
.setDeviceId(Device.PRIMARY_ID))
.build());
assertTrue(response.hasFailedUnidentifiedAuthorization());
verifyNoInteractions(accountsManager);
verifyNoInteractions(keysManager);
}
@@ -263,13 +273,13 @@ class KeysAnonymousGrpcServiceTest extends SimpleBaseGrpcTest<KeysAnonymousGrpcS
when(accountsManager.getByServiceIdentifierAsync(nonexistentAci))
.thenReturn(CompletableFuture.completedFuture(Optional.empty()));
assertGetKeysFailure(Status.UNAUTHENTICATED,
GetPreKeysAnonymousRequest.newBuilder()
final GetPreKeysAnonymousResponse preKeysResponse =
unauthenticatedServiceStub().getPreKeys(GetPreKeysAnonymousRequest.newBuilder()
.setUnidentifiedAccessKey(UUIDUtil.toByteString(UUID.randomUUID()))
.setRequest(GetPreKeysRequest.newBuilder()
.setTargetIdentifier(ServiceIdentifierUtil.toGrpcServiceIdentifier(nonexistentAci)))
.build());
.build());
assertTrue(preKeysResponse.hasFailedUnidentifiedAuthorization());
verifyNoInteractions(keysManager);
}
@@ -286,13 +296,13 @@ class KeysAnonymousGrpcServiceTest extends SimpleBaseGrpcTest<KeysAnonymousGrpcS
when(accountsManager.getByServiceIdentifierAsync(nonexistentAci))
.thenReturn(CompletableFuture.completedFuture(Optional.empty()));
assertGetKeysFailure(Status.NOT_FOUND,
GetPreKeysAnonymousRequest.newBuilder()
final GetPreKeysAnonymousResponse preKeysResponse =
unauthenticatedServiceStub().getPreKeys(GetPreKeysAnonymousRequest.newBuilder()
.setGroupSendToken(ByteString.copyFrom(token))
.setRequest(GetPreKeysRequest.newBuilder()
.setTargetIdentifier(ServiceIdentifierUtil.toGrpcServiceIdentifier(nonexistentAci)))
.build());
assertTrue(preKeysResponse.hasTargetNotFound());
verifyNoInteractions(keysManager);
}
@@ -312,14 +322,17 @@ class KeysAnonymousGrpcServiceTest extends SimpleBaseGrpcTest<KeysAnonymousGrpcS
when(accountsManager.getByServiceIdentifierAsync(new AciServiceIdentifier(accountIdentifier)))
.thenReturn(CompletableFuture.completedFuture(Optional.of(targetAccount)));
assertGetKeysFailure(Status.NOT_FOUND, GetPreKeysAnonymousRequest.newBuilder()
.setUnidentifiedAccessKey(ByteString.copyFrom(unidentifiedAccessKey))
.setRequest(GetPreKeysRequest.newBuilder()
.setTargetIdentifier(ServiceIdentifier.newBuilder()
.setIdentityType(org.signal.chat.common.IdentityType.IDENTITY_TYPE_ACI)
.setUuid(UUIDUtil.toByteString(accountIdentifier)))
.setDeviceId(Device.PRIMARY_ID))
.build());
final GetPreKeysAnonymousResponse response = unauthenticatedServiceStub().getPreKeys(
GetPreKeysAnonymousRequest.newBuilder()
.setUnidentifiedAccessKey(ByteString.copyFrom(unidentifiedAccessKey))
.setRequest(GetPreKeysRequest.newBuilder()
.setTargetIdentifier(ServiceIdentifier.newBuilder()
.setIdentityType(org.signal.chat.common.IdentityType.IDENTITY_TYPE_ACI)
.setUuid(UUIDUtil.toByteString(accountIdentifier)))
.setDeviceId(Device.PRIMARY_ID))
.build());
assertTrue(response.hasFailedUnidentifiedAuthorization());
}
@Test

View File

@@ -7,6 +7,7 @@ package org.whispersystems.textsecuregcm.grpc;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyByte;
import static org.mockito.ArgumentMatchers.anyString;
@@ -42,6 +43,8 @@ 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.AccountPreKeyBundles;
import org.signal.chat.keys.DevicePreKeyBundle;
import org.signal.chat.keys.GetPreKeyCountRequest;
import org.signal.chat.keys.GetPreKeyCountResponse;
import org.signal.chat.keys.GetPreKeysRequest;
@@ -479,7 +482,7 @@ class KeysGrpcServiceTest extends SimpleBaseGrpcTest<KeysGrpcService, KeysGrpc.K
final Map<Byte, KeysManager.DevicePreKeys> devicePreKeysMap = new HashMap<>();
final Map<Byte, Device> devices = new HashMap<>();
final Map<Byte, GetPreKeysResponse.PreKeyBundle> expectedPreKeyBundles = new HashMap<>();
final Map<Byte, DevicePreKeyBundle> expectedPreKeyBundles = new HashMap<>();
final byte deviceId1 = 1;
final byte deviceId2 = 2;
@@ -498,7 +501,7 @@ class KeysGrpcServiceTest extends SimpleBaseGrpcTest<KeysGrpcService, KeysGrpc.K
devicePreKeysMap.put(entry.getKey(), new KeysManager.DevicePreKeys(ecSignedPreKey, maybeEcPreKey, kemSignedPreKey));
final GetPreKeysResponse.PreKeyBundle.Builder builder = GetPreKeysResponse.PreKeyBundle.newBuilder()
final DevicePreKeyBundle.Builder builder = DevicePreKeyBundle.newBuilder()
.setEcSignedPreKey(EcSignedPreKey.newBuilder()
.setKeyId(ecSignedPreKey.keyId())
.setPublicKey(ByteString.copyFrom(ecSignedPreKey.serializedPublicKey()))
@@ -541,8 +544,9 @@ class KeysGrpcServiceTest extends SimpleBaseGrpcTest<KeysGrpcService, KeysGrpc.K
.build());
final GetPreKeysResponse expectedResponse = GetPreKeysResponse.newBuilder()
.setIdentityKey(ByteString.copyFrom(identityKey.serialize()))
.putPreKeys(1, expectedPreKeyBundles.get(deviceId1))
.setPreKeys(AccountPreKeyBundles.newBuilder()
.setIdentityKey(ByteString.copyFrom(identityKey.serialize()))
.putDevicePreKeys(1, expectedPreKeyBundles.get(deviceId1)))
.build();
assertEquals(expectedResponse, response);
@@ -557,9 +561,10 @@ class KeysGrpcServiceTest extends SimpleBaseGrpcTest<KeysGrpcService, KeysGrpc.K
.build());
final GetPreKeysResponse expectedResponse = GetPreKeysResponse.newBuilder()
.setIdentityKey(ByteString.copyFrom(identityKey.serialize()))
.putPreKeys(1, expectedPreKeyBundles.get(deviceId1))
.putPreKeys(2, expectedPreKeyBundles.get(deviceId2))
.setPreKeys(AccountPreKeyBundles.newBuilder()
.setIdentityKey(ByteString.copyFrom(identityKey.serialize()))
.putDevicePreKeys(1, expectedPreKeyBundles.get(deviceId1))
.putDevicePreKeys(2, expectedPreKeyBundles.get(deviceId2)))
.build();
assertEquals(expectedResponse, response);
@@ -571,12 +576,13 @@ class KeysGrpcServiceTest extends SimpleBaseGrpcTest<KeysGrpcService, KeysGrpc.K
when(accountsManager.getByServiceIdentifierAsync(any()))
.thenReturn(CompletableFuture.completedFuture(Optional.empty()));
assertStatusException(Status.NOT_FOUND, () -> authenticatedServiceStub().getPreKeys(GetPreKeysRequest.newBuilder()
final GetPreKeysResponse response = authenticatedServiceStub().getPreKeys(GetPreKeysRequest.newBuilder()
.setTargetIdentifier(ServiceIdentifier.newBuilder()
.setIdentityType(org.signal.chat.common.IdentityType.IDENTITY_TYPE_ACI)
.setUuid(UUIDUtil.toByteString(UUID.randomUUID()))
.build())
.build()));
.build());
assertTrue(response.hasTargetNotFound());
}
@Test
@@ -592,13 +598,14 @@ class KeysGrpcServiceTest extends SimpleBaseGrpcTest<KeysGrpcService, KeysGrpc.K
when(accountsManager.getByServiceIdentifierAsync(new AciServiceIdentifier(accountIdentifier)))
.thenReturn(CompletableFuture.completedFuture(Optional.of(targetAccount)));
assertStatusException(Status.NOT_FOUND, () -> authenticatedServiceStub().getPreKeys(GetPreKeysRequest.newBuilder()
final GetPreKeysResponse response = authenticatedServiceStub().getPreKeys(GetPreKeysRequest.newBuilder()
.setTargetIdentifier(ServiceIdentifier.newBuilder()
.setIdentityType(org.signal.chat.common.IdentityType.IDENTITY_TYPE_ACI)
.setUuid(UUIDUtil.toByteString(accountIdentifier))
.build())
.setDeviceId(Device.PRIMARY_ID)
.build()));
.build());
assertTrue(response.hasTargetNotFound());
}
@Test