mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-21 06:38:04 +01:00
Always check prekey signatures when new prekeys are uploaded
This commit is contained in:
committed by
GitHub
parent
bc68b67cdf
commit
e38911b2c5
@@ -11,6 +11,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.AssertTrue;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.whispersystems.textsecuregcm.util.ByteArrayAdapter;
|
||||
@@ -24,4 +25,12 @@ public record ChangeNumberRequest(String sessionId,
|
||||
@NotNull @Valid Map<Long, @NotNull @Valid SignedPreKey> devicePniSignedPrekeys,
|
||||
@NotNull Map<Long, Integer> pniRegistrationIds) implements PhoneVerificationRequest {
|
||||
|
||||
@AssertTrue
|
||||
public boolean isSignatureValidOnEachSignedPreKey() {
|
||||
if (devicePniSignedPrekeys == null) {
|
||||
return true;
|
||||
}
|
||||
return devicePniSignedPrekeys.values().parallelStream()
|
||||
.allMatch(spk -> PreKeySignatureValidator.validatePreKeySignature(pniIdentityKey, spk));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.whispersystems.textsecuregcm.entities;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.validation.constraints.AssertTrue;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@@ -18,4 +19,14 @@ public record ChangePhoneNumberRequest(@NotBlank String number,
|
||||
@Nullable List<IncomingMessage> deviceMessages,
|
||||
@Nullable Map<Long, SignedPreKey> devicePniSignedPrekeys,
|
||||
@Nullable Map<Long, Integer> pniRegistrationIds) {
|
||||
|
||||
@AssertTrue
|
||||
public boolean isSignatureValidOnEachSignedPreKey() {
|
||||
if (devicePniSignedPrekeys == null) {
|
||||
return true;
|
||||
}
|
||||
return devicePniSignedPrekeys.values().parallelStream()
|
||||
.allMatch(spk -> PreKeySignatureValidator.validatePreKeySignature(pniIdentityKey, spk));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.AssertTrue;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.whispersystems.textsecuregcm.util.ByteArrayAdapter;
|
||||
@@ -34,4 +35,11 @@ public record PhoneNumberIdentityKeyDistributionRequest(
|
||||
@Valid
|
||||
@Schema(description="The new registration ID to use for the phone-number identity of each device")
|
||||
Map<Long, Integer> pniRegistrationIds) {
|
||||
|
||||
@AssertTrue
|
||||
public boolean isSignatureValidOnEachSignedPreKey() {
|
||||
return devicePniSignedPrekeys.values().parallelStream()
|
||||
.allMatch(spk -> PreKeySignatureValidator.validatePreKeySignature(pniIdentityKey, spk));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2013-2020 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
package org.whispersystems.textsecuregcm.entities;
|
||||
|
||||
import static com.codahale.metrics.MetricRegistry.name;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import java.util.Base64;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
import org.signal.libsignal.protocol.ecc.Curve;
|
||||
import org.signal.libsignal.protocol.ecc.ECPublicKey;
|
||||
|
||||
public abstract class PreKeySignatureValidator {
|
||||
public static final boolean validatePreKeySignature(final String identityKeyB64, final SignedPreKey spk) {
|
||||
try {
|
||||
final byte[] identityKeyBytes = Base64.getDecoder().decode(identityKeyB64);
|
||||
final byte[] prekeyBytes = Base64.getDecoder().decode(spk.getPublicKey());
|
||||
final byte[] prekeySignatureBytes = Base64.getDecoder().decode(spk.getSignature());
|
||||
|
||||
final ECPublicKey identityKey = Curve.decodePoint(identityKeyBytes, 0);
|
||||
|
||||
return identityKey.verifySignature(prekeyBytes, prekeySignatureBytes);
|
||||
} catch (IllegalArgumentException | InvalidKeyException e) {
|
||||
Metrics.counter(name(PreKeySignatureValidator.class, "invalidPreKeySignature")).increment();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.AssertTrue;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@@ -48,4 +49,8 @@ public class PreKeyState {
|
||||
return identityKey;
|
||||
}
|
||||
|
||||
@AssertTrue
|
||||
public boolean isSignatureValid() {
|
||||
return PreKeySignatureValidator.validatePreKeySignature(identityKey, signedPreKey);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user