Refactor ServiceConfig and add sandbox config

This commit is contained in:
AsamK 2021-01-23 23:06:58 +01:00
parent 4eaec83594
commit 7d802fb8c5
15 changed files with 433 additions and 203 deletions

View file

@ -16,6 +16,9 @@
*/
package org.asamk.signal.manager;
import org.asamk.signal.manager.config.ServiceConfig;
import org.asamk.signal.manager.config.ServiceEnvironment;
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
import org.asamk.signal.manager.groups.GroupId;
import org.asamk.signal.manager.groups.GroupIdV1;
import org.asamk.signal.manager.groups.GroupIdV2;
@ -131,7 +134,6 @@ import org.whispersystems.signalservice.api.util.SleepTimer;
import org.whispersystems.signalservice.api.util.StreamDetails;
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
import org.whispersystems.signalservice.internal.contacts.crypto.Quote;
import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedQuoteException;
import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException;
@ -169,17 +171,15 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import static org.asamk.signal.manager.ServiceConfig.CDS_MRENCLAVE;
import static org.asamk.signal.manager.ServiceConfig.capabilities;
import static org.asamk.signal.manager.ServiceConfig.getIasKeyStore;
import static org.asamk.signal.manager.config.ServiceConfig.capabilities;
public class Manager implements Closeable {
private final static Logger logger = LoggerFactory.getLogger(Manager.class);
private final CertificateValidator certificateValidator = new CertificateValidator(ServiceConfig.getUnidentifiedSenderTrustRoot());
private final CertificateValidator certificateValidator;
private final SignalServiceConfiguration serviceConfiguration;
private final ServiceEnvironmentConfig serviceEnvironmentConfig;
private final String userAgent;
private SignalAccount account;
@ -202,16 +202,17 @@ public class Manager implements Closeable {
Manager(
SignalAccount account,
PathConfig pathConfig,
SignalServiceConfiguration serviceConfiguration,
ServiceEnvironmentConfig serviceEnvironmentConfig,
String userAgent
) {
this.account = account;
this.serviceConfiguration = serviceConfiguration;
this.serviceEnvironmentConfig = serviceEnvironmentConfig;
this.certificateValidator = new CertificateValidator(serviceEnvironmentConfig.getUnidentifiedSenderTrustRoot());
this.userAgent = userAgent;
this.groupsV2Operations = capabilities.isGv2() ? new GroupsV2Operations(ClientZkOperations.create(
serviceConfiguration)) : null;
serviceEnvironmentConfig.getSignalServiceConfiguration())) : null;
final SleepTimer timer = new UptimeSleepTimer();
this.accountManager = new SignalServiceAccountManager(serviceConfiguration,
this.accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
new DynamicCredentialsProvider(account.getUuid(),
account.getUsername(),
account.getPassword(),
@ -222,11 +223,18 @@ public class Manager implements Closeable {
ServiceConfig.AUTOMATIC_NETWORK_RETRY,
timer);
this.groupsV2Api = accountManager.getGroupsV2Api();
final KeyBackupService keyBackupService = ServiceConfig.createKeyBackupService(accountManager);
final KeyBackupService keyBackupService = accountManager.getKeyBackupService(ServiceConfig.getIasKeyStore(),
serviceEnvironmentConfig.getKeyBackupConfig().getEnclaveName(),
serviceEnvironmentConfig.getKeyBackupConfig().getServiceId(),
serviceEnvironmentConfig.getKeyBackupConfig().getMrenclave(),
10);
this.pinHelper = new PinHelper(keyBackupService);
this.clientZkProfileOperations = capabilities.isGv2() ? ClientZkOperations.create(serviceConfiguration)
.getProfileOperations() : null;
this.messageReceiver = new SignalServiceMessageReceiver(serviceConfiguration,
this.clientZkProfileOperations = capabilities.isGv2()
? ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration())
.getProfileOperations()
: null;
this.messageReceiver = new SignalServiceMessageReceiver(serviceEnvironmentConfig.getSignalServiceConfiguration(),
account.getUuid(),
account.getUsername(),
account.getPassword(),
@ -275,7 +283,7 @@ public class Manager implements Closeable {
}
public static Manager init(
String username, File settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent
String username, File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent
) throws IOException, NotRegisteredException {
PathConfig pathConfig = PathConfig.createDefault(settingsPath);
@ -289,7 +297,11 @@ public class Manager implements Closeable {
throw new NotRegisteredException();
}
return new Manager(account, pathConfig, serviceConfiguration, userAgent);
final ServiceEnvironmentConfig serviceEnvironmentConfig = ServiceConfig.getServiceEnvironmentConfig(
serviceEnvironment,
userAgent);
return new Manager(account, pathConfig, serviceEnvironmentConfig, userAgent);
}
public static List<String> getAllLocalUsernames(File settingsPath) {
@ -498,7 +510,7 @@ public class Manager implements Closeable {
private SignalServiceMessageSender createMessageSender() {
final ExecutorService executor = null;
return new SignalServiceMessageSender(serviceConfiguration,
return new SignalServiceMessageSender(serviceEnvironmentConfig.getSignalServiceConfiguration(),
account.getUuid(),
account.getUsername(),
account.getPassword(),
@ -1262,7 +1274,9 @@ public class Manager implements Closeable {
private Map<String, UUID> getRegisteredUsers(final Set<String> numbersMissingUuid) throws IOException {
try {
return accountManager.getRegisteredUsers(getIasKeyStore(), numbersMissingUuid, CDS_MRENCLAVE);
return accountManager.getRegisteredUsers(ServiceConfig.getIasKeyStore(),
numbersMissingUuid,
serviceEnvironmentConfig.getCdsMrenclave());
} catch (Quote.InvalidQuoteFormatException | UnauthenticatedQuoteException | SignatureException | UnauthenticatedResponseException | InvalidKeyException e) {
throw new IOException(e);
}

View file

@ -16,6 +16,9 @@
*/
package org.asamk.signal.manager;
import org.asamk.signal.manager.config.ServiceConfig;
import org.asamk.signal.manager.config.ServiceEnvironment;
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
import org.asamk.signal.manager.storage.SignalAccount;
import org.asamk.signal.manager.util.KeyUtils;
import org.signal.zkgroup.InvalidInputException;
@ -31,7 +34,6 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.util.SleepTimer;
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
import java.io.File;
@ -43,7 +45,7 @@ public class ProvisioningManager {
private final static Logger logger = LoggerFactory.getLogger(ProvisioningManager.class);
private final PathConfig pathConfig;
private final SignalServiceConfiguration serviceConfiguration;
private final ServiceEnvironmentConfig serviceEnvironmentConfig;
private final String userAgent;
private final SignalServiceAccountManager accountManager;
@ -51,9 +53,9 @@ public class ProvisioningManager {
private final int registrationId;
private final String password;
public ProvisioningManager(File settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent) {
this.pathConfig = PathConfig.createDefault(settingsPath);
this.serviceConfiguration = serviceConfiguration;
ProvisioningManager(PathConfig pathConfig, ServiceEnvironmentConfig serviceEnvironmentConfig, String userAgent) {
this.pathConfig = pathConfig;
this.serviceEnvironmentConfig = serviceEnvironmentConfig;
this.userAgent = userAgent;
identityKey = KeyUtils.generateIdentityKeyPair();
@ -62,11 +64,11 @@ public class ProvisioningManager {
final SleepTimer timer = new UptimeSleepTimer();
GroupsV2Operations groupsV2Operations;
try {
groupsV2Operations = new GroupsV2Operations(ClientZkOperations.create(serviceConfiguration));
groupsV2Operations = new GroupsV2Operations(ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration()));
} catch (Throwable ignored) {
groupsV2Operations = null;
}
accountManager = new SignalServiceAccountManager(serviceConfiguration,
accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
new DynamicCredentialsProvider(null, null, password, null, SignalServiceAddress.DEFAULT_DEVICE_ID),
userAgent,
groupsV2Operations,
@ -74,6 +76,18 @@ public class ProvisioningManager {
timer);
}
public static ProvisioningManager init(
File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent
) {
PathConfig pathConfig = PathConfig.createDefault(settingsPath);
final ServiceEnvironmentConfig serviceConfiguration = ServiceConfig.getServiceEnvironmentConfig(
serviceEnvironment,
userAgent);
return new ProvisioningManager(pathConfig, serviceConfiguration, userAgent);
}
public String getDeviceLinkUri() throws TimeoutException, IOException {
String deviceUuid = accountManager.getNewDeviceUuid();
@ -120,7 +134,7 @@ public class ProvisioningManager {
profileKey)) {
account.save();
try (Manager m = new Manager(account, pathConfig, serviceConfiguration, userAgent)) {
try (Manager m = new Manager(account, pathConfig, serviceEnvironmentConfig, userAgent)) {
try {
m.refreshPreKeys();

View file

@ -16,6 +16,9 @@
*/
package org.asamk.signal.manager;
import org.asamk.signal.manager.config.ServiceConfig;
import org.asamk.signal.manager.config.ServiceEnvironment;
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
import org.asamk.signal.manager.helper.PinHelper;
import org.asamk.signal.manager.storage.SignalAccount;
import org.asamk.signal.manager.util.KeyUtils;
@ -28,11 +31,12 @@ import org.whispersystems.signalservice.api.KeyBackupService;
import org.whispersystems.signalservice.api.KeyBackupServicePinException;
import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.util.SleepTimer;
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
import org.whispersystems.signalservice.internal.push.LockedException;
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse;
import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
@ -46,7 +50,7 @@ public class RegistrationManager implements Closeable {
private SignalAccount account;
private final PathConfig pathConfig;
private final SignalServiceConfiguration serviceConfiguration;
private final ServiceEnvironmentConfig serviceEnvironmentConfig;
private final String userAgent;
private final SignalServiceAccountManager accountManager;
@ -55,31 +59,49 @@ public class RegistrationManager implements Closeable {
public RegistrationManager(
SignalAccount account,
PathConfig pathConfig,
SignalServiceConfiguration serviceConfiguration,
ServiceEnvironmentConfig serviceEnvironmentConfig,
String userAgent
) {
this.account = account;
this.pathConfig = pathConfig;
this.serviceConfiguration = serviceConfiguration;
this.serviceEnvironmentConfig = serviceEnvironmentConfig;
this.userAgent = userAgent;
final SleepTimer timer = new UptimeSleepTimer();
this.accountManager = new SignalServiceAccountManager(serviceConfiguration, new DynamicCredentialsProvider(
// Using empty UUID, because registering doesn't work otherwise
null,
account.getUsername(),
account.getPassword(),
account.getSignalingKey(),
SignalServiceAddress.DEFAULT_DEVICE_ID), userAgent, null, ServiceConfig.AUTOMATIC_NETWORK_RETRY, timer);
final KeyBackupService keyBackupService = ServiceConfig.createKeyBackupService(accountManager);
GroupsV2Operations groupsV2Operations;
try {
groupsV2Operations = new GroupsV2Operations(ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration()));
} catch (Throwable ignored) {
groupsV2Operations = null;
}
this.accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
new DynamicCredentialsProvider(
// Using empty UUID, because registering doesn't work otherwise
null,
account.getUsername(),
account.getPassword(),
account.getSignalingKey(),
SignalServiceAddress.DEFAULT_DEVICE_ID),
userAgent,
groupsV2Operations,
ServiceConfig.AUTOMATIC_NETWORK_RETRY,
timer);
final KeyBackupService keyBackupService = accountManager.getKeyBackupService(ServiceConfig.getIasKeyStore(),
serviceEnvironmentConfig.getKeyBackupConfig().getEnclaveName(),
serviceEnvironmentConfig.getKeyBackupConfig().getServiceId(),
serviceEnvironmentConfig.getKeyBackupConfig().getMrenclave(),
10);
this.pinHelper = new PinHelper(keyBackupService);
}
public static RegistrationManager init(
String username, File settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent
String username, File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent
) throws IOException {
PathConfig pathConfig = PathConfig.createDefault(settingsPath);
final ServiceEnvironmentConfig serviceConfiguration = ServiceConfig.getServiceEnvironmentConfig(
serviceEnvironment,
userAgent);
if (!SignalAccount.userExists(pathConfig.getDataPath(), username)) {
IdentityKeyPair identityKey = KeyUtils.generateIdentityKeyPair();
int registrationId = KeyHelper.generateRegistrationId(false);
@ -159,7 +181,7 @@ public class RegistrationManager implements Closeable {
account.getSignalProtocolStore().getIdentityKeyPair().getPublicKey(),
TrustLevel.TRUSTED_VERIFIED);
try (Manager m = new Manager(account, pathConfig, serviceConfiguration, userAgent)) {
try (Manager m = new Manager(account, pathConfig, serviceEnvironmentConfig, userAgent)) {
m.refreshPreKeys();

View file

@ -1,141 +0,0 @@
package org.asamk.signal.manager;
import org.bouncycastle.util.encoders.Hex;
import org.signal.zkgroup.ServerPublicParams;
import org.whispersystems.libsignal.InvalidKeyException;
import org.whispersystems.libsignal.ecc.Curve;
import org.whispersystems.libsignal.ecc.ECPublicKey;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.KeyBackupService;
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.account.AccountAttributes;
import org.whispersystems.signalservice.api.push.TrustStore;
import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl;
import org.whispersystems.signalservice.internal.configuration.SignalContactDiscoveryUrl;
import org.whispersystems.signalservice.internal.configuration.SignalKeyBackupServiceUrl;
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
import org.whispersystems.signalservice.internal.configuration.SignalServiceUrl;
import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import okhttp3.Dns;
import okhttp3.Interceptor;
public class ServiceConfig {
final static byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder()
.decode("BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF");
final static int PREKEY_MINIMUM_COUNT = 20;
final static int PREKEY_BATCH_SIZE = 100;
final static int MAX_ATTACHMENT_SIZE = 150 * 1024 * 1024;
final static long MAX_ENVELOPE_SIZE = 0;
final static long AVATAR_DOWNLOAD_FAILSAFE_MAX_SIZE = 10 * 1024 * 1024;
final static boolean AUTOMATIC_NETWORK_RETRY = true;
final static String CDS_MRENCLAVE = "c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15";
final static String KEY_BACKUP_ENCLAVE_NAME = "fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe";
final static byte[] KEY_BACKUP_SERVICE_ID = Hex.decode(
"fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe");
final static String KEY_BACKUP_MRENCLAVE = "a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87";
private final static String URL = "https://textsecure-service.whispersystems.org";
private final static String CDN_URL = "https://cdn.signal.org";
private final static String CDN2_URL = "https://cdn2.signal.org";
private final static String SIGNAL_CONTACT_DISCOVERY_URL = "https://api.directory.signal.org";
private final static String SIGNAL_KEY_BACKUP_URL = "https://api.backup.signal.org";
private final static String STORAGE_URL = "https://storage.signal.org";
private final static TrustStore TRUST_STORE = new WhisperTrustStore();
private final static TrustStore IAS_TRUST_STORE = new IasTrustStore();
private final static Optional<Dns> dns = Optional.absent();
private final static byte[] zkGroupServerPublicParams = Base64.getDecoder()
.decode("AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X0=");
static final AccountAttributes.Capabilities capabilities;
static {
boolean zkGroupAvailable;
try {
new ServerPublicParams(zkGroupServerPublicParams);
zkGroupAvailable = true;
} catch (Throwable ignored) {
zkGroupAvailable = false;
}
capabilities = new AccountAttributes.Capabilities(false, zkGroupAvailable, false, zkGroupAvailable);
}
public static SignalServiceConfiguration createDefaultServiceConfiguration(String userAgent) {
final Interceptor userAgentInterceptor = chain -> chain.proceed(chain.request()
.newBuilder()
.header("User-Agent", userAgent)
.build());
final List<Interceptor> interceptors = List.of(userAgentInterceptor);
return new SignalServiceConfiguration(new SignalServiceUrl[]{new SignalServiceUrl(URL, TRUST_STORE)},
makeSignalCdnUrlMapFor(new SignalCdnUrl[]{new SignalCdnUrl(CDN_URL, TRUST_STORE)},
new SignalCdnUrl[]{new SignalCdnUrl(CDN2_URL, TRUST_STORE)}),
new SignalContactDiscoveryUrl[]{new SignalContactDiscoveryUrl(SIGNAL_CONTACT_DISCOVERY_URL,
TRUST_STORE)},
new SignalKeyBackupServiceUrl[]{new SignalKeyBackupServiceUrl(SIGNAL_KEY_BACKUP_URL, TRUST_STORE)},
new SignalStorageUrl[]{new SignalStorageUrl(STORAGE_URL, TRUST_STORE)},
interceptors,
dns,
zkGroupServerPublicParams);
}
public static AccountAttributes.Capabilities getCapabilities() {
return capabilities;
}
static KeyStore getIasKeyStore() {
try {
TrustStore contactTrustStore = IAS_TRUST_STORE;
KeyStore keyStore = KeyStore.getInstance("BKS");
keyStore.load(contactTrustStore.getKeyStoreInputStream(),
contactTrustStore.getKeyStorePassword().toCharArray());
return keyStore;
} catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
static KeyBackupService createKeyBackupService(SignalServiceAccountManager accountManager) {
KeyStore keyStore = ServiceConfig.getIasKeyStore();
return accountManager.getKeyBackupService(keyStore,
ServiceConfig.KEY_BACKUP_ENCLAVE_NAME,
ServiceConfig.KEY_BACKUP_SERVICE_ID,
ServiceConfig.KEY_BACKUP_MRENCLAVE,
10);
}
static ECPublicKey getUnidentifiedSenderTrustRoot() {
try {
return Curve.decodePoint(UNIDENTIFIED_SENDER_TRUST_ROOT, 0);
} catch (InvalidKeyException e) {
throw new AssertionError(e);
}
}
private static Map<Integer, SignalCdnUrl[]> makeSignalCdnUrlMapFor(
SignalCdnUrl[] cdn0Urls, SignalCdnUrl[] cdn2Urls
) {
return Map.of(0, cdn0Urls, 2, cdn2Urls);
}
private ServiceConfig() {
}
}

View file

@ -1,4 +1,4 @@
package org.asamk.signal.manager;
package org.asamk.signal.manager.config;
import org.whispersystems.signalservice.api.push.TrustStore;

View file

@ -0,0 +1,26 @@
package org.asamk.signal.manager.config;
public class KeyBackupConfig {
private final String enclaveName;
private final byte[] serviceId;
private final String mrenclave;
public KeyBackupConfig(final String enclaveName, final byte[] serviceId, final String mrenclave) {
this.enclaveName = enclaveName;
this.serviceId = serviceId;
this.mrenclave = mrenclave;
}
public String getEnclaveName() {
return enclaveName;
}
public byte[] getServiceId() {
return serviceId;
}
public String getMrenclave() {
return mrenclave;
}
}

View file

@ -0,0 +1,82 @@
package org.asamk.signal.manager.config;
import org.bouncycastle.util.encoders.Hex;
import org.whispersystems.libsignal.InvalidKeyException;
import org.whispersystems.libsignal.ecc.Curve;
import org.whispersystems.libsignal.ecc.ECPublicKey;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.push.TrustStore;
import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl;
import org.whispersystems.signalservice.internal.configuration.SignalContactDiscoveryUrl;
import org.whispersystems.signalservice.internal.configuration.SignalKeyBackupServiceUrl;
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
import org.whispersystems.signalservice.internal.configuration.SignalServiceUrl;
import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import okhttp3.Dns;
import okhttp3.Interceptor;
class LiveConfig {
private final static byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder()
.decode("BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF");
private final static String CDS_MRENCLAVE = "c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15";
private final static String KEY_BACKUP_ENCLAVE_NAME = "fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe";
private final static byte[] KEY_BACKUP_SERVICE_ID = Hex.decode(
"fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe");
private final static String KEY_BACKUP_MRENCLAVE = "a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87";
private final static String URL = "https://textsecure-service.whispersystems.org";
private final static String CDN_URL = "https://cdn.signal.org";
private final static String CDN2_URL = "https://cdn2.signal.org";
private final static String SIGNAL_CONTACT_DISCOVERY_URL = "https://api.directory.signal.org";
private final static String SIGNAL_KEY_BACKUP_URL = "https://api.backup.signal.org";
private final static String STORAGE_URL = "https://storage.signal.org";
private final static TrustStore TRUST_STORE = new WhisperTrustStore();
private final static Optional<Dns> dns = Optional.absent();
private final static byte[] zkGroupServerPublicParams = Base64.getDecoder()
.decode("AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X0=");
static SignalServiceConfiguration createDefaultServiceConfiguration(
final List<Interceptor> interceptors
) {
return new SignalServiceConfiguration(new SignalServiceUrl[]{new SignalServiceUrl(URL, TRUST_STORE)},
Map.of(0,
new SignalCdnUrl[]{new SignalCdnUrl(CDN_URL, TRUST_STORE)},
2,
new SignalCdnUrl[]{new SignalCdnUrl(CDN2_URL, TRUST_STORE)}),
new SignalContactDiscoveryUrl[]{new SignalContactDiscoveryUrl(SIGNAL_CONTACT_DISCOVERY_URL,
TRUST_STORE)},
new SignalKeyBackupServiceUrl[]{new SignalKeyBackupServiceUrl(SIGNAL_KEY_BACKUP_URL, TRUST_STORE)},
new SignalStorageUrl[]{new SignalStorageUrl(STORAGE_URL, TRUST_STORE)},
interceptors,
dns,
zkGroupServerPublicParams);
}
static ECPublicKey getUnidentifiedSenderTrustRoot() {
try {
return Curve.decodePoint(UNIDENTIFIED_SENDER_TRUST_ROOT, 0);
} catch (InvalidKeyException e) {
throw new AssertionError(e);
}
}
static KeyBackupConfig createKeyBackupConfig() {
return new KeyBackupConfig(KEY_BACKUP_ENCLAVE_NAME, KEY_BACKUP_SERVICE_ID, KEY_BACKUP_MRENCLAVE);
}
static String getCdsMrenclave() {
return CDS_MRENCLAVE;
}
private LiveConfig() {
}
}

View file

@ -0,0 +1,82 @@
package org.asamk.signal.manager.config;
import org.bouncycastle.util.encoders.Hex;
import org.whispersystems.libsignal.InvalidKeyException;
import org.whispersystems.libsignal.ecc.Curve;
import org.whispersystems.libsignal.ecc.ECPublicKey;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.push.TrustStore;
import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl;
import org.whispersystems.signalservice.internal.configuration.SignalContactDiscoveryUrl;
import org.whispersystems.signalservice.internal.configuration.SignalKeyBackupServiceUrl;
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
import org.whispersystems.signalservice.internal.configuration.SignalServiceUrl;
import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import okhttp3.Dns;
import okhttp3.Interceptor;
class SandboxConfig {
private final static byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder()
.decode("BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx");
private final static String CDS_MRENCLAVE = "c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15";
private final static String KEY_BACKUP_ENCLAVE_NAME = "823a3b2c037ff0cbe305cc48928cfcc97c9ed4a8ca6d49af6f7d6981fb60a4e9";
private final static byte[] KEY_BACKUP_SERVICE_ID = Hex.decode(
"038c40bbbacdc873caa81ac793bb75afde6dfe436a99ab1f15e3f0cbb7434ced");
private final static String KEY_BACKUP_MRENCLAVE = "a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87";
private final static String URL = "https://textsecure-service-staging.whispersystems.org";
private final static String CDN_URL = "https://cdn-staging.signal.org";
private final static String CDN2_URL = "https://cdn2-staging.signal.org";
private final static String SIGNAL_CONTACT_DISCOVERY_URL = "https://api-staging.directory.signal.org";
private final static String SIGNAL_KEY_BACKUP_URL = "https://api-staging.backup.signal.org";
private final static String STORAGE_URL = "https://storage-staging.signal.org";
private final static TrustStore TRUST_STORE = new WhisperTrustStore();
private final static Optional<Dns> dns = Optional.absent();
private final static byte[] zkGroupServerPublicParams = Base64.getDecoder()
.decode("ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdls=");
static SignalServiceConfiguration createDefaultServiceConfiguration(
final List<Interceptor> interceptors
) {
return new SignalServiceConfiguration(new SignalServiceUrl[]{new SignalServiceUrl(URL, TRUST_STORE)},
Map.of(0,
new SignalCdnUrl[]{new SignalCdnUrl(CDN_URL, TRUST_STORE)},
2,
new SignalCdnUrl[]{new SignalCdnUrl(CDN2_URL, TRUST_STORE)}),
new SignalContactDiscoveryUrl[]{new SignalContactDiscoveryUrl(SIGNAL_CONTACT_DISCOVERY_URL,
TRUST_STORE)},
new SignalKeyBackupServiceUrl[]{new SignalKeyBackupServiceUrl(SIGNAL_KEY_BACKUP_URL, TRUST_STORE)},
new SignalStorageUrl[]{new SignalStorageUrl(STORAGE_URL, TRUST_STORE)},
interceptors,
dns,
zkGroupServerPublicParams);
}
static ECPublicKey getUnidentifiedSenderTrustRoot() {
try {
return Curve.decodePoint(UNIDENTIFIED_SENDER_TRUST_ROOT, 0);
} catch (InvalidKeyException e) {
throw new AssertionError(e);
}
}
static KeyBackupConfig createKeyBackupConfig() {
return new KeyBackupConfig(KEY_BACKUP_ENCLAVE_NAME, KEY_BACKUP_SERVICE_ID, KEY_BACKUP_MRENCLAVE);
}
static String getCdsMrenclave() {
return CDS_MRENCLAVE;
}
private SandboxConfig() {
}
}

View file

@ -0,0 +1,85 @@
package org.asamk.signal.manager.config;
import org.signal.zkgroup.internal.Native;
import org.whispersystems.signalservice.api.account.AccountAttributes;
import org.whispersystems.signalservice.api.push.TrustStore;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.List;
import okhttp3.Interceptor;
public class ServiceConfig {
public final static int PREKEY_MINIMUM_COUNT = 20;
public final static int PREKEY_BATCH_SIZE = 100;
public final static int MAX_ATTACHMENT_SIZE = 150 * 1024 * 1024;
public final static long MAX_ENVELOPE_SIZE = 0;
public final static long AVATAR_DOWNLOAD_FAILSAFE_MAX_SIZE = 10 * 1024 * 1024;
public final static boolean AUTOMATIC_NETWORK_RETRY = true;
private final static KeyStore iasKeyStore;
public static final AccountAttributes.Capabilities capabilities;
static {
boolean zkGroupAvailable;
try {
Native.serverPublicParamsCheckValidContentsJNI(new byte[]{});
zkGroupAvailable = true;
} catch (Throwable ignored) {
zkGroupAvailable = false;
}
capabilities = new AccountAttributes.Capabilities(false, zkGroupAvailable, false, zkGroupAvailable);
try {
TrustStore contactTrustStore = new IasTrustStore();
KeyStore keyStore = KeyStore.getInstance("BKS");
keyStore.load(contactTrustStore.getKeyStoreInputStream(),
contactTrustStore.getKeyStorePassword().toCharArray());
iasKeyStore = keyStore;
} catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
public static AccountAttributes.Capabilities getCapabilities() {
return capabilities;
}
public static KeyStore getIasKeyStore() {
return iasKeyStore;
}
public static ServiceEnvironmentConfig getServiceEnvironmentConfig(
ServiceEnvironment serviceEnvironment, String userAgent
) {
final Interceptor userAgentInterceptor = chain -> chain.proceed(chain.request()
.newBuilder()
.header("User-Agent", userAgent)
.build());
final List<Interceptor> interceptors = List.of(userAgentInterceptor);
switch (serviceEnvironment) {
case LIVE:
return new ServiceEnvironmentConfig(LiveConfig.createDefaultServiceConfiguration(interceptors),
LiveConfig.getUnidentifiedSenderTrustRoot(),
LiveConfig.createKeyBackupConfig(),
LiveConfig.getCdsMrenclave());
case SANDBOX:
return new ServiceEnvironmentConfig(SandboxConfig.createDefaultServiceConfiguration(interceptors),
SandboxConfig.getUnidentifiedSenderTrustRoot(),
SandboxConfig.createKeyBackupConfig(),
SandboxConfig.getCdsMrenclave());
default:
throw new IllegalArgumentException("Unsupported environment");
}
}
}

View file

@ -0,0 +1,6 @@
package org.asamk.signal.manager.config;
public enum ServiceEnvironment {
LIVE,
SANDBOX,
}

View file

@ -0,0 +1,43 @@
package org.asamk.signal.manager.config;
import org.whispersystems.libsignal.ecc.ECPublicKey;
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
public class ServiceEnvironmentConfig {
private final SignalServiceConfiguration signalServiceConfiguration;
private final ECPublicKey unidentifiedSenderTrustRoot;
private final KeyBackupConfig keyBackupConfig;
private final String cdsMrenclave;
public ServiceEnvironmentConfig(
final SignalServiceConfiguration signalServiceConfiguration,
final ECPublicKey unidentifiedSenderTrustRoot,
final KeyBackupConfig keyBackupConfig,
final String cdsMrenclave
) {
this.signalServiceConfiguration = signalServiceConfiguration;
this.unidentifiedSenderTrustRoot = unidentifiedSenderTrustRoot;
this.keyBackupConfig = keyBackupConfig;
this.cdsMrenclave = cdsMrenclave;
}
public SignalServiceConfiguration getSignalServiceConfiguration() {
return signalServiceConfiguration;
}
public ECPublicKey getUnidentifiedSenderTrustRoot() {
return unidentifiedSenderTrustRoot;
}
public KeyBackupConfig getKeyBackupConfig() {
return keyBackupConfig;
}
public String getCdsMrenclave() {
return cdsMrenclave;
}
}

View file

@ -1,4 +1,4 @@
package org.asamk.signal.manager;
package org.asamk.signal.manager.config;
import org.whispersystems.signalservice.api.push.TrustStore;