Convert `PreKeyState` to a record

This commit is contained in:
Jon Chambers 2023-11-28 22:03:10 -05:00 committed by Jon Chambers
parent 9ecfe15ac4
commit f10f772e94
3 changed files with 57 additions and 101 deletions

View File

@ -138,15 +138,15 @@ public class KeysController {
final boolean usePhoneNumberIdentity = usePhoneNumberIdentity(identityType);
if (preKeys.getSignedPreKey() != null &&
!preKeys.getSignedPreKey().equals(usePhoneNumberIdentity ? device.getSignedPreKey(IdentityType.PNI)
if (preKeys.signedPreKey() != null &&
!preKeys.signedPreKey().equals(usePhoneNumberIdentity ? device.getSignedPreKey(IdentityType.PNI)
: device.getSignedPreKey(IdentityType.ACI))) {
updateAccount = true;
}
final IdentityKey oldIdentityKey =
usePhoneNumberIdentity ? account.getIdentityKey(IdentityType.PNI) : account.getIdentityKey(IdentityType.ACI);
if (!Objects.equals(preKeys.getIdentityKey(), oldIdentityKey)) {
if (!Objects.equals(preKeys.identityKey(), oldIdentityKey)) {
updateAccount = true;
final boolean hasIdentityKey = oldIdentityKey != null;
@ -170,26 +170,26 @@ public class KeysController {
if (updateAccount) {
account = accounts.update(account, a -> {
if (preKeys.getSignedPreKey() != null) {
if (preKeys.signedPreKey() != null) {
a.getDevice(device.getId()).ifPresent(d -> {
if (usePhoneNumberIdentity) {
d.setPhoneNumberIdentitySignedPreKey(preKeys.getSignedPreKey());
d.setPhoneNumberIdentitySignedPreKey(preKeys.signedPreKey());
} else {
d.setSignedPreKey(preKeys.getSignedPreKey());
d.setSignedPreKey(preKeys.signedPreKey());
}
});
}
if (usePhoneNumberIdentity) {
a.setPhoneNumberIdentityKey(preKeys.getIdentityKey());
a.setPhoneNumberIdentityKey(preKeys.identityKey());
} else {
a.setIdentityKey(preKeys.getIdentityKey());
a.setIdentityKey(preKeys.identityKey());
}
});
}
return keys.store(getIdentifier(account, identityType), device.getId(),
preKeys.getPreKeys(), preKeys.getPqPreKeys(), preKeys.getSignedPreKey(), preKeys.getPqLastResortPreKey())
preKeys.preKeys(), preKeys.pqPreKeys(), preKeys.signedPreKey(), preKeys.pqLastResortPreKey())
.thenApply(Util.ASYNC_EMPTY_RESPONSE);
}

View File

@ -4,105 +4,59 @@
*/
package org.whispersystems.textsecuregcm.entities;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.google.common.annotations.VisibleForTesting;
import io.swagger.v3.oas.annotations.media.Schema;
import org.signal.libsignal.protocol.IdentityKey;
import org.whispersystems.textsecuregcm.util.IdentityKeyAdapter;
import javax.validation.Valid;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
public class PreKeyState {
@JsonProperty
public record PreKeyState(
@Valid
@Schema(description = """
A list of unsigned elliptic-curve prekeys to use for this device. If present and not empty, replaces all stored
unsigned EC prekeys for the device; if absent or empty, any stored unsigned EC prekeys for the device are not
deleted.
""")
private List<@Valid ECPreKey> preKeys;
List<@Valid ECPreKey> preKeys,
@JsonProperty
@Valid
@Schema(description = """
An optional signed elliptic-curve prekey to use for this device. If present, replaces the stored signed
elliptic-curve prekey for the device; if absent, the stored signed prekey is not deleted. If present, must have a
valid signature from the identity key in this request.
elliptic-curve prekey for the device; if absent, the stored signed prekey is not deleted. If present, must have
a valid signature from the identity key in this request.
""")
private ECSignedPreKey signedPreKey;
ECSignedPreKey signedPreKey,
@JsonProperty
@Valid
@Schema(description = """
A list of signed post-quantum one-time prekeys to use for this device. Each key must have a valid signature from
the identity key in this request. If present and not empty, replaces all stored unsigned PQ prekeys for the
device; if absent or empty, any stored unsigned PQ prekeys for the device are not deleted.
""")
private List<@Valid KEMSignedPreKey> pqPreKeys;
List<@Valid KEMSignedPreKey> pqPreKeys,
@JsonProperty
@Valid
@Schema(description = """
An optional signed last-resort post-quantum prekey to use for this device. If present, replaces the stored signed
post-quantum last-resort prekey for the device; if absent, a stored last-resort prekey will *not* be deleted. If
present, must have a valid signature from the identity key in this request.
An optional signed last-resort post-quantum prekey to use for this device. If present, replaces the stored
signed post-quantum last-resort prekey for the device; if absent, a stored last-resort prekey will *not* be
deleted. If present, must have a valid signature from the identity key in this request.
""")
private KEMSignedPreKey pqLastResortPreKey;
KEMSignedPreKey pqLastResortPreKey,
@JsonProperty
@JsonSerialize(using = IdentityKeyAdapter.Serializer.class)
@JsonDeserialize(using = IdentityKeyAdapter.Deserializer.class)
@NotNull
@Schema(description = """
Required. The public identity key for this identity (account or phone-number identity). If this device is not the
primary device for the account, must match the existing stored identity key for this identity.
Required. The public identity key for this identity (account or phone-number identity). If this device is not
the primary device for the account, must match the existing stored identity key for this identity.
""")
private IdentityKey identityKey;
public PreKeyState() {
}
@VisibleForTesting
public PreKeyState(IdentityKey identityKey, ECSignedPreKey signedPreKey, List<ECPreKey> keys) {
this(identityKey, signedPreKey, keys, null, null);
}
@VisibleForTesting
public PreKeyState(IdentityKey identityKey, ECSignedPreKey signedPreKey, List<ECPreKey> keys,
List<KEMSignedPreKey> pqKeys, KEMSignedPreKey pqLastResortKey) {
this.identityKey = identityKey;
this.signedPreKey = signedPreKey;
this.preKeys = keys;
this.pqPreKeys = pqKeys;
this.pqLastResortPreKey = pqLastResortKey;
}
public List<ECPreKey> getPreKeys() {
return preKeys;
}
public ECSignedPreKey getSignedPreKey() {
return signedPreKey;
}
public List<KEMSignedPreKey> getPqPreKeys() {
return pqPreKeys;
}
public KEMSignedPreKey getPqLastResortPreKey() {
return pqLastResortPreKey;
}
public IdentityKey getIdentityKey() {
return identityKey;
}
IdentityKey identityKey
) {
@AssertTrue
public boolean isSignatureValidOnEachSignedKey() {

View File

@ -732,7 +732,7 @@ class KeysControllerTest {
final ECSignedPreKey signedPreKey = KeysHelper.signedECPreKey(31338, identityKeyPair);
final IdentityKey identityKey = new IdentityKey(identityKeyPair.getPublicKey());
PreKeyState preKeyState = new PreKeyState(identityKey, signedPreKey, List.of(preKey));
final PreKeyState preKeyState = new PreKeyState(List.of(preKey), signedPreKey, null, null, identityKey);
Response response =
resources.getJerseyTest()
@ -763,7 +763,8 @@ class KeysControllerTest {
final KEMSignedPreKey pqLastResortPreKey = KeysHelper.signedKEMPreKey(31340, identityKeyPair);
final IdentityKey identityKey = new IdentityKey(identityKeyPair.getPublicKey());
PreKeyState preKeyState = new PreKeyState(identityKey, signedPreKey, List.of(preKey), List.of(pqPreKey), pqLastResortPreKey);
final PreKeyState preKeyState =
new PreKeyState(List.of(preKey), signedPreKey, List.of(pqPreKey), pqLastResortPreKey, identityKey);
Response response =
resources.getJerseyTest()
@ -866,7 +867,7 @@ class KeysControllerTest {
final ECSignedPreKey signedPreKey = KeysHelper.signedECPreKey(31338, identityKeyPair);
final IdentityKey identityKey = new IdentityKey(identityKeyPair.getPublicKey());
PreKeyState preKeyState = new PreKeyState(identityKey, signedPreKey, List.of(preKey));
final PreKeyState preKeyState = new PreKeyState(List.of(preKey), signedPreKey, null, null, identityKey);
Response response =
resources.getJerseyTest()
@ -898,7 +899,8 @@ class KeysControllerTest {
final KEMSignedPreKey pqLastResortPreKey = KeysHelper.signedKEMPreKey(31340, identityKeyPair);
final IdentityKey identityKey = new IdentityKey(identityKeyPair.getPublicKey());
PreKeyState preKeyState = new PreKeyState(identityKey, signedPreKey, List.of(preKey), List.of(pqPreKey), pqLastResortPreKey);
final PreKeyState preKeyState =
new PreKeyState(List.of(preKey), signedPreKey, List.of(pqPreKey), pqLastResortPreKey, identityKey);
Response response =
resources.getJerseyTest()
@ -926,7 +928,7 @@ class KeysControllerTest {
@Test
void putPrekeyWithInvalidSignature() {
final ECSignedPreKey badSignedPreKey = KeysHelper.signedECPreKey(1, Curve.generateKeyPair());
PreKeyState preKeyState = new PreKeyState(IDENTITY_KEY, badSignedPreKey, List.of());
final PreKeyState preKeyState = new PreKeyState(List.of(), badSignedPreKey, null, null, IDENTITY_KEY);
Response response =
resources.getJerseyTest()
.target("/v2/keys")
@ -945,7 +947,7 @@ class KeysControllerTest {
final ECSignedPreKey signedPreKey = KeysHelper.signedECPreKey(31338, identityKeyPair);
final IdentityKey identityKey = new IdentityKey(identityKeyPair.getPublicKey());
PreKeyState preKeyState = new PreKeyState(identityKey, signedPreKey, List.of(preKey));
final PreKeyState preKeyState = new PreKeyState(List.of(preKey), signedPreKey, null, null, identityKey);
Response response =
resources.getJerseyTest()
@ -975,9 +977,9 @@ class KeysControllerTest {
final ECPreKey preKey = KeysHelper.ecPreKey(31337);
final ECSignedPreKey signedPreKey = KeysHelper.signedECPreKey(31338, IDENTITY_KEY_PAIR);
List<ECPreKey> preKeys = List.of(preKey);
final List<ECPreKey> preKeys = List.of(preKey);
PreKeyState preKeyState = new PreKeyState(IDENTITY_KEY, signedPreKey, preKeys);
final PreKeyState preKeyState = new PreKeyState(preKeys, signedPreKey, null, null, IDENTITY_KEY);
Response response =
resources.getJerseyTest()