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 {
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.
""")
List<@Valid ECPreKey> preKeys,
@JsonProperty
@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;
@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.
""")
ECSignedPreKey signedPreKey,
@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.
""")
private ECSignedPreKey signedPreKey;
@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.
""")
List<@Valid KEMSignedPreKey> pqPreKeys,
@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;
@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.
""")
KEMSignedPreKey pqLastResortPreKey,
@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.
""")
private 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.
""")
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;
}
@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.
""")
IdentityKey identityKey
) {
@AssertTrue
public boolean isSignatureValidOnEachSignedKey() {