import okhttp3.Dns;
import okhttp3.Interceptor;
+import static org.asamk.signal.manager.api.ServiceEnvironment.LIVE;
+
class LiveConfig {
private static final byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder()
.decode("BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF");
private static final String CDSI_MRENCLAVE = "0f6fd79cdfdaa5b2e6337f534d3baf999318b0c462a7ac1f41297a3e4b424a57";
- private static final String SVR2_MRENCLAVE = "6ee1042f9e20f880326686dd4ba50c25359f01e9f733eeba4382bca001d45094";
+ private static final String SVR2_MRENCLAVE = "a6622ad4656e1abcd0bc0ff17c229477747d2ded0495c4ebee7ed35c1789fa97";
+ private static final String SVR2_MRENCLAVE_DEPRECATED = "6ee1042f9e20f880326686dd4ba50c25359f01e9f733eeba4382bca001d45094";
private static final String URL = "https://chat.signal.org";
private static final String CDN_URL = "https://cdn.signal.org";
}
}
- static String getCdsiMrenclave() {
- return CDSI_MRENCLAVE;
- }
-
- static String getSvr2Mrenclave() {
- return SVR2_MRENCLAVE;
+ static ServiceEnvironmentConfig getServiceEnvironmentConfig(List<Interceptor> interceptors) {
+ return new ServiceEnvironmentConfig(LIVE,
+ createDefaultServiceConfiguration(interceptors),
+ getUnidentifiedSenderTrustRoot(),
+ CDSI_MRENCLAVE,
+ List.of(SVR2_MRENCLAVE, SVR2_MRENCLAVE_DEPRECATED));
}
private LiveConfig() {
import okhttp3.Dns;
import okhttp3.Interceptor;
+import static org.asamk.signal.manager.api.ServiceEnvironment.STAGING;
+
class StagingConfig {
private static final byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder()
.decode("BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx");
private static final String CDSI_MRENCLAVE = "0f6fd79cdfdaa5b2e6337f534d3baf999318b0c462a7ac1f41297a3e4b424a57";
- private static final String SVR2_MRENCLAVE = "a8a261420a6bb9b61aa25bf8a79e8bd20d7652531feb3381cbffd446d270be95";
+ private static final String SVR2_MRENCLAVE = "acb1973aa0bbbd14b3b4e06f145497d948fd4a98efc500fcce363b3b743ec482";
+ private static final String SVR2_MRENCLAVE_DEPRECATED = "a8a261420a6bb9b61aa25bf8a79e8bd20d7652531feb3381cbffd446d270be95";
private static final String URL = "https://chat.staging.signal.org";
private static final String CDN_URL = "https://cdn-staging.signal.org";
}
}
- static String getCdsiMrenclave() {
- return CDSI_MRENCLAVE;
- }
-
- static String getSvr2Mrenclave() {
- return SVR2_MRENCLAVE;
+ static ServiceEnvironmentConfig getServiceEnvironmentConfig(List<Interceptor> interceptors) {
+ return new ServiceEnvironmentConfig(STAGING,
+ createDefaultServiceConfiguration(interceptors),
+ getUnidentifiedSenderTrustRoot(),
+ CDSI_MRENCLAVE,
+ List.of(SVR2_MRENCLAVE, SVR2_MRENCLAVE_DEPRECATED));
}
private StagingConfig() {
import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.kbs.MasterKey;
import org.whispersystems.signalservice.api.svr.SecureValueRecovery;
-import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV2;
import org.whispersystems.signalservice.internal.push.AuthCredentials;
import org.whispersystems.signalservice.internal.push.LockedException;
import java.io.IOException;
+import java.util.List;
public class PinHelper {
private static final Logger logger = LoggerFactory.getLogger(PinHelper.class);
- private final SecureValueRecoveryV2 secureValueRecoveryV2;
+ private final List<SecureValueRecovery> secureValueRecoveries;
- public PinHelper(final SecureValueRecoveryV2 secureValueRecoveryV2) {
- this.secureValueRecoveryV2 = secureValueRecoveryV2;
+ public PinHelper(final List<SecureValueRecovery> secureValueRecoveries) {
+ this.secureValueRecoveries = secureValueRecoveries;
}
public void setRegistrationLockPin(
String pin, MasterKey masterKey
) throws IOException {
- final var backupResponse = secureValueRecoveryV2.setPin(pin, masterKey).execute();
- switch (backupResponse) {
- case SecureValueRecovery.BackupResponse.Success success -> {
+ IOException exception = null;
+ for (final var secureValueRecovery : secureValueRecoveries) {
+ try {
+ final var backupResponse = secureValueRecovery.setPin(pin, masterKey).execute();
+ switch (backupResponse) {
+ case SecureValueRecovery.BackupResponse.Success success -> {
+ }
+ case SecureValueRecovery.BackupResponse.ServerRejected serverRejected ->
+ logger.warn("Backup svr2 failed: ServerRejected");
+ case SecureValueRecovery.BackupResponse.EnclaveNotFound enclaveNotFound ->
+ logger.warn("Backup svr2 failed: EnclaveNotFound");
+ case SecureValueRecovery.BackupResponse.ExposeFailure exposeFailure ->
+ logger.warn("Backup svr2 failed: ExposeFailure");
+ case SecureValueRecovery.BackupResponse.ApplicationError error ->
+ throw new IOException(error.getException());
+ case SecureValueRecovery.BackupResponse.NetworkError error -> throw error.getException();
+ case null, default -> throw new AssertionError("Unexpected response");
+ }
+ } catch (IOException e) {
+ exception = e;
}
- case SecureValueRecovery.BackupResponse.ServerRejected serverRejected ->
- logger.warn("Backup svr2 failed: ServerRejected");
- case SecureValueRecovery.BackupResponse.EnclaveNotFound enclaveNotFound ->
- logger.warn("Backup svr2 failed: EnclaveNotFound");
- case SecureValueRecovery.BackupResponse.ExposeFailure exposeFailure ->
- logger.warn("Backup svr2 failed: ExposeFailure");
- case SecureValueRecovery.BackupResponse.ApplicationError error ->
- throw new IOException(error.getException());
- case SecureValueRecovery.BackupResponse.NetworkError error -> throw error.getException();
- case null, default -> throw new AssertionError("Unexpected response");
+ }
+ if (exception != null) {
+ throw exception;
}
}
}
public void removeRegistrationLockPin() throws IOException {
- final var deleteResponse = secureValueRecoveryV2.deleteData();
- switch (deleteResponse) {
- case SecureValueRecovery.DeleteResponse.Success success -> {
+ IOException exception = null;
+ for (final var secureValueRecovery : secureValueRecoveries) {
+ try {
+ final var deleteResponse = secureValueRecovery.deleteData();
+ switch (deleteResponse) {
+ case SecureValueRecovery.DeleteResponse.Success success -> {
+ }
+ case SecureValueRecovery.DeleteResponse.ServerRejected serverRejected ->
+ logger.warn("Delete svr2 failed: ServerRejected");
+ case SecureValueRecovery.DeleteResponse.EnclaveNotFound enclaveNotFound ->
+ logger.warn("Delete svr2 failed: EnclaveNotFound");
+ case SecureValueRecovery.DeleteResponse.ApplicationError error ->
+ throw new IOException(error.getException());
+ case SecureValueRecovery.DeleteResponse.NetworkError error -> throw error.getException();
+ case null, default -> throw new AssertionError("Unexpected response");
+ }
+ } catch (IOException e) {
+ exception = e;
}
- case SecureValueRecovery.DeleteResponse.ServerRejected serverRejected ->
- logger.warn("Delete svr2 failed: ServerRejected");
- case SecureValueRecovery.DeleteResponse.EnclaveNotFound enclaveNotFound ->
- logger.warn("Delete svr2 failed: EnclaveNotFound");
- case SecureValueRecovery.DeleteResponse.ApplicationError error ->
- throw new IOException(error.getException());
- case SecureValueRecovery.DeleteResponse.NetworkError error -> throw error.getException();
- case null, default -> throw new AssertionError("Unexpected response");
+ }
+ if (exception != null) {
+ throw exception;
}
}
public SecureValueRecovery.RestoreResponse.Success getRegistrationLockData(
- String pin, LockedException e
+ String pin, LockedException lockedException
) throws IOException, IncorrectPinException {
- var svr2Credentials = e.getSvr2Credentials();
+ var svr2Credentials = lockedException.getSvr2Credentials();
if (svr2Credentials != null) {
- return getRegistrationLockData(secureValueRecoveryV2, svr2Credentials, pin);
+ IOException exception = null;
+ for (final var secureValueRecovery : secureValueRecoveries) {
+ try {
+ return getRegistrationLockData(secureValueRecovery, svr2Credentials, pin);
+ } catch (IOException e) {
+ exception = e;
+ }
+ }
+ if (exception != null) {
+ throw exception;
+ }
}
return null;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.services.ProfileService;
-import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV2;
+import org.whispersystems.signalservice.api.svr.SecureValueRecovery;
import org.whispersystems.signalservice.api.util.CredentialsProvider;
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
import org.whispersystems.signalservice.api.websocket.WebSocketFactory;
import org.whispersystems.signalservice.internal.push.PushServiceSocket;
import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
+import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;
private SignalServiceMessageReceiver messageReceiver;
private SignalServiceMessageSender messageSender;
- private SecureValueRecoveryV2 secureValueRecoveryV2;
+ private List<SecureValueRecovery> secureValueRecoveryV2;
private ProfileService profileService;
private SignalServiceCipher cipher;
pushServiceSocket));
}
- public SecureValueRecoveryV2 getSecureValueRecoveryV2() {
+ public List<SecureValueRecovery> getSecureValueRecoveryV2() {
return getOrCreate(() -> secureValueRecoveryV2,
- () -> secureValueRecoveryV2 = getAccountManager().getSecureValueRecoveryV2(serviceEnvironmentConfig.svr2Mrenclave()));
+ () -> secureValueRecoveryV2 = serviceEnvironmentConfig.svr2Mrenclaves()
+ .stream()
+ .map(mr -> (SecureValueRecovery) getAccountManager().getSecureValueRecoveryV2(mr))
+ .toList());
}
public ProfileService getProfileService() {