mirror of
https://github.com/signalapp/Signal-Server
synced 2026-08-31 22:52:11 +01:00
Add support for issuing libsignal v0.101.0+ call link credentials
This commit is contained in:
@@ -79,6 +79,7 @@ storageService.userAuthenticationTokenSharedSecret: AAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
|
||||
zkConfig-libsignal-0.42.serverSecret: ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdef
|
||||
|
||||
callingZkConfigPreV101.serverSecret: ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzAA==
|
||||
callingZkConfig.serverSecret: ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzAA==
|
||||
chatZkConfig.serverSecret: ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789+abcdefghijklmnopqrstuvwxyzAA==
|
||||
|
||||
|
||||
@@ -315,6 +315,9 @@ storageService:
|
||||
AAAAAAAAAAAAAAAAAAAA
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
callingZkConfigPreV101:
|
||||
serverSecret: secret://callingZkConfigPreV101.serverSecret
|
||||
|
||||
callingZkConfig:
|
||||
serverSecret: secret://callingZkConfig.serverSecret
|
||||
|
||||
|
||||
+10
@@ -228,6 +228,11 @@ public class WhisperServerConfiguration extends Configuration {
|
||||
@JsonProperty
|
||||
private PaymentsServiceConfiguration paymentsService;
|
||||
|
||||
@Valid
|
||||
@NotNull
|
||||
@JsonProperty
|
||||
private GenericZkConfig callingZkConfigPreV101;
|
||||
|
||||
@Valid
|
||||
@NotNull
|
||||
@JsonProperty
|
||||
@@ -514,6 +519,11 @@ public class WhisperServerConfiguration extends Configuration {
|
||||
return chatZkConfig;
|
||||
}
|
||||
|
||||
/// ZK secret shared with Calling Service
|
||||
public GenericZkConfig getCallingZkConfigPreV101() {
|
||||
return callingZkConfigPreV101;
|
||||
}
|
||||
|
||||
/// ZK secret shared with Calling Service
|
||||
public GenericZkConfig getCallingZkConfig() {
|
||||
return callingZkConfig;
|
||||
|
||||
@@ -940,6 +940,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||
config.getCdnConfiguration().credentials().secretAccessKey().value());
|
||||
|
||||
ServerSecretParams groupZkSecretParams = new ServerSecretParams(config.getGroupsZkConfig().serverSecret().value());
|
||||
GenericServerSecretParams callingPreV101GenericZkSecretParams = new GenericServerSecretParams(config.getCallingZkConfigPreV101().serverSecret().value());
|
||||
GenericServerSecretParams callingGenericZkSecretParams = new GenericServerSecretParams(config.getCallingZkConfig().serverSecret().value());
|
||||
GenericServerSecretParams chatGenericZkSecretParams = new GenericServerSecretParams(config.getChatZkConfig().serverSecret().value());
|
||||
ServerZkProfileOperations zkProfileOperations = new ServerZkProfileOperations(groupZkSecretParams);
|
||||
@@ -1268,9 +1269,9 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||
experimentEnrollmentManager, config.getAttachments().maxAttachmentUploadSizeInBytes()),
|
||||
new ArchiveController(accountsManager, backupAuthManager, backupManager, backupMetrics, config.getAttachments().maxAttachmentUploadSizeInBytes(), config.getAttachments().maxMessageBackupUploadSizeInBytes()),
|
||||
new CallRoutingControllerV2(rateLimiters, cloudflareTurnCredentialsManager),
|
||||
new CallLinkController(rateLimiters, callingGenericZkSecretParams),
|
||||
new CallLinkController(rateLimiters, callingGenericZkSecretParams, callingPreV101GenericZkSecretParams),
|
||||
new CallQualitySurveyController(callQualitySurveyManager),
|
||||
new CertificateController(accountsManager, certificateGenerator, zkAuthOperations, callingGenericZkSecretParams, clock),
|
||||
new CertificateController(accountsManager, certificateGenerator, zkAuthOperations, callingGenericZkSecretParams, callingPreV101GenericZkSecretParams, clock),
|
||||
new ChallengeController(accountsManager, rateLimitChallengeManager, challengeConstraintChecker),
|
||||
new DeviceController(accountsManager, rateLimiters, persistentTimer),
|
||||
new DeviceCheckController(clock, accountsManager, backupAuthManager, appleDeviceCheckManager, rateLimiters,
|
||||
|
||||
+10
-3
@@ -2,6 +2,7 @@ package org.whispersystems.textsecuregcm.controllers;
|
||||
|
||||
import io.dropwizard.auth.Auth;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
@@ -9,6 +10,7 @@ import jakarta.ws.rs.BadRequestException;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
@@ -26,13 +28,16 @@ import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||
public class CallLinkController {
|
||||
private final RateLimiters rateLimiters;
|
||||
private final GenericServerSecretParams genericServerSecretParams;
|
||||
private final GenericServerSecretParams genericServerSecretParamsPreV101;
|
||||
|
||||
public CallLinkController(
|
||||
final RateLimiters rateLimiters,
|
||||
final GenericServerSecretParams genericServerSecretParams
|
||||
final GenericServerSecretParams genericServerSecretParams,
|
||||
final GenericServerSecretParams genericServerSecretParamsPreV101
|
||||
) {
|
||||
this.rateLimiters = rateLimiters;
|
||||
this.genericServerSecretParams = genericServerSecretParams;
|
||||
this.genericServerSecretParamsPreV101 = genericServerSecretParamsPreV101;
|
||||
}
|
||||
|
||||
@POST
|
||||
@@ -52,7 +57,9 @@ public class CallLinkController {
|
||||
@ApiResponse(responseCode = "429", description = "Ratelimited.")
|
||||
public CreateCallLinkCredential getCreateAuth(
|
||||
final @Auth AuthenticatedDevice auth,
|
||||
final @NotNull @Valid GetCreateCallLinkCredentialsRequest request
|
||||
final @NotNull @Valid GetCreateCallLinkCredentialsRequest request,
|
||||
@Parameter(description = "Whether to use libsignal v0.101.0+ secret params")
|
||||
final @QueryParam("v101") boolean v101
|
||||
) throws RateLimitExceededException {
|
||||
|
||||
rateLimiters.getCreateCallLinkLimiter().validate(auth.accountIdentifier());
|
||||
@@ -67,7 +74,7 @@ public class CallLinkController {
|
||||
}
|
||||
|
||||
return new CreateCallLinkCredential(
|
||||
createCallLinkCredentialRequest.issueCredential(new ServiceId.Aci(auth.accountIdentifier()), truncatedDayTimestamp, genericServerSecretParams).serialize(),
|
||||
createCallLinkCredentialRequest.issueCredential(new ServiceId.Aci(auth.accountIdentifier()), truncatedDayTimestamp, v101 ? genericServerSecretParams : genericServerSecretParamsPreV101).serialize(),
|
||||
truncatedDayTimestamp.getEpochSecond()
|
||||
);
|
||||
}
|
||||
|
||||
+8
-2
@@ -10,6 +10,7 @@ import static org.whispersystems.textsecuregcm.metrics.MetricsUtil.name;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.dropwizard.auth.Auth;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.ws.rs.BadRequestException;
|
||||
import jakarta.ws.rs.DefaultValue;
|
||||
@@ -49,6 +50,7 @@ public class CertificateController {
|
||||
private final CertificateGenerator certificateGenerator;
|
||||
private final ServerZkAuthOperations serverZkAuthOperations;
|
||||
private final GenericServerSecretParams genericServerSecretParams;
|
||||
private final GenericServerSecretParams genericServerSecretParamsPreV101;
|
||||
private final Clock clock;
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -61,12 +63,14 @@ public class CertificateController {
|
||||
@Nonnull CertificateGenerator certificateGenerator,
|
||||
@Nonnull ServerZkAuthOperations serverZkAuthOperations,
|
||||
@Nonnull GenericServerSecretParams genericServerSecretParams,
|
||||
@Nonnull GenericServerSecretParams genericServerSecretParamsPreV101,
|
||||
@Nonnull Clock clock) {
|
||||
|
||||
this.accountsManager = accountsManager;
|
||||
this.certificateGenerator = Objects.requireNonNull(certificateGenerator);
|
||||
this.serverZkAuthOperations = Objects.requireNonNull(serverZkAuthOperations);
|
||||
this.genericServerSecretParams = genericServerSecretParams;
|
||||
this.genericServerSecretParamsPreV101 = genericServerSecretParamsPreV101;
|
||||
this.clock = Objects.requireNonNull(clock);
|
||||
}
|
||||
|
||||
@@ -95,7 +99,9 @@ public class CertificateController {
|
||||
public GroupCredentials getGroupAuthenticationCredentials(
|
||||
@Auth AuthenticatedDevice auth,
|
||||
@QueryParam("redemptionStartSeconds") long startSeconds,
|
||||
@QueryParam("redemptionEndSeconds") long endSeconds) {
|
||||
@QueryParam("redemptionEndSeconds") long endSeconds,
|
||||
@Parameter(description = "Whether to use libsignal v0.101.0+ secret params")
|
||||
@QueryParam("v101") boolean v101) {
|
||||
|
||||
final RedemptionRange redemptionRange;
|
||||
try {
|
||||
@@ -127,7 +133,7 @@ public class CertificateController {
|
||||
(int) redemption.getEpochSecond()));
|
||||
|
||||
callLinkAuthCredentials.add(new GroupCredentials.CallLinkAuthCredential(
|
||||
CallLinkAuthCredentialResponse.issueCredential(aci, redemption, genericServerSecretParams).serialize(),
|
||||
CallLinkAuthCredentialResponse.issueCredential(aci, redemption, v101 ? genericServerSecretParams : genericServerSecretParamsPreV101).serialize(),
|
||||
redemption.getEpochSecond()));
|
||||
}
|
||||
|
||||
|
||||
+35
-3
@@ -19,9 +19,17 @@ import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.NullSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.signal.libsignal.protocol.ServiceId;
|
||||
import org.signal.libsignal.protocol.util.Hex;
|
||||
import org.signal.libsignal.zkgroup.GenericServerSecretParams;
|
||||
import org.signal.libsignal.zkgroup.calllinks.CallLinkSecretParams;
|
||||
import org.signal.libsignal.zkgroup.calllinks.CreateCallLinkCredential;
|
||||
import org.signal.libsignal.zkgroup.calllinks.CreateCallLinkCredentialPresentation;
|
||||
import org.signal.libsignal.zkgroup.calllinks.CreateCallLinkCredentialRequestContext;
|
||||
import org.signal.libsignal.zkgroup.calllinks.CreateCallLinkCredentialResponse;
|
||||
import org.whispersystems.textsecuregcm.auth.AuthenticatedDevice;
|
||||
import org.whispersystems.textsecuregcm.entities.GetCreateCallLinkCredentialsRequest;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
||||
@@ -29,10 +37,12 @@ import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||
import org.whispersystems.textsecuregcm.mappers.RateLimitExceededExceptionMapper;
|
||||
import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
|
||||
import org.whispersystems.textsecuregcm.util.SystemMapper;
|
||||
import org.whispersystems.textsecuregcm.util.TestRandomUtil;
|
||||
|
||||
@ExtendWith(DropwizardExtensionsSupport.class)
|
||||
public class CallLinkControllerTest {
|
||||
private static final GenericServerSecretParams genericServerSecretParams = GenericServerSecretParams.generate();
|
||||
private static final GenericServerSecretParams genericServerSecretParamsPreV101 = GenericServerSecretParams.generate();
|
||||
private static final RateLimiters rateLimiters = mock(RateLimiters.class);
|
||||
private static final RateLimiter createCallLinkLimiter = mock(RateLimiter.class);
|
||||
private static final byte[] roomId = Hex.fromStringCondensedAssert("c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7");
|
||||
@@ -45,7 +55,7 @@ public class CallLinkControllerTest {
|
||||
.addProvider(new RateLimitExceededExceptionMapper())
|
||||
.setMapper(SystemMapper.jsonMapper())
|
||||
.setTestContainerFactory(new GrizzlyWebTestContainerFactory())
|
||||
.addResource(new CallLinkController(rateLimiters, genericServerSecretParams))
|
||||
.addResource(new CallLinkController(rateLimiters, genericServerSecretParams, genericServerSecretParamsPreV101))
|
||||
.build();
|
||||
|
||||
@BeforeEach
|
||||
@@ -53,14 +63,36 @@ public class CallLinkControllerTest {
|
||||
when(rateLimiters.getCreateCallLinkLimiter()).thenReturn(createCallLinkLimiter);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetCreateAuth() {
|
||||
@ParameterizedTest
|
||||
@NullSource
|
||||
@ValueSource(booleans = {true, false})
|
||||
void testGetCreateAuth(final Boolean v101) throws Exception {
|
||||
try (Response response = resources.getJerseyTest()
|
||||
.target("/v1/call-link/create-auth")
|
||||
// a null value will exclude the parameter altogether, rather than sending `?v101=`
|
||||
.queryParam("v101", v101)
|
||||
.request()
|
||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||
.post(Entity.json(new GetCreateCallLinkCredentialsRequest(createCallLinkRequestSerialized)))) {
|
||||
assertThat(response.getStatus()).isEqualTo(200);
|
||||
|
||||
final GenericServerSecretParams verificationParams = v101 != null && v101
|
||||
? genericServerSecretParams
|
||||
: genericServerSecretParamsPreV101;
|
||||
|
||||
final byte[] serializedCredential = response.readEntity(
|
||||
org.whispersystems.textsecuregcm.entities.CreateCallLinkCredential.class).credential();
|
||||
final CreateCallLinkCredentialResponse credentialResponse = new CreateCallLinkCredentialResponse(serializedCredential);
|
||||
|
||||
final ServiceId.Aci aci = new ServiceId.Aci(AuthHelper.VALID_UUID);
|
||||
final CreateCallLinkCredential credential = createCallLinkRequestContext.receiveResponse(credentialResponse, aci,
|
||||
verificationParams.getPublicParams());
|
||||
final CallLinkSecretParams callLinkSecretParams = CallLinkSecretParams.deriveFromRootKey(TestRandomUtil.nextBytes(16));
|
||||
|
||||
final CreateCallLinkCredentialPresentation presentation = credential.present(roomId,
|
||||
aci, verificationParams.getPublicParams(), callLinkSecretParams);
|
||||
|
||||
presentation.verify(roomId, verificationParams, callLinkSecretParams.getPublicParams());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+25
-7
@@ -68,6 +68,7 @@ class CertificateControllerTest {
|
||||
private static final ServerSecretParams SERVER_SECRET_PARAMS = ServerSecretParams.generate();
|
||||
|
||||
private static final GenericServerSecretParams genericServerSecretParams = GenericServerSecretParams.generate();
|
||||
private static final GenericServerSecretParams genericServerSecretParamsPreV101 = GenericServerSecretParams.generate();
|
||||
|
||||
private static final ServerZkAuthOperations SERVER_ZK_AUTH_OPERATIONS;
|
||||
private static final Clock clock = Clock.fixed(Instant.now(), ZoneId.systemDefault());
|
||||
@@ -96,7 +97,7 @@ class CertificateControllerTest {
|
||||
.addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedDevice.class))
|
||||
.setMapper(SystemMapper.jsonMapper())
|
||||
.setTestContainerFactory(new GrizzlyWebTestContainerFactory())
|
||||
.addResource(new CertificateController(AuthHelper.ACCOUNTS_MANAGER, CERTIFICATE_GENERATOR, SERVER_ZK_AUTH_OPERATIONS, genericServerSecretParams, clock))
|
||||
.addResource(new CertificateController(AuthHelper.ACCOUNTS_MANAGER, CERTIFICATE_GENERATOR, SERVER_ZK_AUTH_OPERATIONS, genericServerSecretParams, genericServerSecretParamsPreV101, clock))
|
||||
.build();
|
||||
|
||||
@Test
|
||||
@@ -237,7 +238,8 @@ class CertificateControllerTest {
|
||||
final UUID aci,
|
||||
final String password,
|
||||
@Nullable UUID pni,
|
||||
@Nullable byte[] authCredentialSalt) {
|
||||
@Nullable byte[] authCredentialSalt,
|
||||
@Nullable Boolean v101) {
|
||||
|
||||
final Instant startOfDay = clock.instant().truncatedTo(ChronoUnit.DAYS);
|
||||
|
||||
@@ -245,6 +247,8 @@ class CertificateControllerTest {
|
||||
.target("/v1/certificate/auth/group")
|
||||
.queryParam("redemptionStartSeconds", startOfDay.getEpochSecond())
|
||||
.queryParam("redemptionEndSeconds", startOfDay.getEpochSecond())
|
||||
// a null value will exclude the parameter altogether, rather than sending `?v101=`
|
||||
.queryParam("v101", v101)
|
||||
.request()
|
||||
.header("Authorization", AuthHelper.getAuthHeader(aci, password))
|
||||
.get(GroupCredentials.class);
|
||||
@@ -276,16 +280,24 @@ class CertificateControllerTest {
|
||||
|
||||
}
|
||||
|
||||
final GenericServerSecretParams verificationParams = v101 != null && v101
|
||||
? genericServerSecretParams
|
||||
: genericServerSecretParamsPreV101;
|
||||
|
||||
assertDoesNotThrow(() -> {
|
||||
new CallLinkAuthCredentialResponse(credentials.callLinkAuthCredentials().getFirst().credential())
|
||||
.receive(new ServiceId.Aci(aci), startOfDay, genericServerSecretParams.getPublicParams());
|
||||
.receive(new ServiceId.Aci(aci), startOfDay, verificationParams.getPublicParams());
|
||||
});
|
||||
}
|
||||
|
||||
static Collection<Arguments> getGroupCredentials() {
|
||||
return List.of(
|
||||
Arguments.argumentSet("account with phone number", true, AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD, AuthHelper.VALID_PNI, null),
|
||||
Arguments.argumentSet("account without phone number", false, AuthHelper.NUMBERLESS_UUID, AuthHelper.NUMBERLESS_PASSWORD, null, AuthHelper.NUMBERLESS_AUTH_CREDENTIAL_SALT)
|
||||
Arguments.argumentSet("account with phone number", true, AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD, AuthHelper.VALID_PNI, null, null),
|
||||
Arguments.argumentSet("account with phone number - v101 = false", true, AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD, AuthHelper.VALID_PNI, null, false),
|
||||
Arguments.argumentSet("account with phone number - v101 = true", true, AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD, AuthHelper.VALID_PNI, null, true),
|
||||
Arguments.argumentSet("account without phone number", false, AuthHelper.NUMBERLESS_UUID, AuthHelper.NUMBERLESS_PASSWORD, null, AuthHelper.NUMBERLESS_AUTH_CREDENTIAL_SALT, null),
|
||||
Arguments.argumentSet("account without phone number - v101 = false", false, AuthHelper.NUMBERLESS_UUID, AuthHelper.NUMBERLESS_PASSWORD, null, AuthHelper.NUMBERLESS_AUTH_CREDENTIAL_SALT, false),
|
||||
Arguments.argumentSet("account without phone number - v101 = true", false, AuthHelper.NUMBERLESS_UUID, AuthHelper.NUMBERLESS_PASSWORD, null, AuthHelper.NUMBERLESS_AUTH_CREDENTIAL_SALT, true)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -295,13 +307,15 @@ class CertificateControllerTest {
|
||||
final UUID aci,
|
||||
final String password,
|
||||
@Nullable UUID pni,
|
||||
@Nullable byte[] authCredentialSalt) {
|
||||
@Nullable byte[] authCredentialSalt,
|
||||
@Nullable Boolean v101) {
|
||||
final Instant startOfDay = clock.instant().truncatedTo(ChronoUnit.DAYS);
|
||||
|
||||
final GroupCredentials credentials = resources.getJerseyTest()
|
||||
.target("/v1/certificate/auth/group")
|
||||
.queryParam("redemptionStartSeconds", startOfDay.getEpochSecond())
|
||||
.queryParam("redemptionEndSeconds", startOfDay.plus(Duration.ofDays(7)).getEpochSecond())
|
||||
.queryParam("v101", v101)
|
||||
.request()
|
||||
.header("Authorization", AuthHelper.getAuthHeader(aci, password))
|
||||
.get(GroupCredentials.class);
|
||||
@@ -336,9 +350,13 @@ class CertificateControllerTest {
|
||||
new AuthCredentialWithPniResponse(credentials.credentials().getFirst().credential())));
|
||||
}
|
||||
|
||||
final GenericServerSecretParams verificationParams = v101 != null && v101
|
||||
? genericServerSecretParams
|
||||
: genericServerSecretParamsPreV101;
|
||||
|
||||
assertDoesNotThrow(() -> {
|
||||
new CallLinkAuthCredentialResponse(credentials.callLinkAuthCredentials().get(index).credential())
|
||||
.receive(new ServiceId.Aci(aci), redemptionTime, genericServerSecretParams.getPublicParams());
|
||||
.receive(new ServiceId.Aci(aci), redemptionTime, verificationParams.getPublicParams());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,6 +155,7 @@ storageService.userAuthenticationTokenSharedSecret: AAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
|
||||
# The below secrets were generated exclusively for testing purposes. Do not use them in any other context.
|
||||
zkConfig-libsignal-0.42.serverSecret: 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
|
||||
callingZkConfigPreV101.serverSecret: AIZmPk8ms6TWBTGFcFE1iEuu4kSpTRL1EAPA2ZVWm4EIIF/N811ZhILbCx8QSLBf90mNXhUtsfNF5PY5UdnJMgBGu3AtrVs5erRXf5hi6RxvCkl1QnYs/tcuUGNbkejyR9bPR2uJaK6CxGJS0RRUDWf8f2hQloe/+kWKilM1I/MHSV2+PcyCDJIigPi9RhbD2STXc6cHEpYXReg+1OYSEQk3K2M0qnUoVOAjbPuFXANEPU+106f37w/iF6MhyfWyDCb+oit29DFtoDS31cxheB3x1KVga2ErfnIyHpQrSWYHUdGPZLXc0xRmaa0VwDyyXzK0o3w4oS/F9+xqWYUWkwgsAm9e7dP4l0qVolnPQ67uNj7BFG4JQ0vXxD/JJQ+5B4bHyK+v5ndJpRMXDC9rJw8ehopvDCTXSoICqN7nvY8Fyqhf5zkM880Su2XiBa2paDTVuZgwq07zBeDrrPc2zQ8A4neV6++t95veOfpp94FymnHJ8ILaznKqzJluGDdtCA==
|
||||
callingZkConfig.serverSecret: AIZmPk8ms6TWBTGFcFE1iEuu4kSpTRL1EAPA2ZVWm4EIIF/N811ZhILbCx8QSLBf90mNXhUtsfNF5PY5UdnJMgBGu3AtrVs5erRXf5hi6RxvCkl1QnYs/tcuUGNbkejyR9bPR2uJaK6CxGJS0RRUDWf8f2hQloe/+kWKilM1I/MHSV2+PcyCDJIigPi9RhbD2STXc6cHEpYXReg+1OYSEQk3K2M0qnUoVOAjbPuFXANEPU+106f37w/iF6MhyfWyDCb+oit29DFtoDS31cxheB3x1KVga2ErfnIyHpQrSWYHUdGPZLXc0xRmaa0VwDyyXzK0o3w4oS/F9+xqWYUWkwgsAm9e7dP4l0qVolnPQ67uNj7BFG4JQ0vXxD/JJQ+5B4bHyK+v5ndJpRMXDC9rJw8ehopvDCTXSoICqN7nvY8Fyqhf5zkM880Su2XiBa2paDTVuZgwq07zBeDrrPc2zQ8A4neV6++t95veOfpp94FymnHJ8ILaznKqzJluGDdtCA==
|
||||
chatZkConfig.serverSecret: AIZmPk8ms6TWBTGFcFE1iEuu4kSpTRL1EAPA2ZVWm4EIIF/N811ZhILbCx8QSLBf90mNXhUtsfNF5PY5UdnJMgBGu3AtrVs5erRXf5hi6RxvCkl1QnYs/tcuUGNbkejyR9bPR2uJaK6CxGJS0RRUDWf8f2hQloe/+kWKilM1I/MHSV2+PcyCDJIigPi9RhbD2STXc6cHEpYXReg+1OYSEQk3K2M0qnUoVOAjbPuFXANEPU+106f37w/iF6MhyfWyDCb+oit29DFtoDS31cxheB3x1KVga2ErfnIyHpQrSWYHUdGPZLXc0xRmaa0VwDyyXzK0o3w4oS/F9+xqWYUWkwgsAm9e7dP4l0qVolnPQ67uNj7BFG4JQ0vXxD/JJQ+5B4bHyK+v5ndJpRMXDC9rJw8ehopvDCTXSoICqN7nvY8Fyqhf5zkM880Su2XiBa2paDTVuZgwq07zBeDrrPc2zQ8A4neV6++t95veOfpp94FymnHJ8ILaznKqzJluGDdtCA==
|
||||
|
||||
|
||||
@@ -324,6 +324,9 @@ storageService:
|
||||
9Kxq0DY7RCEpdHMCKcOL
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
callingZkConfigPreV101:
|
||||
serverSecret: secret://callingZkConfigPreV101.serverSecret
|
||||
|
||||
callingZkConfig:
|
||||
serverSecret: secret://callingZkConfig.serverSecret
|
||||
|
||||
|
||||
Reference in New Issue
Block a user