mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 18:40:39 +00:00
Use a new SVR2 enclave.
This commit is contained in:
parent
2535cd9c2c
commit
4dcdffda0a
7 changed files with 99 additions and 61 deletions
|
@ -20,12 +20,15 @@ import java.util.Optional;
|
||||||
import okhttp3.Dns;
|
import okhttp3.Dns;
|
||||||
import okhttp3.Interceptor;
|
import okhttp3.Interceptor;
|
||||||
|
|
||||||
|
import static org.asamk.signal.manager.api.ServiceEnvironment.LIVE;
|
||||||
|
|
||||||
class LiveConfig {
|
class LiveConfig {
|
||||||
|
|
||||||
private static final byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder()
|
private static final byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder()
|
||||||
.decode("BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF");
|
.decode("BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF");
|
||||||
private static final String CDSI_MRENCLAVE = "0f6fd79cdfdaa5b2e6337f534d3baf999318b0c462a7ac1f41297a3e4b424a57";
|
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 URL = "https://chat.signal.org";
|
||||||
private static final String CDN_URL = "https://cdn.signal.org";
|
private static final String CDN_URL = "https://cdn.signal.org";
|
||||||
|
@ -69,12 +72,12 @@ class LiveConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getCdsiMrenclave() {
|
static ServiceEnvironmentConfig getServiceEnvironmentConfig(List<Interceptor> interceptors) {
|
||||||
return CDSI_MRENCLAVE;
|
return new ServiceEnvironmentConfig(LIVE,
|
||||||
}
|
createDefaultServiceConfiguration(interceptors),
|
||||||
|
getUnidentifiedSenderTrustRoot(),
|
||||||
static String getSvr2Mrenclave() {
|
CDSI_MRENCLAVE,
|
||||||
return SVR2_MRENCLAVE;
|
List.of(SVR2_MRENCLAVE, SVR2_MRENCLAVE_DEPRECATED));
|
||||||
}
|
}
|
||||||
|
|
||||||
private LiveConfig() {
|
private LiveConfig() {
|
||||||
|
|
|
@ -43,16 +43,8 @@ public class ServiceConfig {
|
||||||
final var interceptors = List.of(userAgentInterceptor);
|
final var interceptors = List.of(userAgentInterceptor);
|
||||||
|
|
||||||
return switch (serviceEnvironment) {
|
return switch (serviceEnvironment) {
|
||||||
case LIVE -> new ServiceEnvironmentConfig(serviceEnvironment,
|
case LIVE -> LiveConfig.getServiceEnvironmentConfig(interceptors);
|
||||||
LiveConfig.createDefaultServiceConfiguration(interceptors),
|
case STAGING -> StagingConfig.getServiceEnvironmentConfig(interceptors);
|
||||||
LiveConfig.getUnidentifiedSenderTrustRoot(),
|
|
||||||
LiveConfig.getCdsiMrenclave(),
|
|
||||||
LiveConfig.getSvr2Mrenclave());
|
|
||||||
case STAGING -> new ServiceEnvironmentConfig(serviceEnvironment,
|
|
||||||
StagingConfig.createDefaultServiceConfiguration(interceptors),
|
|
||||||
StagingConfig.getUnidentifiedSenderTrustRoot(),
|
|
||||||
StagingConfig.getCdsiMrenclave(),
|
|
||||||
StagingConfig.getSvr2Mrenclave());
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,12 @@ import org.asamk.signal.manager.api.ServiceEnvironment;
|
||||||
import org.signal.libsignal.protocol.ecc.ECPublicKey;
|
import org.signal.libsignal.protocol.ecc.ECPublicKey;
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public record ServiceEnvironmentConfig(
|
public record ServiceEnvironmentConfig(
|
||||||
ServiceEnvironment type,
|
ServiceEnvironment type,
|
||||||
SignalServiceConfiguration signalServiceConfiguration,
|
SignalServiceConfiguration signalServiceConfiguration,
|
||||||
ECPublicKey unidentifiedSenderTrustRoot,
|
ECPublicKey unidentifiedSenderTrustRoot,
|
||||||
String cdsiMrenclave,
|
String cdsiMrenclave,
|
||||||
String svr2Mrenclave
|
List<String> svr2Mrenclaves
|
||||||
) {}
|
) {}
|
||||||
|
|
|
@ -20,12 +20,15 @@ import java.util.Optional;
|
||||||
import okhttp3.Dns;
|
import okhttp3.Dns;
|
||||||
import okhttp3.Interceptor;
|
import okhttp3.Interceptor;
|
||||||
|
|
||||||
|
import static org.asamk.signal.manager.api.ServiceEnvironment.STAGING;
|
||||||
|
|
||||||
class StagingConfig {
|
class StagingConfig {
|
||||||
|
|
||||||
private static final byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder()
|
private static final byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder()
|
||||||
.decode("BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx");
|
.decode("BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx");
|
||||||
private static final String CDSI_MRENCLAVE = "0f6fd79cdfdaa5b2e6337f534d3baf999318b0c462a7ac1f41297a3e4b424a57";
|
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 URL = "https://chat.staging.signal.org";
|
||||||
private static final String CDN_URL = "https://cdn-staging.signal.org";
|
private static final String CDN_URL = "https://cdn-staging.signal.org";
|
||||||
|
@ -69,12 +72,12 @@ class StagingConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getCdsiMrenclave() {
|
static ServiceEnvironmentConfig getServiceEnvironmentConfig(List<Interceptor> interceptors) {
|
||||||
return CDSI_MRENCLAVE;
|
return new ServiceEnvironmentConfig(STAGING,
|
||||||
}
|
createDefaultServiceConfiguration(interceptors),
|
||||||
|
getUnidentifiedSenderTrustRoot(),
|
||||||
static String getSvr2Mrenclave() {
|
CDSI_MRENCLAVE,
|
||||||
return SVR2_MRENCLAVE;
|
List.of(SVR2_MRENCLAVE, SVR2_MRENCLAVE_DEPRECATED));
|
||||||
}
|
}
|
||||||
|
|
||||||
private StagingConfig() {
|
private StagingConfig() {
|
||||||
|
|
|
@ -5,39 +5,49 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.signalservice.api.kbs.MasterKey;
|
import org.whispersystems.signalservice.api.kbs.MasterKey;
|
||||||
import org.whispersystems.signalservice.api.svr.SecureValueRecovery;
|
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.AuthCredentials;
|
||||||
import org.whispersystems.signalservice.internal.push.LockedException;
|
import org.whispersystems.signalservice.internal.push.LockedException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class PinHelper {
|
public class PinHelper {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(PinHelper.class);
|
private static final Logger logger = LoggerFactory.getLogger(PinHelper.class);
|
||||||
|
|
||||||
private final SecureValueRecoveryV2 secureValueRecoveryV2;
|
private final List<SecureValueRecovery> secureValueRecoveries;
|
||||||
|
|
||||||
public PinHelper(final SecureValueRecoveryV2 secureValueRecoveryV2) {
|
public PinHelper(final List<SecureValueRecovery> secureValueRecoveries) {
|
||||||
this.secureValueRecoveryV2 = secureValueRecoveryV2;
|
this.secureValueRecoveries = secureValueRecoveries;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRegistrationLockPin(
|
public void setRegistrationLockPin(
|
||||||
String pin, MasterKey masterKey
|
String pin, MasterKey masterKey
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
final var backupResponse = secureValueRecoveryV2.setPin(pin, masterKey).execute();
|
IOException exception = null;
|
||||||
switch (backupResponse) {
|
for (final var secureValueRecovery : secureValueRecoveries) {
|
||||||
case SecureValueRecovery.BackupResponse.Success success -> {
|
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");
|
if (exception != null) {
|
||||||
case SecureValueRecovery.BackupResponse.EnclaveNotFound enclaveNotFound ->
|
throw exception;
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,27 +56,47 @@ public class PinHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeRegistrationLockPin() throws IOException {
|
public void removeRegistrationLockPin() throws IOException {
|
||||||
final var deleteResponse = secureValueRecoveryV2.deleteData();
|
IOException exception = null;
|
||||||
switch (deleteResponse) {
|
for (final var secureValueRecovery : secureValueRecoveries) {
|
||||||
case SecureValueRecovery.DeleteResponse.Success success -> {
|
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");
|
if (exception != null) {
|
||||||
case SecureValueRecovery.DeleteResponse.EnclaveNotFound enclaveNotFound ->
|
throw exception;
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecureValueRecovery.RestoreResponse.Success getRegistrationLockData(
|
public SecureValueRecovery.RestoreResponse.Success getRegistrationLockData(
|
||||||
String pin, LockedException e
|
String pin, LockedException lockedException
|
||||||
) throws IOException, IncorrectPinException {
|
) throws IOException, IncorrectPinException {
|
||||||
var svr2Credentials = e.getSvr2Credentials();
|
var svr2Credentials = lockedException.getSvr2Credentials();
|
||||||
if (svr2Credentials != null) {
|
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;
|
return null;
|
||||||
|
|
|
@ -45,6 +45,7 @@ import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException;
|
import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
|
import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
|
||||||
|
import org.whispersystems.signalservice.api.svr.SecureValueRecovery;
|
||||||
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse;
|
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse;
|
||||||
import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
|
import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
|
||||||
|
|
||||||
|
@ -90,7 +91,10 @@ public class RegistrationManagerImpl implements RegistrationManager {
|
||||||
userAgent,
|
userAgent,
|
||||||
groupsV2Operations,
|
groupsV2Operations,
|
||||||
ServiceConfig.AUTOMATIC_NETWORK_RETRY);
|
ServiceConfig.AUTOMATIC_NETWORK_RETRY);
|
||||||
final var secureValueRecoveryV2 = accountManager.getSecureValueRecoveryV2(serviceEnvironmentConfig.svr2Mrenclave());
|
final var secureValueRecoveryV2 = serviceEnvironmentConfig.svr2Mrenclaves()
|
||||||
|
.stream()
|
||||||
|
.map(mr -> (SecureValueRecovery) accountManager.getSecureValueRecoveryV2(mr))
|
||||||
|
.toList();
|
||||||
this.pinHelper = new PinHelper(secureValueRecoveryV2);
|
this.pinHelper = new PinHelper(secureValueRecoveryV2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,14 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
|
||||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.services.ProfileService;
|
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.CredentialsProvider;
|
||||||
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
|
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
|
||||||
import org.whispersystems.signalservice.api.websocket.WebSocketFactory;
|
import org.whispersystems.signalservice.api.websocket.WebSocketFactory;
|
||||||
import org.whispersystems.signalservice.internal.push.PushServiceSocket;
|
import org.whispersystems.signalservice.internal.push.PushServiceSocket;
|
||||||
import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
|
import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
@ -50,7 +51,7 @@ public class SignalDependencies {
|
||||||
private SignalServiceMessageReceiver messageReceiver;
|
private SignalServiceMessageReceiver messageReceiver;
|
||||||
private SignalServiceMessageSender messageSender;
|
private SignalServiceMessageSender messageSender;
|
||||||
|
|
||||||
private SecureValueRecoveryV2 secureValueRecoveryV2;
|
private List<SecureValueRecovery> secureValueRecoveryV2;
|
||||||
private ProfileService profileService;
|
private ProfileService profileService;
|
||||||
private SignalServiceCipher cipher;
|
private SignalServiceCipher cipher;
|
||||||
|
|
||||||
|
@ -192,9 +193,12 @@ public class SignalDependencies {
|
||||||
pushServiceSocket));
|
pushServiceSocket));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecureValueRecoveryV2 getSecureValueRecoveryV2() {
|
public List<SecureValueRecovery> getSecureValueRecoveryV2() {
|
||||||
return getOrCreate(() -> secureValueRecoveryV2,
|
return getOrCreate(() -> secureValueRecoveryV2,
|
||||||
() -> secureValueRecoveryV2 = getAccountManager().getSecureValueRecoveryV2(serviceEnvironmentConfig.svr2Mrenclave()));
|
() -> secureValueRecoveryV2 = serviceEnvironmentConfig.svr2Mrenclaves()
|
||||||
|
.stream()
|
||||||
|
.map(mr -> (SecureValueRecovery) getAccountManager().getSecureValueRecoveryV2(mr))
|
||||||
|
.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProfileService getProfileService() {
|
public ProfileService getProfileService() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue