Represent pre-key public keys and signatures as byte arrays in DAOs

This commit is contained in:
Jon Chambers
2023-05-19 10:02:14 -04:00
committed by Jon Chambers
parent 4a8ad3103c
commit 217b68a1e0
16 changed files with 141 additions and 112 deletions

View File

@@ -61,6 +61,8 @@ import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.ArgumentCaptor;
import org.mockito.stubbing.Answer;
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount;
import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount;
import org.whispersystems.textsecuregcm.auth.PhoneVerificationTokenManager;
@@ -72,7 +74,6 @@ 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.entities.SignedPreKey;
import org.whispersystems.textsecuregcm.limits.RateLimiter;
import org.whispersystems.textsecuregcm.limits.RateLimiters;
import org.whispersystems.textsecuregcm.mappers.ImpossiblePhoneNumberExceptionMapper;
@@ -87,6 +88,7 @@ import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.RegistrationRecoveryPasswordsManager;
import org.whispersystems.textsecuregcm.tests.util.AccountsHelper;
import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
import org.whispersystems.textsecuregcm.tests.util.KeysHelper;
import org.whispersystems.textsecuregcm.util.SystemMapper;
import org.whispersystems.textsecuregcm.util.Util;
@@ -786,12 +788,18 @@ class AccountControllerV2Test {
static Account buildTestAccountForDataReport(final UUID aci, final String number,
final boolean unrestrictedUnidentifiedAccess, final boolean discoverableByPhoneNumber,
List<AccountBadge> badges, List<DeviceData> devices) {
final ECKeyPair aciIdentityKeyPair = Curve.generateKeyPair();
final ECKeyPair pniIdentityKeyPair = Curve.generateKeyPair();
final Account account = new Account();
account.setUuid(aci);
account.setNumber(number, UUID.randomUUID());
account.setUnrestrictedUnidentifiedAccess(unrestrictedUnidentifiedAccess);
account.setDiscoverableByPhoneNumber(discoverableByPhoneNumber);
account.setBadges(Clock.systemUTC(), new ArrayList<>(badges));
account.setIdentityKey(KeysHelper.serializeIdentityKey(aciIdentityKeyPair));
account.setPhoneNumberIdentityKey(KeysHelper.serializeIdentityKey(pniIdentityKeyPair));
assert !devices.isEmpty();
@@ -802,7 +810,8 @@ class AccountControllerV2Test {
device.setId(deviceData.id);
device.setAuthTokenHash(passwordTokenHash);
device.setFetchesMessages(true);
device.setSignedPreKey(new SignedPreKey(1, "publicKey", "signature"));
device.setSignedPreKey(KeysHelper.signedECPreKey(1, aciIdentityKeyPair));
device.setPhoneNumberIdentitySignedPreKey(KeysHelper.signedECPreKey(2, pniIdentityKeyPair));
device.setLastSeen(deviceData.lastSeen().toEpochMilli());
device.setCreated(deviceData.created().toEpochMilli());
device.setUserAgent(deviceData.userAgent());

View File

@@ -69,6 +69,8 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.ArgumentCaptor;
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount;
import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount;
import org.whispersystems.textsecuregcm.auth.OptionalAccess;
@@ -101,6 +103,7 @@ import org.whispersystems.textsecuregcm.storage.MessagesManager;
import org.whispersystems.textsecuregcm.storage.ReportMessageManager;
import org.whispersystems.textsecuregcm.tests.util.AccountsHelper;
import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
import org.whispersystems.textsecuregcm.tests.util.KeysHelper;
import org.whispersystems.textsecuregcm.util.Pair;
import org.whispersystems.textsecuregcm.util.SystemMapper;
import org.whispersystems.websocket.Stories;
@@ -163,13 +166,17 @@ class MessageControllerTest {
@BeforeEach
void setup() {
final ECKeyPair identityKeyPair = Curve.generateKeyPair();
final List<Device> singleDeviceList = List.of(
generateTestDevice(SINGLE_DEVICE_ID1, SINGLE_DEVICE_REG_ID1, 1111, new SignedPreKey(333, "baz", "boop"), System.currentTimeMillis(), System.currentTimeMillis())
generateTestDevice(SINGLE_DEVICE_ID1, SINGLE_DEVICE_REG_ID1, 1111, KeysHelper.signedECPreKey(333, identityKeyPair), System.currentTimeMillis(), System.currentTimeMillis())
);
final List<Device> multiDeviceList = List.of(
generateTestDevice(MULTI_DEVICE_ID1, MULTI_DEVICE_REG_ID1, 2222, new SignedPreKey(111, "foo", "bar"), System.currentTimeMillis(), System.currentTimeMillis()),
generateTestDevice(MULTI_DEVICE_ID2, MULTI_DEVICE_REG_ID2, 3333, new SignedPreKey(222, "oof", "rab"), System.currentTimeMillis(), System.currentTimeMillis()),
generateTestDevice(MULTI_DEVICE_ID1, MULTI_DEVICE_REG_ID1, 2222, KeysHelper.signedECPreKey(111, identityKeyPair), System.currentTimeMillis(), System.currentTimeMillis()),
generateTestDevice(MULTI_DEVICE_ID2, MULTI_DEVICE_REG_ID2, 3333, KeysHelper.signedECPreKey(222, identityKeyPair), System.currentTimeMillis(), System.currentTimeMillis()),
generateTestDevice(MULTI_DEVICE_ID3, MULTI_DEVICE_REG_ID3, 4444, null, System.currentTimeMillis(), System.currentTimeMillis() - TimeUnit.DAYS.toMillis(31))
);

View File

@@ -134,11 +134,6 @@ class AccountsManagerConcurrentModificationIntegrationTest {
accountsManager.create("+14155551212", "password", null, new AccountAttributes(), new ArrayList<>()),
a -> {
a.setUnidentifiedAccessKey(new byte[16]);
final Random random = new Random();
final SignedPreKey signedPreKey = new SignedPreKey(random.nextInt(), "testPublicKey-" + random.nextInt(),
"testSignature-" + random.nextInt());
a.removeDevice(1);
a.addDevice(DevicesHelper.createDevice(1));
});

View File

@@ -49,6 +49,8 @@ import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.stubbing.Answer;
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
import org.whispersystems.textsecuregcm.controllers.MismatchedDevicesException;
import org.whispersystems.textsecuregcm.entities.AccountAttributes;
@@ -61,6 +63,7 @@ import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery2
import org.whispersystems.textsecuregcm.storage.Device.DeviceCapabilities;
import org.whispersystems.textsecuregcm.tests.util.AccountsHelper;
import org.whispersystems.textsecuregcm.tests.util.DevicesHelper;
import org.whispersystems.textsecuregcm.tests.util.KeysHelper;
import org.whispersystems.textsecuregcm.tests.util.RedisClusterHelper;
class AccountsManagerTest {
@@ -506,7 +509,7 @@ class AccountsManagerTest {
Device enabledDevice = new Device();
enabledDevice.setFetchesMessages(true);
enabledDevice.setSignedPreKey(new SignedPreKey(1L, "key", "signature"));
enabledDevice.setSignedPreKey(KeysHelper.signedECPreKey(1, Curve.generateKeyPair()));
enabledDevice.setLastSeen(System.currentTimeMillis());
final long deviceId = account.getNextDeviceId();
enabledDevice.setId(deviceId);
@@ -720,12 +723,13 @@ class AccountsManagerTest {
final UUID uuid = UUID.randomUUID();
final UUID originalPni = UUID.randomUUID();
final UUID targetPni = UUID.randomUUID();
final ECKeyPair identityKeyPair = Curve.generateKeyPair();
final Map<Long, SignedPreKey> newSignedKeys = Map.of(
1L, new SignedPreKey(1L, "pub1", "sig1"),
2L, new SignedPreKey(2L, "pub2", "sig2"));
1L, KeysHelper.signedECPreKey(1, identityKeyPair),
2L, KeysHelper.signedECPreKey(2, identityKeyPair));
final Map<Long, SignedPreKey> newSignedPqKeys = Map.of(
1L, new SignedPreKey(3L, "pub3", "sig3"),
2L, new SignedPreKey(4L, "pub4", "sig4"));
1L, KeysHelper.signedKEMPreKey(3, identityKeyPair),
2L, KeysHelper.signedKEMPreKey(4, identityKeyPair));
final Map<Long, Integer> newRegistrationIds = Map.of(1L, 201, 2L, 202);
final Account existingAccount = AccountsHelper.generateTestAccount(targetNumber, existingAccountUuid, targetPni, new ArrayList<>(), new byte[16]);
@@ -747,7 +751,7 @@ class AccountsManagerTest {
verify(keys).delete(newPni);
verify(keys).delete(originalPni);
verify(keys).getPqEnabledDevices(uuid);
verify(keys).storePqLastResort(eq(newPni), eq(Map.of(1L, new SignedPreKey(3L, "pub3", "sig3"))));
verify(keys).storePqLastResort(eq(newPni), eq(Map.of(1L, newSignedPqKeys.get(1L))));
verifyNoMoreInteractions(keys);
}
@@ -768,9 +772,10 @@ class AccountsManagerTest {
List<Device> devices = List.of(DevicesHelper.createDevice(1L, 0L, 101), DevicesHelper.createDevice(2L, 0L, 102));
Account account = AccountsHelper.generateTestAccount(number, UUID.randomUUID(), UUID.randomUUID(), devices, new byte[16]);
final ECKeyPair identityKeyPair = Curve.generateKeyPair();
Map<Long, SignedPreKey> newSignedKeys = Map.of(
1L, new SignedPreKey(1L, "pub1", "sig1"),
2L, new SignedPreKey(2L, "pub2", "sig2"));
1L, KeysHelper.signedECPreKey(1, identityKeyPair),
2L, KeysHelper.signedECPreKey(2, identityKeyPair));
Map<Long, Integer> newRegistrationIds = Map.of(1L, 201, 2L, 202);
UUID oldUuid = account.getUuid();
@@ -807,12 +812,13 @@ class AccountsManagerTest {
List<Device> devices = List.of(DevicesHelper.createDevice(1L, 0L, 101), DevicesHelper.createDevice(2L, 0L, 102));
Account account = AccountsHelper.generateTestAccount(number, UUID.randomUUID(), UUID.randomUUID(), devices, new byte[16]);
Map<Long, SignedPreKey> newSignedKeys = Map.of(
1L, new SignedPreKey(1L, "pub1", "sig1"),
2L, new SignedPreKey(2L, "pub2", "sig2"));
Map<Long, SignedPreKey> newSignedPqKeys = Map.of(
1L, new SignedPreKey(3L, "pub3", "sig3"),
2L, new SignedPreKey(4L, "pub4", "sig4"));
final ECKeyPair identityKeyPair = Curve.generateKeyPair();
final Map<Long, SignedPreKey> newSignedKeys = Map.of(
1L, KeysHelper.signedECPreKey(1, identityKeyPair),
2L, KeysHelper.signedECPreKey(2, identityKeyPair));
final Map<Long, SignedPreKey> newSignedPqKeys = Map.of(
1L, KeysHelper.signedKEMPreKey(3, identityKeyPair),
2L, KeysHelper.signedKEMPreKey(4, identityKeyPair));
Map<Long, Integer> newRegistrationIds = Map.of(1L, 201, 2L, 202);
UUID oldUuid = account.getUuid();
@@ -947,7 +953,7 @@ class AccountsManagerTest {
final Device device = new Device();
device.setId(Device.MASTER_ID);
device.setFetchesMessages(true);
device.setSignedPreKey(new SignedPreKey(1, "key", "sig"));
device.setSignedPreKey(KeysHelper.signedECPreKey(1, Curve.generateKeyPair()));
device.setLastSeen(lastSeen);
return device;

View File

@@ -20,9 +20,12 @@ import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
import org.whispersystems.textsecuregcm.entities.PreKey;
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
import org.whispersystems.textsecuregcm.storage.DynamoDbExtensionSchema.Tables;
import org.whispersystems.textsecuregcm.tests.util.KeysHelper;
import org.whispersystems.textsecuregcm.util.AttributeValues;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
@@ -211,9 +214,11 @@ class KeysTest {
void testStorePqLastResort() {
assertEquals(0, getLastResortCount(ACCOUNT_UUID));
final ECKeyPair identityKeyPair = Curve.generateKeyPair();
keys.storePqLastResort(
ACCOUNT_UUID,
Map.of(1L, new SignedPreKey(1L, "pub1", "sig1"), 2L, new SignedPreKey(2L, "pub2", "sig2")));
Map.of(1L, KeysHelper.signedKEMPreKey(1, identityKeyPair), 2L, KeysHelper.signedKEMPreKey(2, identityKeyPair)));
assertEquals(2, getLastResortCount(ACCOUNT_UUID));
assertEquals(1L, keys.getLastResort(ACCOUNT_UUID, 1L).get().getKeyId());
assertEquals(2L, keys.getLastResort(ACCOUNT_UUID, 2L).get().getKeyId());
@@ -221,7 +226,7 @@ class KeysTest {
keys.storePqLastResort(
ACCOUNT_UUID,
Map.of(1L, new SignedPreKey(3L, "pub3", "sig3"), 3L, new SignedPreKey(4L, "pub4", "sig4")));
Map.of(1L, KeysHelper.signedKEMPreKey(3, identityKeyPair), 3L, KeysHelper.signedKEMPreKey(4, identityKeyPair)));
assertEquals(3, getLastResortCount(ACCOUNT_UUID), "storing new last-resort keys should not create duplicates");
assertEquals(3L, keys.getLastResort(ACCOUNT_UUID, 1L).get().getKeyId(), "storing new last-resort keys should overwrite old ones");
assertEquals(2L, keys.getLastResort(ACCOUNT_UUID, 2L).get().getKeyId(), "storing new last-resort keys should leave untouched ones alone");
@@ -242,9 +247,11 @@ class KeysTest {
@Test
void testGetPqEnabledDevices() {
keys.store(ACCOUNT_UUID, DEVICE_ID, null, List.of(new SignedPreKey(1L, "pub1", "sig1")), null);
keys.store(ACCOUNT_UUID, DEVICE_ID + 1, null, null, new SignedPreKey(2L, "pub2", "sig2"));
keys.store(ACCOUNT_UUID, DEVICE_ID + 2, null, List.of(new SignedPreKey(3L, "pub3", "sig3")), new SignedPreKey(4L, "pub4", "sig4"));
final ECKeyPair identityKeyPair = Curve.generateKeyPair();
keys.store(ACCOUNT_UUID, DEVICE_ID, null, List.of(KeysHelper.signedKEMPreKey(1, identityKeyPair)), null);
keys.store(ACCOUNT_UUID, DEVICE_ID + 1, null, null, KeysHelper.signedKEMPreKey(2, identityKeyPair));
keys.store(ACCOUNT_UUID, DEVICE_ID + 2, null, List.of(KeysHelper.signedKEMPreKey(3, identityKeyPair)), KeysHelper.signedKEMPreKey(4, identityKeyPair));
keys.store(ACCOUNT_UUID, DEVICE_ID + 3, null, null, null);
assertIterableEquals(
Set.of(DEVICE_ID + 1, DEVICE_ID + 2),
@@ -291,7 +298,7 @@ class KeysTest {
final byte[] key = new byte[32];
new SecureRandom().nextBytes(key);
return new PreKey(keyId, Base64.getEncoder().encodeToString(key));
return new PreKey(keyId, key);
}
private static SignedPreKey generateTestSignedPreKey(final long keyId) {
@@ -302,6 +309,6 @@ class KeysTest {
secureRandom.nextBytes(key);
secureRandom.nextBytes(signature);
return new SignedPreKey(keyId, Base64.getEncoder().encodeToString(key), Base64.getEncoder().encodeToString(signature));
return new SignedPreKey(keyId, key, signature);
}
}

View File

@@ -514,7 +514,7 @@ class DeviceControllerTest {
private static SignedPreKey signedPreKeyWithBadSignature(final SignedPreKey signedPreKey) {
return new SignedPreKey(signedPreKey.getKeyId(),
signedPreKey.getPublicKey(),
Base64.getEncoder().encodeToString("incorrect-signature".getBytes(StandardCharsets.UTF_8)));
"incorrect-signature".getBytes(StandardCharsets.UTF_8));
}
@Test

View File

@@ -26,7 +26,6 @@ import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
import io.dropwizard.testing.junit5.ResourceExtension;
import java.time.Duration;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
@@ -86,18 +85,18 @@ class KeysControllerTest {
private final ECKeyPair PNI_IDENTITY_KEY_PAIR = Curve.generateKeyPair();
private final String PNI_IDENTITY_KEY = KeysHelper.serializeIdentityKey(PNI_IDENTITY_KEY_PAIR);
private final PreKey SAMPLE_KEY = new PreKey(1234, "test1");
private final PreKey SAMPLE_KEY2 = new PreKey(5667, "test3");
private final PreKey SAMPLE_KEY3 = new PreKey(334, "test5");
private final PreKey SAMPLE_KEY4 = new PreKey(336, "test6");
private final PreKey SAMPLE_KEY = KeysHelper.ecPreKey(1234);
private final PreKey SAMPLE_KEY2 = KeysHelper.ecPreKey(5667);
private final PreKey SAMPLE_KEY3 = KeysHelper.ecPreKey(334);
private final PreKey SAMPLE_KEY4 = KeysHelper.ecPreKey(336);
private final PreKey SAMPLE_KEY_PNI = new PreKey(7777, "test7");
private final PreKey SAMPLE_KEY_PNI = KeysHelper.ecPreKey(7777);
private final SignedPreKey SAMPLE_PQ_KEY = new SignedPreKey(2424, "test1", "sig");
private final SignedPreKey SAMPLE_PQ_KEY2 = new SignedPreKey(6868, "test3", "sig");
private final SignedPreKey SAMPLE_PQ_KEY3 = new SignedPreKey(1313, "test5", "sig");
private final SignedPreKey SAMPLE_PQ_KEY = KeysHelper.signedKEMPreKey(2424, Curve.generateKeyPair());
private final SignedPreKey SAMPLE_PQ_KEY2 = KeysHelper.signedKEMPreKey(6868, Curve.generateKeyPair());
private final SignedPreKey SAMPLE_PQ_KEY3 = KeysHelper.signedKEMPreKey(1313, Curve.generateKeyPair());
private final SignedPreKey SAMPLE_PQ_KEY_PNI = new SignedPreKey(8888, "test7", "sig");
private final SignedPreKey SAMPLE_PQ_KEY_PNI = KeysHelper.signedKEMPreKey(8888, Curve.generateKeyPair());
private final SignedPreKey SAMPLE_SIGNED_KEY = KeysHelper.signedECPreKey(1111, IDENTITY_KEY_PAIR);
private final SignedPreKey SAMPLE_SIGNED_KEY2 = KeysHelper.signedECPreKey(2222, IDENTITY_KEY_PAIR);
@@ -656,7 +655,7 @@ class KeysControllerTest {
@Test
void putKeysTestV2() {
final PreKey preKey = new PreKey(31337, "foobar");
final PreKey preKey = KeysHelper.ecPreKey(31337);
final ECKeyPair identityKeyPair = Curve.generateKeyPair();
final SignedPreKey signedPreKey = KeysHelper.signedECPreKey(31338, identityKeyPair);
final String identityKey = KeysHelper.serializeIdentityKey(identityKeyPair);
@@ -684,7 +683,7 @@ class KeysControllerTest {
@Test
void putKeysPqTestV2() {
final PreKey preKey = new PreKey(31337, "foobar");
final PreKey preKey = KeysHelper.ecPreKey(31337);
final ECKeyPair identityKeyPair = Curve.generateKeyPair();
final SignedPreKey signedPreKey = KeysHelper.signedECPreKey(31338, identityKeyPair);
final SignedPreKey pqPreKey = KeysHelper.signedECPreKey(31339, identityKeyPair);
@@ -716,7 +715,7 @@ class KeysControllerTest {
@Test
void putKeysByPhoneNumberIdentifierTestV2() {
final PreKey preKey = new PreKey(31337, "foobar");
final PreKey preKey = KeysHelper.ecPreKey(31337);
final ECKeyPair identityKeyPair = Curve.generateKeyPair();
final SignedPreKey signedPreKey = KeysHelper.signedECPreKey(31338, identityKeyPair);
final String identityKey = KeysHelper.serializeIdentityKey(identityKeyPair);
@@ -745,7 +744,7 @@ class KeysControllerTest {
@Test
void putKeysByPhoneNumberIdentifierPqTestV2() {
final PreKey preKey = new PreKey(31337, "foobar");
final PreKey preKey = KeysHelper.ecPreKey(31337);
final ECKeyPair identityKeyPair = Curve.generateKeyPair();
final SignedPreKey signedPreKey = KeysHelper.signedECPreKey(31338, identityKeyPair);
final SignedPreKey pqPreKey = KeysHelper.signedECPreKey(31339, identityKeyPair);
@@ -778,7 +777,7 @@ class KeysControllerTest {
@Test
void putPrekeyWithInvalidSignature() {
final SignedPreKey badSignedPreKey = new SignedPreKey(1L, "foo", "bar");
final SignedPreKey badSignedPreKey = KeysHelper.signedECPreKey(1, Curve.generateKeyPair());
PreKeyState preKeyState = new PreKeyState(IDENTITY_KEY, badSignedPreKey, List.of());
Response response =
resources.getJerseyTest()
@@ -793,16 +792,12 @@ class KeysControllerTest {
@Test
void disabledPutKeysTestV2() {
final PreKey preKey = new PreKey(31337, "foobar");
final PreKey preKey = KeysHelper.ecPreKey(31337);
final ECKeyPair identityKeyPair = Curve.generateKeyPair();
final SignedPreKey signedPreKey = KeysHelper.signedECPreKey(31338, identityKeyPair);
final String identityKey = KeysHelper.serializeIdentityKey(identityKeyPair);
List<PreKey> preKeys = new LinkedList<PreKey>() {{
add(preKey);
}};
PreKeyState preKeyState = new PreKeyState(identityKey, signedPreKey, preKeys);
PreKeyState preKeyState = new PreKeyState(identityKey, signedPreKey, List.of(preKey));
Response response =
resources.getJerseyTest()
@@ -819,7 +814,7 @@ class KeysControllerTest {
List<PreKey> capturedList = listCaptor.getValue();
assertThat(capturedList.size()).isEqualTo(1);
assertThat(capturedList.get(0).getKeyId()).isEqualTo(31337);
assertThat(capturedList.get(0).getPublicKey()).isEqualTo("foobar");
assertThat(capturedList.get(0).getPublicKey()).isEqualTo(preKey.getPublicKey());
verify(AuthHelper.DISABLED_ACCOUNT).setIdentityKey(eq(identityKey));
verify(AuthHelper.DISABLED_DEVICE).setSignedPreKey(eq(signedPreKey));
@@ -828,7 +823,7 @@ class KeysControllerTest {
@Test
void putIdentityKeyNonPrimary() {
final PreKey preKey = new PreKey(31337, "foobar");
final PreKey preKey = KeysHelper.ecPreKey(31337);
final SignedPreKey signedPreKey = KeysHelper.signedECPreKey(31338, IDENTITY_KEY_PAIR);
List<PreKey> preKeys = List.of(preKey);

View File

@@ -14,11 +14,15 @@ import static org.whispersystems.textsecuregcm.tests.util.JsonHelpers.jsonFixtur
import org.junit.jupiter.api.Test;
import org.whispersystems.textsecuregcm.entities.PreKey;
import java.util.Base64;
class PreKeyTest {
private static final byte[] PUBLIC_KEY = Base64.getDecoder().decode("BQ+NbroQtVKyFaCSfqzSw8Wy72Ff22RSa5ERKTv5DIk2");
@Test
void serializeToJSONV2() throws Exception {
PreKey preKey = new PreKey(1234, "test");
PreKey preKey = new PreKey(1234, PUBLIC_KEY);
assertThat("PreKeyV2 Serialization works",
asJson(preKey),

View File

@@ -6,6 +6,8 @@
package org.whispersystems.textsecuregcm.tests.util;
import java.util.Random;
import org.signal.libsignal.protocol.ecc.Curve;
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.util.Util;
@@ -36,8 +38,8 @@ public class DevicesHelper {
public static void setEnabled(Device device, boolean enabled) {
if (enabled) {
device.setSignedPreKey(new SignedPreKey(RANDOM.nextLong(), "testPublicKey-" + RANDOM.nextLong(),
"testSignature-" + RANDOM.nextLong()));
device.setSignedPreKey(KeysHelper.signedECPreKey(RANDOM.nextLong(), Curve.generateKeyPair()));
device.setPhoneNumberIdentitySignedPreKey(KeysHelper.signedECPreKey(RANDOM.nextLong(), Curve.generateKeyPair()));
device.setGcmId("testGcmId" + RANDOM.nextLong());
device.setLastSeen(Util.todayInMillis());
} else {

View File

@@ -10,22 +10,27 @@ import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
import org.signal.libsignal.protocol.kem.KEMKeyPair;
import org.signal.libsignal.protocol.kem.KEMKeyType;
import org.whispersystems.textsecuregcm.entities.PreKey;
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
public final class KeysHelper {
public static String serializeIdentityKey(ECKeyPair keyPair) {
return Base64.getEncoder().encodeToString(keyPair.getPublicKey().serialize());
}
public static PreKey ecPreKey(final long id) {
return new PreKey(id, Curve.generateKeyPair().getPublicKey().serialize());
}
public static SignedPreKey signedECPreKey(long id, final ECKeyPair identityKeyPair) {
final byte[] pubKey = Curve.generateKeyPair().getPublicKey().serialize();
final byte[] sig = identityKeyPair.getPrivateKey().calculateSignature(pubKey);
return new SignedPreKey(id, Base64.getEncoder().encodeToString(pubKey), Base64.getEncoder().encodeToString(sig));
return new SignedPreKey(id, pubKey, sig);
}
public static SignedPreKey signedKEMPreKey(long id, final ECKeyPair identityKeyPair) {
final byte[] pubKey = KEMKeyPair.generate(KEMKeyType.KYBER_1024).getPublicKey().serialize();
final byte[] sig = identityKeyPair.getPrivateKey().calculateSignature(pubKey);
return new SignedPreKey(id, Base64.getEncoder().encodeToString(pubKey), Base64.getEncoder().encodeToString(sig));
return new SignedPreKey(id, pubKey, sig);
}
}