mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 10:05:15 +00:00
clean up: signal service protocols
This commit is contained in:
parent
88bbc0b677
commit
1db9ccdf27
@ -81,7 +81,6 @@ import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.notifications.OptimizedMessageNotifier;
|
||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.service.LocalBackupListener;
|
||||
|
@ -2,11 +2,8 @@ package org.thoughtcrime.securesms.dependencies;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.api.SignalServiceMessageReceiver;
|
||||
import org.session.libsignal.service.api.SignalServiceMessageSender;
|
||||
import org.session.libsignal.service.api.util.CredentialsProvider;
|
||||
import org.session.libsignal.service.api.websocket.ConnectivityListener;
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
@ -24,15 +21,12 @@ import org.thoughtcrime.securesms.jobs.SendDeliveryReceiptJob;
|
||||
import org.thoughtcrime.securesms.jobs.SendReadReceiptJob;
|
||||
import org.thoughtcrime.securesms.jobs.TypingSendJob;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
|
||||
import org.session.libsignal.utilities.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.api.SessionProtocolImpl;
|
||||
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
|
||||
import org.thoughtcrime.securesms.util.RealtimeSleepTimer;
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import network.loki.messenger.BuildConfig;
|
||||
|
||||
@Module(complete = false, injects = {PushGroupSendJob.class,
|
||||
PushTextSendJob.class,
|
||||
@ -52,8 +46,6 @@ import network.loki.messenger.BuildConfig;
|
||||
|
||||
public class SignalCommunicationModule {
|
||||
|
||||
private static final String TAG = SignalCommunicationModule.class.getSimpleName();
|
||||
|
||||
private final Context context;
|
||||
|
||||
private SignalServiceMessageSender messageSender;
|
||||
@ -66,8 +58,7 @@ public class SignalCommunicationModule {
|
||||
@Provides
|
||||
public synchronized SignalServiceMessageSender provideSignalMessageSender() {
|
||||
if (this.messageSender == null) {
|
||||
this.messageSender = new SignalServiceMessageSender(new DynamicCredentialsProvider(context),
|
||||
new SignalProtocolStoreImpl(context),
|
||||
this.messageSender = new SignalServiceMessageSender(new SignalProtocolStoreImpl(context),
|
||||
TextSecurePreferences.getLocalNumber(context),
|
||||
DatabaseFactory.getLokiAPIDatabase(context),
|
||||
DatabaseFactory.getLokiThreadDatabase(context),
|
||||
@ -89,54 +80,4 @@ public class SignalCommunicationModule {
|
||||
|
||||
return this.messageReceiver;
|
||||
}
|
||||
|
||||
private static class DynamicCredentialsProvider implements CredentialsProvider {
|
||||
|
||||
private final Context context;
|
||||
|
||||
private DynamicCredentialsProvider(Context context) {
|
||||
this.context = context.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUser() {
|
||||
return TextSecurePreferences.getLocalNumber(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return TextSecurePreferences.getPushServerPassword(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSignalingKey() {
|
||||
return TextSecurePreferences.getSignalingKey(context);
|
||||
}
|
||||
}
|
||||
|
||||
private class PipeConnectivityListener implements ConnectivityListener {
|
||||
|
||||
@Override
|
||||
public void onConnected() {
|
||||
Log.i(TAG, "onConnected()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnecting() {
|
||||
Log.i(TAG, "onConnecting()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected() {
|
||||
Log.w(TAG, "onDisconnected()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailure() {
|
||||
Log.w(TAG, "onAuthenticationFailure()");
|
||||
TextSecurePreferences.setUnauthorizedReceived(context, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.session.libsignal.service.api.util.InvalidNumberException;
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos.GroupContext;
|
||||
|
||||
import java.util.Collection;
|
||||
@ -137,7 +136,6 @@ public class GroupManager {
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name,
|
||||
@NonNull Set<Recipient> admins)
|
||||
throws InvalidNumberException
|
||||
{
|
||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
final Set<Address> memberAddresses = getMemberAddresses(members);
|
||||
|
@ -1,29 +0,0 @@
|
||||
package org.thoughtcrime.securesms.push;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
import org.session.libsignal.service.api.push.TrustStore;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public class DomainFrontingTrustStore implements TrustStore {
|
||||
|
||||
private final Context context;
|
||||
|
||||
public DomainFrontingTrustStore(Context context) {
|
||||
this.context = context.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getKeyStoreInputStream() {
|
||||
return context.getResources().openRawResource(R.raw.censorship_fronting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyStorePassword() {
|
||||
return "whisper";
|
||||
}
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package org.thoughtcrime.securesms.push;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
import org.session.libsignal.service.api.push.TrustStore;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public class IasTrustStore implements TrustStore {
|
||||
|
||||
private final Context context;
|
||||
|
||||
public IasTrustStore(Context context) {
|
||||
this.context = context.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getKeyStoreInputStream() {
|
||||
return context.getResources().openRawResource(R.raw.ias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyStorePassword() {
|
||||
return "whisper";
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package org.thoughtcrime.securesms.push;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.SecurityEvent;
|
||||
import org.session.libsignal.service.api.SignalServiceMessageSender;
|
||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||
|
||||
public class MessageSenderEventListener implements SignalServiceMessageSender.EventListener {
|
||||
private final Context context;
|
||||
|
||||
public MessageSenderEventListener(Context context) {
|
||||
this.context = context.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSecurityEvent(SignalServiceAddress textSecureAddress) {
|
||||
SecurityEvent.broadcastSecurityUpdateEvent(context);
|
||||
}
|
||||
}
|
@ -1,171 +0,0 @@
|
||||
package org.thoughtcrime.securesms.push;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
import org.session.libsignal.service.api.push.TrustStore;
|
||||
import org.session.libsignal.service.internal.configuration.SignalCdnUrl;
|
||||
import org.session.libsignal.service.internal.configuration.SignalContactDiscoveryUrl;
|
||||
import org.session.libsignal.service.internal.configuration.SignalServiceConfiguration;
|
||||
import org.session.libsignal.service.internal.configuration.SignalServiceUrl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import network.loki.messenger.BuildConfig;
|
||||
import okhttp3.CipherSuite;
|
||||
import okhttp3.ConnectionSpec;
|
||||
import okhttp3.TlsVersion;
|
||||
|
||||
public class SignalServiceNetworkAccess {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = SignalServiceNetworkAccess.class.getSimpleName();
|
||||
|
||||
private static final String COUNTRY_CODE_EGYPT = "+20";
|
||||
private static final String COUNTRY_CODE_UAE = "+971";
|
||||
private static final String COUNTRY_CODE_OMAN = "+968";
|
||||
private static final String COUNTRY_CODE_QATAR = "+974";
|
||||
|
||||
private static final String SERVICE_REFLECTOR_HOST = "europe-west1-signal-cdn-reflector.cloudfunctions.net";
|
||||
|
||||
private static final ConnectionSpec GMAPS_CONNECTION_SPEC = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
||||
.tlsVersions(TlsVersion.TLS_1_2)
|
||||
.cipherSuites(CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA)
|
||||
.supportsTlsExtensions(true)
|
||||
.build();
|
||||
|
||||
private static final ConnectionSpec GMAIL_CONNECTION_SPEC = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
||||
.tlsVersions(TlsVersion.TLS_1_2)
|
||||
.cipherSuites(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA)
|
||||
.supportsTlsExtensions(true)
|
||||
.build();
|
||||
|
||||
private static final ConnectionSpec PLAY_CONNECTION_SPEC = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
||||
.tlsVersions(TlsVersion.TLS_1_2)
|
||||
.cipherSuites(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA)
|
||||
.supportsTlsExtensions(true)
|
||||
.build();
|
||||
|
||||
|
||||
private final Map<String, SignalServiceConfiguration> censorshipConfiguration;
|
||||
private final String[] censoredCountries;
|
||||
private final SignalServiceConfiguration uncensoredConfiguration;
|
||||
|
||||
public SignalServiceNetworkAccess(Context context) {
|
||||
|
||||
final TrustStore trustStore = new DomainFrontingTrustStore(context);
|
||||
final SignalServiceUrl baseGoogleService = new SignalServiceUrl("https://www.google.com/service", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalServiceUrl baseAndroidService = new SignalServiceUrl("https://android.clients.google.com/service", SERVICE_REFLECTOR_HOST, trustStore, PLAY_CONNECTION_SPEC);
|
||||
final SignalServiceUrl mapsOneAndroidService = new SignalServiceUrl("https://clients3.google.com/service", SERVICE_REFLECTOR_HOST, trustStore, GMAPS_CONNECTION_SPEC);
|
||||
final SignalServiceUrl mapsTwoAndroidService = new SignalServiceUrl("https://clients4.google.com/service", SERVICE_REFLECTOR_HOST, trustStore, GMAPS_CONNECTION_SPEC);
|
||||
final SignalServiceUrl mailAndroidService = new SignalServiceUrl("https://inbox.google.com/service", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalServiceUrl egyptGoogleService = new SignalServiceUrl("https://www.google.com.eg/service", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalServiceUrl uaeGoogleService = new SignalServiceUrl("https://www.google.com.ae/service", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalServiceUrl omanGoogleService = new SignalServiceUrl("https://www.google.com.om/service", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalServiceUrl qatarGoogleService = new SignalServiceUrl("https://www.google.com.qa/service", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
|
||||
final SignalCdnUrl baseGoogleCdn = new SignalCdnUrl("https://www.google.com/cdn", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalCdnUrl baseAndroidCdn = new SignalCdnUrl("https://android.clients.google.com/cdn", SERVICE_REFLECTOR_HOST, trustStore, PLAY_CONNECTION_SPEC);
|
||||
final SignalCdnUrl mapsOneAndroidCdn = new SignalCdnUrl("https://clients3.google.com/cdn", SERVICE_REFLECTOR_HOST, trustStore, GMAPS_CONNECTION_SPEC);
|
||||
final SignalCdnUrl mapsTwoAndroidCdn = new SignalCdnUrl("https://clients4.google.com/cdn", SERVICE_REFLECTOR_HOST, trustStore, GMAPS_CONNECTION_SPEC);
|
||||
final SignalCdnUrl mailAndroidCdn = new SignalCdnUrl("https://inbox.google.com/cdn", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalCdnUrl egyptGoogleCdn = new SignalCdnUrl("https://www.google.com.eg/cdn", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalCdnUrl uaeGoogleCdn = new SignalCdnUrl("https://www.google.com.ae/cdn", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalCdnUrl omanGoogleCdn = new SignalCdnUrl("https://www.google.com.om/cdn", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalCdnUrl qatarGoogleCdn = new SignalCdnUrl("https://www.google.com.qa/cdn", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
|
||||
final SignalContactDiscoveryUrl baseGoogleDiscovery = new SignalContactDiscoveryUrl("https://www.google.com/directory", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalContactDiscoveryUrl baseAndroidDiscovery = new SignalContactDiscoveryUrl("https://android.clients.google.com/directory", SERVICE_REFLECTOR_HOST, trustStore, PLAY_CONNECTION_SPEC);
|
||||
final SignalContactDiscoveryUrl mapsOneAndroidDiscovery = new SignalContactDiscoveryUrl("https://clients3.google.com/directory", SERVICE_REFLECTOR_HOST, trustStore, GMAPS_CONNECTION_SPEC);
|
||||
final SignalContactDiscoveryUrl mapsTwoAndroidDiscovery = new SignalContactDiscoveryUrl("https://clients4.google.com/directory", SERVICE_REFLECTOR_HOST, trustStore, GMAPS_CONNECTION_SPEC);
|
||||
final SignalContactDiscoveryUrl mailAndroidDiscovery = new SignalContactDiscoveryUrl("https://inbox.google.com/directory", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalContactDiscoveryUrl egyptGoogleDiscovery = new SignalContactDiscoveryUrl("https://www.google.com.eg/directory", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalContactDiscoveryUrl uaeGoogleDiscovery = new SignalContactDiscoveryUrl("https://www.google.com.ae/directory", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalContactDiscoveryUrl omanGoogleDiscovery = new SignalContactDiscoveryUrl("https://www.google.com.om/directory", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
final SignalContactDiscoveryUrl qatarGoogleDiscovery = new SignalContactDiscoveryUrl("https://www.google.com.qa/directory", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC);
|
||||
|
||||
|
||||
this.censorshipConfiguration = new HashMap<String, SignalServiceConfiguration>() {{
|
||||
put(COUNTRY_CODE_EGYPT, new SignalServiceConfiguration(new SignalServiceUrl[] {egyptGoogleService, baseGoogleService, baseAndroidService, mapsOneAndroidService, mapsTwoAndroidService, mailAndroidService},
|
||||
new SignalCdnUrl[] {egyptGoogleCdn, baseAndroidCdn, baseGoogleCdn, mapsOneAndroidCdn, mapsTwoAndroidCdn, mailAndroidCdn, mailAndroidCdn},
|
||||
new SignalContactDiscoveryUrl[] {egyptGoogleDiscovery, baseGoogleDiscovery, baseAndroidDiscovery, mapsOneAndroidDiscovery, mapsTwoAndroidDiscovery, mailAndroidDiscovery}));
|
||||
|
||||
put(COUNTRY_CODE_UAE, new SignalServiceConfiguration(new SignalServiceUrl[] {uaeGoogleService, baseAndroidService, baseGoogleService, mapsOneAndroidService, mapsTwoAndroidService, mailAndroidService},
|
||||
new SignalCdnUrl[] {uaeGoogleCdn, baseAndroidCdn, baseGoogleCdn, mapsOneAndroidCdn, mapsTwoAndroidCdn, mailAndroidCdn},
|
||||
new SignalContactDiscoveryUrl[] {uaeGoogleDiscovery, baseGoogleDiscovery, baseAndroidDiscovery, mapsOneAndroidDiscovery, mapsTwoAndroidDiscovery, mailAndroidDiscovery}));
|
||||
|
||||
put(COUNTRY_CODE_OMAN, new SignalServiceConfiguration(new SignalServiceUrl[] {omanGoogleService, baseAndroidService, baseGoogleService, mapsOneAndroidService, mapsTwoAndroidService, mailAndroidService},
|
||||
new SignalCdnUrl[] {omanGoogleCdn, baseAndroidCdn, baseGoogleCdn, mapsOneAndroidCdn, mapsTwoAndroidCdn, mailAndroidCdn},
|
||||
new SignalContactDiscoveryUrl[] {omanGoogleDiscovery, baseGoogleDiscovery, baseAndroidDiscovery, mapsOneAndroidDiscovery, mapsTwoAndroidDiscovery, mailAndroidDiscovery}));
|
||||
|
||||
|
||||
put(COUNTRY_CODE_QATAR, new SignalServiceConfiguration(new SignalServiceUrl[] {qatarGoogleService, baseAndroidService, baseGoogleService, mapsOneAndroidService, mapsTwoAndroidService, mailAndroidService},
|
||||
new SignalCdnUrl[] {qatarGoogleCdn, baseAndroidCdn, baseGoogleCdn, mapsOneAndroidCdn, mapsTwoAndroidCdn, mailAndroidCdn},
|
||||
new SignalContactDiscoveryUrl[] {qatarGoogleDiscovery, baseGoogleDiscovery, baseAndroidDiscovery, mapsOneAndroidDiscovery, mapsTwoAndroidDiscovery, mailAndroidDiscovery}));
|
||||
}};
|
||||
|
||||
this.uncensoredConfiguration = new SignalServiceConfiguration(new SignalServiceUrl[] {new SignalServiceUrl(BuildConfig.SIGNAL_URL, new SignalServiceTrustStore(context))},
|
||||
new SignalCdnUrl[] {new SignalCdnUrl(BuildConfig.SIGNAL_CDN_URL, new SignalServiceTrustStore(context))},
|
||||
new SignalContactDiscoveryUrl[] {new SignalContactDiscoveryUrl(BuildConfig.SIGNAL_CONTACT_DISCOVERY_URL, new SignalServiceTrustStore(context))});
|
||||
|
||||
this.censoredCountries = this.censorshipConfiguration.keySet().toArray(new String[0]);
|
||||
}
|
||||
|
||||
public SignalServiceConfiguration getConfiguration(Context context) {
|
||||
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
||||
return getConfiguration(localNumber);
|
||||
}
|
||||
|
||||
public SignalServiceConfiguration getConfiguration(@Nullable String localNumber) {
|
||||
if (localNumber == null) return this.uncensoredConfiguration;
|
||||
|
||||
for (String censoredRegion : this.censoredCountries) {
|
||||
if (localNumber.startsWith(censoredRegion)) {
|
||||
return this.censorshipConfiguration.get(censoredRegion);
|
||||
}
|
||||
}
|
||||
|
||||
return this.uncensoredConfiguration;
|
||||
}
|
||||
|
||||
public boolean isCensored(Context context) {
|
||||
return getConfiguration(context) != this.uncensoredConfiguration;
|
||||
}
|
||||
|
||||
public boolean isCensored(String number) {
|
||||
return getConfiguration(number) != this.uncensoredConfiguration;
|
||||
}
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package org.thoughtcrime.securesms.push;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
import org.session.libsignal.service.api.push.TrustStore;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public class SignalServiceTrustStore implements TrustStore {
|
||||
|
||||
private final Context context;
|
||||
|
||||
public SignalServiceTrustStore(Context context) {
|
||||
this.context = context.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getKeyStoreInputStream() {
|
||||
return context.getResources().openRawResource(R.raw.whisper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyStorePassword() {
|
||||
return "whisper";
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
package org.thoughtcrime.securesms.util;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
import org.session.libsignal.utilities.logging.Log;
|
||||
|
||||
import org.session.libsignal.service.api.util.SleepTimer;
|
||||
|
||||
/**
|
||||
* A sleep timer that is based on elapsed realtime, so
|
||||
* that it works properly, even in low-power sleep modes.
|
||||
*
|
||||
*/
|
||||
public class RealtimeSleepTimer implements SleepTimer {
|
||||
private static final String TAG = RealtimeSleepTimer.class.getSimpleName();
|
||||
|
||||
private final AlarmReceiver alarmReceiver;
|
||||
private final Context context;
|
||||
|
||||
public RealtimeSleepTimer(Context context) {
|
||||
this.context = context;
|
||||
alarmReceiver = new RealtimeSleepTimer.AlarmReceiver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sleep(long millis) {
|
||||
context.registerReceiver(alarmReceiver,
|
||||
new IntentFilter(AlarmReceiver.WAKE_UP_THREAD_ACTION));
|
||||
|
||||
final long startTime = System.currentTimeMillis();
|
||||
alarmReceiver.setAlarm(millis);
|
||||
|
||||
while (System.currentTimeMillis() - startTime < millis) {
|
||||
try {
|
||||
synchronized (this) {
|
||||
wait(millis - System.currentTimeMillis() + startTime);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
|
||||
context.unregisterReceiver(alarmReceiver);
|
||||
}
|
||||
|
||||
private class AlarmReceiver extends BroadcastReceiver {
|
||||
private static final String WAKE_UP_THREAD_ACTION = "org.session.libsignal.service.api.util.RealtimeSleepTimer.AlarmReceiver.WAKE_UP_THREAD";
|
||||
|
||||
private void setAlarm(long millis) {
|
||||
final Intent intent = new Intent(WAKE_UP_THREAD_ACTION);
|
||||
final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
|
||||
final AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
|
||||
|
||||
Log.w(TAG, "Setting alarm to wake up in " + millis + "ms.");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
|
||||
SystemClock.elapsedRealtime() + millis,
|
||||
pendingIntent);
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
|
||||
SystemClock.elapsedRealtime() + millis,
|
||||
pendingIntent);
|
||||
} else {
|
||||
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
|
||||
SystemClock.elapsedRealtime() + millis,
|
||||
pendingIntent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Log.w(TAG, "Waking up.");
|
||||
|
||||
synchronized (RealtimeSleepTimer.this) {
|
||||
RealtimeSleepTimer.this.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ import org.session.libsignal.service.api.messages.shared.SharedContact;
|
||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||
import org.session.libsignal.service.api.push.exceptions.PushNetworkException;
|
||||
import org.session.libsignal.service.api.push.exceptions.UnregisteredUserException;
|
||||
import org.session.libsignal.service.api.util.CredentialsProvider;
|
||||
import org.session.libsignal.service.internal.crypto.PaddingInputStream;
|
||||
import org.session.libsignal.service.internal.push.OutgoingPushMessage;
|
||||
import org.session.libsignal.service.internal.push.OutgoingPushMessageList;
|
||||
@ -44,7 +43,6 @@ import org.session.libsignal.service.internal.push.SignalServiceProtos.TypingMes
|
||||
import org.session.libsignal.service.internal.push.http.AttachmentCipherOutputStreamFactory;
|
||||
import org.session.libsignal.service.internal.push.http.OutputStreamFactory;
|
||||
import org.session.libsignal.utilities.Base64;
|
||||
import org.session.libsignal.service.internal.util.StaticCredentialsProvider;
|
||||
import org.session.libsignal.service.internal.util.Util;
|
||||
import org.session.libsignal.utilities.concurrent.SettableFuture;
|
||||
import org.session.libsignal.service.loki.api.LokiDotNetAPI;
|
||||
@ -75,7 +73,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
@ -91,8 +88,6 @@ public class SignalServiceMessageSender {
|
||||
private static final String TAG = SignalServiceMessageSender.class.getSimpleName();
|
||||
|
||||
private final IdentityKeyStore store;
|
||||
private final SignalServiceAddress localAddress;
|
||||
|
||||
// Loki
|
||||
private final String userPublicKey;
|
||||
private final LokiAPIDatabaseProtocol apiDatabase;
|
||||
@ -103,29 +98,7 @@ public class SignalServiceMessageSender {
|
||||
private final LokiOpenGroupDatabaseProtocol openGroupDatabase;
|
||||
private final Broadcaster broadcaster;
|
||||
|
||||
/**
|
||||
* Construct a SignalServiceMessageSender.
|
||||
*
|
||||
* @param user The Signal Service username (eg phone number).
|
||||
* @param password The Signal Service user password.
|
||||
* @param store The SignalProtocolStore.
|
||||
*/
|
||||
public SignalServiceMessageSender(String user, String password,
|
||||
IdentityKeyStore store,
|
||||
String userPublicKey,
|
||||
LokiAPIDatabaseProtocol apiDatabase,
|
||||
LokiThreadDatabaseProtocol threadDatabase,
|
||||
LokiMessageDatabaseProtocol messageDatabase,
|
||||
SessionProtocol sessionProtocolImpl,
|
||||
LokiUserDatabaseProtocol userDatabase,
|
||||
LokiOpenGroupDatabaseProtocol openGroupDatabase,
|
||||
Broadcaster broadcaster)
|
||||
{
|
||||
this(new StaticCredentialsProvider(user, password, null), store, userPublicKey, apiDatabase, threadDatabase, messageDatabase, sessionProtocolImpl, userDatabase, openGroupDatabase, broadcaster);
|
||||
}
|
||||
|
||||
public SignalServiceMessageSender(CredentialsProvider credentialsProvider,
|
||||
IdentityKeyStore store,
|
||||
public SignalServiceMessageSender(IdentityKeyStore store,
|
||||
String userPublicKey,
|
||||
LokiAPIDatabaseProtocol apiDatabase,
|
||||
LokiThreadDatabaseProtocol threadDatabase,
|
||||
@ -136,7 +109,6 @@ public class SignalServiceMessageSender {
|
||||
Broadcaster broadcaster)
|
||||
{
|
||||
this.store = store;
|
||||
this.localAddress = new SignalServiceAddress(credentialsProvider.getUser());
|
||||
this.userPublicKey = userPublicKey;
|
||||
this.apiDatabase = apiDatabase;
|
||||
this.threadDatabase = threadDatabase;
|
||||
@ -517,7 +489,6 @@ public class SignalServiceMessageSender {
|
||||
throws IOException
|
||||
{
|
||||
List<SendMessageResult> results = new LinkedList<>();
|
||||
SignalServiceAddress ownAddress = localAddress;
|
||||
Iterator<SignalServiceAddress> recipientIterator = recipients.iterator();
|
||||
Iterator<Optional<UnidentifiedAccess>> unidentifiedAccessIterator = unidentifiedAccess.iterator();
|
||||
|
||||
|
@ -1,44 +0,0 @@
|
||||
package org.session.libsignal.service.api.profiles;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class SignalServiceProfile {
|
||||
|
||||
@JsonProperty
|
||||
private String identityKey;
|
||||
|
||||
@JsonProperty
|
||||
private String name;
|
||||
|
||||
@JsonProperty
|
||||
private String avatar;
|
||||
|
||||
@JsonProperty
|
||||
private String unidentifiedAccess;
|
||||
|
||||
@JsonProperty
|
||||
private boolean unrestrictedUnidentifiedAccess;
|
||||
|
||||
public SignalServiceProfile() {}
|
||||
|
||||
public String getIdentityKey() {
|
||||
return identityKey;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
public String getUnidentifiedAccess() {
|
||||
return unidentifiedAccess;
|
||||
}
|
||||
|
||||
public boolean isUnrestrictedUnidentifiedAccess() {
|
||||
return unrestrictedUnidentifiedAccess;
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014-2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
|
||||
package org.session.libsignal.service.api.push;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* A class that represents a Java {@link java.security.KeyStore} and
|
||||
* its associated password.
|
||||
*/
|
||||
public interface TrustStore {
|
||||
public InputStream getKeyStoreInputStream();
|
||||
public String getKeyStorePassword();
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014-2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
|
||||
package org.session.libsignal.service.api.util;
|
||||
|
||||
public interface CredentialsProvider {
|
||||
public String getUser();
|
||||
public String getPassword();
|
||||
public String getSignalingKey();
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014-2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
|
||||
package org.session.libsignal.service.api.util;
|
||||
|
||||
public class InvalidNumberException extends Throwable {
|
||||
public InvalidNumberException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014-2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
|
||||
package org.session.libsignal.service.api.util;
|
||||
|
||||
import com.google.i18n.phonenumbers.NumberParseException;
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat;
|
||||
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
|
||||
|
||||
import org.session.libsignal.utilities.logging.Log;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Phone number formats are a pain.
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*
|
||||
*/
|
||||
public class PhoneNumberFormatter {
|
||||
|
||||
private static final String TAG = PhoneNumberFormatter.class.getSimpleName();
|
||||
|
||||
private static final String COUNTRY_CODE_BR = "55";
|
||||
private static final String COUNTRY_CODE_US = "1";
|
||||
|
||||
public static boolean isValidNumber(String e164Number, String countryCode) {
|
||||
if (!PhoneNumberUtil.getInstance().isPossibleNumber(e164Number, countryCode)) {
|
||||
Log.w(TAG, "Failed isPossibleNumber()");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (COUNTRY_CODE_US.equals(countryCode) && !Pattern.matches("^\\+1\\d{10}$", e164Number)) {
|
||||
Log.w(TAG, "Failed US number format check");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (COUNTRY_CODE_BR.equals(countryCode) && !Pattern.matches("^\\+55\\d{2}9?\\d{8}$", e164Number)) {
|
||||
Log.w(TAG, "Failed Brazil number format check");
|
||||
return false;
|
||||
}
|
||||
|
||||
return e164Number.matches("^\\+[0-9]{10,}") ||
|
||||
e164Number.matches("^\\+685[0-9]{5}") ||
|
||||
e164Number.matches("^\\+376[0-9]{6}") ||
|
||||
e164Number.matches("^\\+299[0-9]{6}") ||
|
||||
e164Number.matches("^\\+597[0-9]{6}") ||
|
||||
e164Number.matches("^\\+298[0-9]{6}") ||
|
||||
e164Number.matches("^\\+240[0-9]{6}") ||
|
||||
e164Number.matches("^\\+687[0-9]{6}") ||
|
||||
e164Number.matches("^\\+689[0-9]{6}");
|
||||
}
|
||||
|
||||
private static String impreciseFormatNumber(String number, String localNumber)
|
||||
throws InvalidNumberException
|
||||
{
|
||||
number = number.replaceAll("[^0-9+]", "");
|
||||
|
||||
if (number.charAt(0) == '+')
|
||||
return number;
|
||||
|
||||
if (localNumber.charAt(0) == '+')
|
||||
localNumber = localNumber.substring(1);
|
||||
|
||||
if (localNumber.length() == number.length() || number.length() > localNumber.length())
|
||||
return "+" + number;
|
||||
|
||||
int difference = localNumber.length() - number.length();
|
||||
|
||||
return "+" + localNumber.substring(0, difference) + number;
|
||||
}
|
||||
|
||||
public static String formatNumberInternational(String number) {
|
||||
try {
|
||||
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
|
||||
PhoneNumber parsedNumber = util.parse(number, null);
|
||||
return util.format(parsedNumber, PhoneNumberFormat.INTERNATIONAL);
|
||||
} catch (NumberParseException e) {
|
||||
Log.w(TAG, e);
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
public static String formatNumber(String number, String localNumber)
|
||||
throws InvalidNumberException
|
||||
{
|
||||
if (number == null) {
|
||||
throw new InvalidNumberException("Null String passed as number.");
|
||||
}
|
||||
|
||||
if (number.contains("@")) {
|
||||
throw new InvalidNumberException("Possible attempt to use email address.");
|
||||
}
|
||||
|
||||
number = number.replaceAll("[^0-9+]", "");
|
||||
|
||||
if (number.length() == 0) {
|
||||
throw new InvalidNumberException("No valid characters found.");
|
||||
}
|
||||
|
||||
// if (number.charAt(0) == '+')
|
||||
// return number;
|
||||
|
||||
try {
|
||||
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
|
||||
PhoneNumber localNumberObject = util.parse(localNumber, null);
|
||||
|
||||
String localCountryCode = util.getRegionCodeForNumber(localNumberObject);
|
||||
Log.w(TAG, "Got local CC: " + localCountryCode);
|
||||
|
||||
PhoneNumber numberObject = util.parse(number, localCountryCode);
|
||||
return util.format(numberObject, PhoneNumberFormat.E164);
|
||||
} catch (NumberParseException e) {
|
||||
Log.w(TAG, e);
|
||||
return impreciseFormatNumber(number, localNumber);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getRegionDisplayName(String regionCode) {
|
||||
return (regionCode == null || regionCode.equals("ZZ") || regionCode.equals(PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY))
|
||||
? "Unknown country" : new Locale("", regionCode).getDisplayCountry(Locale.getDefault());
|
||||
}
|
||||
|
||||
public static String formatE164(String countryCode, String number) {
|
||||
try {
|
||||
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
|
||||
int parsedCountryCode = Integer.parseInt(countryCode);
|
||||
PhoneNumber parsedNumber = util.parse(number,
|
||||
util.getRegionCodeForCountryCode(parsedCountryCode));
|
||||
|
||||
return util.format(parsedNumber, PhoneNumberUtil.PhoneNumberFormat.E164);
|
||||
} catch (NumberParseException e) {
|
||||
Log.w(TAG, e);
|
||||
} catch (NumberFormatException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
|
||||
return "+" +
|
||||
countryCode.replaceAll("[^0-9]", "").replaceAll("^0*", "") +
|
||||
number.replaceAll("[^0-9]", "");
|
||||
}
|
||||
|
||||
public static String getInternationalFormatFromE164(String e164number) {
|
||||
try {
|
||||
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
|
||||
PhoneNumber parsedNumber = util.parse(e164number, null);
|
||||
return util.format(parsedNumber, PhoneNumberFormat.INTERNATIONAL);
|
||||
} catch (NumberParseException e) {
|
||||
Log.w(TAG, e);
|
||||
return e164number;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
package org.session.libsignal.service.api.util;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A sleep timer that is based on elapsed realtime, so
|
||||
* that it works properly, even in low-power sleep modes.
|
||||
*
|
||||
*/
|
||||
public class RealtimeSleepTimer implements SleepTimer {
|
||||
private static final String TAG = RealtimeSleepTimer.class.getSimpleName();
|
||||
|
||||
private final AlarmReceiver alarmReceiver;
|
||||
private final Context context;
|
||||
|
||||
public RealtimeSleepTimer(Context context) {
|
||||
this.context = context;
|
||||
alarmReceiver = new AlarmReceiver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sleep(long millis) {
|
||||
context.registerReceiver(alarmReceiver,
|
||||
new IntentFilter(AlarmReceiver.WAKE_UP_THREAD_ACTION));
|
||||
|
||||
final long startTime = System.currentTimeMillis();
|
||||
alarmReceiver.setAlarm(millis);
|
||||
|
||||
while (System.currentTimeMillis() - startTime < millis) {
|
||||
try {
|
||||
synchronized (this) {
|
||||
wait(millis - System.currentTimeMillis() + startTime);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
|
||||
context.unregisterReceiver(alarmReceiver);
|
||||
}
|
||||
|
||||
private class AlarmReceiver extends BroadcastReceiver {
|
||||
private static final String WAKE_UP_THREAD_ACTION = "org.session.libsignal.service.api.util.RealtimeSleepTimer.AlarmReceiver.WAKE_UP_THREAD";
|
||||
|
||||
private void setAlarm(long millis) {
|
||||
final Intent intent = new Intent(WAKE_UP_THREAD_ACTION);
|
||||
final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
|
||||
final AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
|
||||
|
||||
Log.w(TAG, "Setting alarm to wake up in " + millis + "ms.");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
|
||||
SystemClock.elapsedRealtime() + millis,
|
||||
pendingIntent);
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
|
||||
SystemClock.elapsedRealtime() + millis,
|
||||
pendingIntent);
|
||||
} else {
|
||||
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
|
||||
SystemClock.elapsedRealtime() + millis,
|
||||
pendingIntent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Log.w(TAG, "Waking up.");
|
||||
|
||||
synchronized (RealtimeSleepTimer.this) {
|
||||
RealtimeSleepTimer.this.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
package org.session.libsignal.service.api.util;
|
||||
|
||||
public interface SleepTimer {
|
||||
public void sleep(long millis) throws InterruptedException;
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
package org.session.libsignal.service.api.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
/**
|
||||
* Enables TLS v1.2 when creating SSLSockets.
|
||||
* <p/>
|
||||
* For some reason, android supports TLS v1.2 from API 16, but enables it by
|
||||
* default only from API 20.
|
||||
* @link https://developer.android.com/reference/javax/net/ssl/SSLSocket.html
|
||||
* @see SSLSocketFactory
|
||||
*/
|
||||
public class Tls12SocketFactory extends SSLSocketFactory {
|
||||
private static final String[] TLS_V12_V13_ONLY = {"TLSv1.3", "TLSv1.2"};
|
||||
|
||||
final SSLSocketFactory delegate;
|
||||
|
||||
public Tls12SocketFactory(SSLSocketFactory base) {
|
||||
this.delegate = base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return delegate.getDefaultCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return delegate.getSupportedCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
||||
return patch(delegate.createSocket(s, host, port, autoClose));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
|
||||
return patch(delegate.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
|
||||
return patch(delegate.createSocket(host, port, localHost, localPort));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress host, int port) throws IOException {
|
||||
return patch(delegate.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
|
||||
return patch(delegate.createSocket(address, port, localAddress, localPort));
|
||||
}
|
||||
|
||||
private Socket patch(Socket s) {
|
||||
if (s instanceof SSLSocket) {
|
||||
((SSLSocket) s).setEnabledProtocols(TLS_V12_V13_ONLY);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package org.session.libsignal.service.api.util;
|
||||
|
||||
import org.session.libsignal.service.api.util.SleepTimer;
|
||||
|
||||
/**
|
||||
* A simle sleep timer. Since Thread.sleep is based on uptime
|
||||
* this will not work properly in low-power sleep modes, when
|
||||
* the CPU is suspended and uptime does not elapse.
|
||||
*
|
||||
*/
|
||||
public class UptimeSleepTimer implements SleepTimer {
|
||||
@Override
|
||||
public void sleep(long millis) throws InterruptedException {
|
||||
Thread.sleep(millis);
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package org.session.libsignal.service.api.websocket;
|
||||
|
||||
|
||||
public interface ConnectivityListener {
|
||||
void onConnected();
|
||||
void onConnecting();
|
||||
void onDisconnected();
|
||||
void onAuthenticationFailure();
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package org.session.libsignal.service.internal.configuration;
|
||||
|
||||
|
||||
import org.session.libsignal.service.api.push.TrustStore;
|
||||
|
||||
import okhttp3.ConnectionSpec;
|
||||
|
||||
public class SignalCdnUrl extends SignalUrl {
|
||||
public SignalCdnUrl(String url, TrustStore trustStore) {
|
||||
super(url, trustStore);
|
||||
}
|
||||
|
||||
public SignalCdnUrl(String url, String hostHeader, TrustStore trustStore, ConnectionSpec connectionSpec) {
|
||||
super(url, hostHeader, trustStore, connectionSpec);
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package org.session.libsignal.service.internal.configuration;
|
||||
|
||||
|
||||
import org.session.libsignal.service.api.push.TrustStore;
|
||||
|
||||
import okhttp3.ConnectionSpec;
|
||||
|
||||
public class SignalContactDiscoveryUrl extends SignalUrl {
|
||||
|
||||
public SignalContactDiscoveryUrl(String url, TrustStore trustStore) {
|
||||
super(url, trustStore);
|
||||
}
|
||||
|
||||
public SignalContactDiscoveryUrl(String url, String hostHeader, TrustStore trustStore, ConnectionSpec connectionSpec) {
|
||||
super(url, hostHeader, trustStore, connectionSpec);
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package org.session.libsignal.service.internal.configuration;
|
||||
|
||||
|
||||
public class SignalServiceConfiguration {
|
||||
|
||||
private final SignalServiceUrl[] signalServiceUrls;
|
||||
private final SignalCdnUrl[] signalCdnUrls;
|
||||
private final SignalContactDiscoveryUrl[] signalContactDiscoveryUrls;
|
||||
|
||||
public SignalServiceConfiguration(SignalServiceUrl[] signalServiceUrls, SignalCdnUrl[] signalCdnUrls, SignalContactDiscoveryUrl[] signalContactDiscoveryUrls) {
|
||||
this.signalServiceUrls = signalServiceUrls;
|
||||
this.signalCdnUrls = signalCdnUrls;
|
||||
this.signalContactDiscoveryUrls = signalContactDiscoveryUrls;
|
||||
}
|
||||
|
||||
public SignalServiceUrl[] getSignalServiceUrls() {
|
||||
return signalServiceUrls;
|
||||
}
|
||||
|
||||
public SignalCdnUrl[] getSignalCdnUrls() {
|
||||
return signalCdnUrls;
|
||||
}
|
||||
|
||||
public SignalContactDiscoveryUrl[] getSignalContactDiscoveryUrls() {
|
||||
return signalContactDiscoveryUrls;
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package org.session.libsignal.service.internal.configuration;
|
||||
|
||||
|
||||
import org.session.libsignal.service.api.push.TrustStore;
|
||||
|
||||
import okhttp3.ConnectionSpec;
|
||||
|
||||
public class SignalServiceUrl extends SignalUrl {
|
||||
|
||||
public SignalServiceUrl(String url, TrustStore trustStore) {
|
||||
super(url, trustStore);
|
||||
}
|
||||
|
||||
public SignalServiceUrl(String url, String hostHeader, TrustStore trustStore, ConnectionSpec connectionSpec) {
|
||||
super(url, hostHeader, trustStore, connectionSpec);
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
package org.session.libsignal.service.internal.configuration;
|
||||
|
||||
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.api.push.TrustStore;
|
||||
import org.session.libsignal.service.internal.util.BlacklistingTrustManager;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.TrustManager;
|
||||
|
||||
import okhttp3.ConnectionSpec;
|
||||
|
||||
public class SignalUrl {
|
||||
|
||||
private final String url;
|
||||
private final Optional<String> hostHeader;
|
||||
private final Optional<ConnectionSpec> connectionSpec;
|
||||
private TrustStore trustStore;
|
||||
|
||||
public SignalUrl(String url, TrustStore trustStore) {
|
||||
this(url, null, trustStore, null);
|
||||
}
|
||||
|
||||
public SignalUrl(String url, String hostHeader,
|
||||
TrustStore trustStore,
|
||||
ConnectionSpec connectionSpec)
|
||||
{
|
||||
this.url = url;
|
||||
this.hostHeader = Optional.fromNullable(hostHeader);
|
||||
this.trustStore = trustStore;
|
||||
this.connectionSpec = Optional.fromNullable(connectionSpec);
|
||||
}
|
||||
|
||||
|
||||
public Optional<String> getHostHeader() {
|
||||
return hostHeader;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public TrustStore getTrustStore() {
|
||||
return trustStore;
|
||||
}
|
||||
|
||||
public Optional<List<ConnectionSpec>> getConnectionSpecs() {
|
||||
return connectionSpec.isPresent() ? Optional.of(Collections.singletonList(connectionSpec.get())) : Optional.<List<ConnectionSpec>>absent();
|
||||
}
|
||||
|
||||
}
|
@ -1,172 +0,0 @@
|
||||
package org.session.libsignal.service.internal.contacts.crypto;
|
||||
|
||||
|
||||
import org.threeten.bp.Instant;
|
||||
import org.threeten.bp.LocalDateTime;
|
||||
import org.threeten.bp.Period;
|
||||
import org.threeten.bp.ZoneId;
|
||||
import org.threeten.bp.ZonedDateTime;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.session.libsignal.libsignal.util.ByteUtil;
|
||||
import org.session.libsignal.service.api.crypto.InvalidCiphertextException;
|
||||
import org.session.libsignal.service.internal.contacts.entities.DiscoveryRequest;
|
||||
import org.session.libsignal.service.internal.contacts.entities.DiscoveryResponse;
|
||||
import org.session.libsignal.service.internal.contacts.entities.RemoteAttestationResponse;
|
||||
import org.session.libsignal.utilities.Hex;
|
||||
import org.session.libsignal.utilities.JsonUtil;
|
||||
import org.session.libsignal.service.internal.util.Util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SignatureException;
|
||||
import java.security.cert.CertPathValidatorException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class ContactDiscoveryCipher {
|
||||
|
||||
private static final int TAG_LENGTH_BYTES = 16;
|
||||
private static final int TAG_LENGTH_BITS = TAG_LENGTH_BYTES * 8;
|
||||
private static final long SIGNATURE_BODY_VERSION = 3L;
|
||||
|
||||
public DiscoveryRequest createDiscoveryRequest(List<String> addressBook, RemoteAttestation remoteAttestation) {
|
||||
try {
|
||||
ByteArrayOutputStream requestDataStream = new ByteArrayOutputStream();
|
||||
|
||||
for (String address : addressBook) {
|
||||
requestDataStream.write(ByteUtil.longToByteArray(Long.parseLong(address)));
|
||||
}
|
||||
|
||||
byte[] requestData = requestDataStream.toByteArray();
|
||||
byte[] nonce = Util.getSecretBytes(12);
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
|
||||
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(remoteAttestation.getKeys().getClientKey(), "AES"), new GCMParameterSpec(TAG_LENGTH_BITS, nonce));
|
||||
cipher.updateAAD(remoteAttestation.getRequestId());
|
||||
|
||||
byte[] cipherText = cipher.doFinal(requestData);
|
||||
byte[][] parts = ByteUtil.split(cipherText, cipherText.length - TAG_LENGTH_BYTES, TAG_LENGTH_BYTES);
|
||||
|
||||
return new DiscoveryRequest(addressBook.size(), remoteAttestation.getRequestId(), nonce, parts[0], parts[1]);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (NoSuchPaddingException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (BadPaddingException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getDiscoveryResponseData(DiscoveryResponse response, RemoteAttestation remoteAttestation) throws InvalidCiphertextException {
|
||||
return decrypt(remoteAttestation.getKeys().getServerKey(), response.getIv(), response.getData(), response.getMac());
|
||||
}
|
||||
|
||||
public byte[] getRequestId(RemoteAttestationKeys keys, RemoteAttestationResponse response) throws InvalidCiphertextException {
|
||||
return decrypt(keys.getServerKey(), response.getIv(), response.getCiphertext(), response.getTag());
|
||||
}
|
||||
|
||||
public void verifyServerQuote(Quote quote, byte[] serverPublicStatic, String mrenclave)
|
||||
throws UnauthenticatedQuoteException
|
||||
{
|
||||
try {
|
||||
byte[] theirServerPublicStatic = new byte[serverPublicStatic.length];
|
||||
System.arraycopy(quote.getReportData(), 0, theirServerPublicStatic, 0, theirServerPublicStatic.length);
|
||||
|
||||
if (!MessageDigest.isEqual(theirServerPublicStatic, serverPublicStatic)) {
|
||||
throw new UnauthenticatedQuoteException("Response quote has unauthenticated report data!");
|
||||
}
|
||||
|
||||
if (!MessageDigest.isEqual(Hex.fromStringCondensed(mrenclave), quote.getMrenclave())) {
|
||||
throw new UnauthenticatedQuoteException("The response quote has the wrong mrenclave value in it: " + Hex.toStringCondensed(quote.getMrenclave()));
|
||||
}
|
||||
|
||||
if (quote.isDebugQuote()) {
|
||||
throw new UnauthenticatedQuoteException("Received quote for debuggable enclave");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UnauthenticatedQuoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void verifyIasSignature(KeyStore trustStore, String certificates, String signatureBody, String signature, Quote quote)
|
||||
throws SignatureException
|
||||
{
|
||||
if (certificates == null || certificates.isEmpty()) {
|
||||
throw new SignatureException("No certificates.");
|
||||
}
|
||||
|
||||
try {
|
||||
SigningCertificate signingCertificate = new SigningCertificate(certificates, trustStore);
|
||||
signingCertificate.verifySignature(signatureBody, signature);
|
||||
|
||||
SignatureBodyEntity signatureBodyEntity = JsonUtil.fromJson(signatureBody, SignatureBodyEntity.class);
|
||||
|
||||
if (signatureBodyEntity.getVersion() != SIGNATURE_BODY_VERSION) {
|
||||
throw new SignatureException("Unexpected signed quote version " + signatureBodyEntity.getVersion());
|
||||
}
|
||||
|
||||
if (!MessageDigest.isEqual(ByteUtil.trim(signatureBodyEntity.getIsvEnclaveQuoteBody(), 432), ByteUtil.trim(quote.getQuoteBytes(), 432))) {
|
||||
throw new SignatureException("Signed quote is not the same as RA quote: " + Hex.toStringCondensed(signatureBodyEntity.getIsvEnclaveQuoteBody()) + " vs " + Hex.toStringCondensed(quote.getQuoteBytes()));
|
||||
}
|
||||
|
||||
if (!"OK".equals(signatureBodyEntity.getIsvEnclaveQuoteStatus())) {
|
||||
throw new SignatureException("Quote status is: " + signatureBodyEntity.getIsvEnclaveQuoteStatus());
|
||||
}
|
||||
|
||||
if (Instant.from(ZonedDateTime.of(LocalDateTime.from(DateTimeFormatter.ofPattern("yyy-MM-dd'T'HH:mm:ss.SSSSSS").parse(signatureBodyEntity.getTimestamp())), ZoneId.of("UTC")))
|
||||
.plus(Period.ofDays(1))
|
||||
.isBefore(Instant.now()))
|
||||
{
|
||||
throw new SignatureException("Signature is expired");
|
||||
}
|
||||
|
||||
} catch (CertificateException e) {
|
||||
throw new SignatureException(e);
|
||||
} catch (CertPathValidatorException e) {
|
||||
throw new SignatureException(e);
|
||||
} catch (IOException e) {
|
||||
throw new SignatureException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] decrypt(byte[] key, byte[] iv, byte[] ciphertext, byte[] tag) throws InvalidCiphertextException {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new GCMParameterSpec(128, iv));
|
||||
|
||||
return cipher.doFinal(ByteUtil.combine(ciphertext, tag));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (NoSuchPaddingException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch(InvalidAlgorithmParameterException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new InvalidCiphertextException(e);
|
||||
} catch (BadPaddingException e) {
|
||||
throw new InvalidCiphertextException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
package org.session.libsignal.service.internal.contacts.crypto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public class Quote {
|
||||
|
||||
private static final long SGX_FLAGS_INITTED = 0x0000000000000001L;
|
||||
private static final long SGX_FLAGS_DEBUG = 0x0000000000000002L;
|
||||
private static final long SGX_FLAGS_MODE64BIT = 0x0000000000000004L;
|
||||
private static final long SGX_FLAGS_PROVISION_KEY = 0x0000000000000004L;
|
||||
private static final long SGX_FLAGS_EINITTOKEN_KEY = 0x0000000000000004L;
|
||||
private static final long SGX_FLAGS_RESERVED = 0xFFFFFFFFFFFFFFC8L;
|
||||
private static final long SGX_XFRM_LEGACY = 0x0000000000000003L;
|
||||
private static final long SGX_XFRM_AVX = 0x0000000000000006L;
|
||||
private static final long SGX_XFRM_RESERVED = 0xFFFFFFFFFFFFFFF8L;
|
||||
|
||||
private final int version;
|
||||
private final boolean isSigLinkable;
|
||||
private final long gid;
|
||||
private final int qeSvn;
|
||||
private final int pceSvn;
|
||||
private final byte[] basename = new byte[32];
|
||||
private final byte[] cpuSvn = new byte[16];
|
||||
private final long flags;
|
||||
private final long xfrm;
|
||||
private final byte[] mrenclave = new byte[32];
|
||||
private final byte[] mrsigner = new byte[32];
|
||||
private final int isvProdId;
|
||||
private final int isvSvn;
|
||||
private final byte[] reportData = new byte[64];
|
||||
private final byte[] signature;
|
||||
private final byte[] quoteBytes;
|
||||
|
||||
public Quote(byte[] quoteBytes) throws InvalidQuoteFormatException {
|
||||
this.quoteBytes = quoteBytes;
|
||||
|
||||
ByteBuffer quoteBuf = ByteBuffer.wrap(quoteBytes);
|
||||
quoteBuf.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
this.version = quoteBuf.getShort(0) & 0xFFFF;
|
||||
if (!(version >= 1 && version <= 2)) {
|
||||
throw new InvalidQuoteFormatException("unknown_quote_version "+version);
|
||||
}
|
||||
|
||||
int sign_type = quoteBuf.getShort(2) & 0xFFFF;
|
||||
if ((sign_type & ~1) != 0) {
|
||||
throw new InvalidQuoteFormatException("unknown_quote_sign_type "+sign_type);
|
||||
}
|
||||
|
||||
this.isSigLinkable = sign_type == 1;
|
||||
this.gid = quoteBuf.getInt(4) & 0xFFFFFFFF;
|
||||
this.qeSvn = quoteBuf.getShort(8) & 0xFFFF;
|
||||
|
||||
if (version > 1) {
|
||||
this.pceSvn = quoteBuf.getShort(10) & 0xFFFF;
|
||||
} else {
|
||||
readZero(quoteBuf, 10, 2);
|
||||
this.pceSvn = 0;
|
||||
}
|
||||
|
||||
readZero(quoteBuf, 12, 4); // xeid (reserved)
|
||||
read(quoteBuf, 16, basename);
|
||||
|
||||
//
|
||||
// report_body
|
||||
//
|
||||
|
||||
read(quoteBuf, 48, cpuSvn);
|
||||
readZero(quoteBuf, 64, 4); // misc_select (reserved)
|
||||
readZero(quoteBuf, 68, 28); // reserved1
|
||||
this.flags = quoteBuf.getLong(96);
|
||||
if ((flags & SGX_FLAGS_RESERVED ) != 0 ||
|
||||
(flags & SGX_FLAGS_INITTED ) == 0 ||
|
||||
(flags & SGX_FLAGS_MODE64BIT) == 0) {
|
||||
throw new InvalidQuoteFormatException("bad_quote_flags "+flags);
|
||||
}
|
||||
this.xfrm = quoteBuf.getLong(104);
|
||||
if ((xfrm & SGX_XFRM_RESERVED) != 0) {
|
||||
throw new InvalidQuoteFormatException("bad_quote_xfrm "+xfrm);
|
||||
}
|
||||
read(quoteBuf, 112, mrenclave);
|
||||
readZero(quoteBuf, 144, 32); // reserved2
|
||||
read(quoteBuf, 176, mrsigner);
|
||||
readZero(quoteBuf, 208, 96); // reserved3
|
||||
this.isvProdId = quoteBuf.getShort(304) & 0xFFFF;
|
||||
this.isvSvn = quoteBuf.getShort(306) & 0xFFFF;
|
||||
readZero(quoteBuf, 308, 60); // reserved4
|
||||
read(quoteBuf, 368, reportData);
|
||||
|
||||
// quote signature
|
||||
int sig_len = quoteBuf.getInt(432) & 0xFFFFFFFF;
|
||||
if (sig_len != quoteBytes.length - 436) {
|
||||
throw new InvalidQuoteFormatException("bad_quote_sig_len "+sig_len);
|
||||
}
|
||||
this.signature = new byte[sig_len];
|
||||
read(quoteBuf, 436, signature);
|
||||
}
|
||||
|
||||
public byte[] getReportData() {
|
||||
return reportData;
|
||||
}
|
||||
|
||||
private void read(ByteBuffer quoteBuf, int pos, byte[] buf) {
|
||||
quoteBuf.position(pos);
|
||||
quoteBuf.get(buf);
|
||||
}
|
||||
|
||||
private void readZero(ByteBuffer quoteBuf, int pos, int count) {
|
||||
byte[] zeroBuf = new byte[count];
|
||||
read(quoteBuf, pos, zeroBuf);
|
||||
for (int zeroBufIdx = 0; zeroBufIdx < count; zeroBufIdx++) {
|
||||
if (zeroBuf[zeroBufIdx] != 0) {
|
||||
throw new IllegalArgumentException("quote_reserved_mismatch "+pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getQuoteBytes() {
|
||||
return quoteBytes;
|
||||
}
|
||||
|
||||
public byte[] getMrenclave() {
|
||||
return mrenclave;
|
||||
}
|
||||
|
||||
public boolean isDebugQuote() {
|
||||
return (flags & SGX_FLAGS_DEBUG) != 0;
|
||||
}
|
||||
|
||||
public static class InvalidQuoteFormatException extends Exception {
|
||||
public InvalidQuoteFormatException(String value) {
|
||||
super(value);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package org.session.libsignal.service.internal.contacts.crypto;
|
||||
|
||||
import org.session.libsignal.service.internal.contacts.crypto.RemoteAttestationKeys;
|
||||
|
||||
public class RemoteAttestation {
|
||||
|
||||
private final byte[] requestId;
|
||||
private final RemoteAttestationKeys keys;
|
||||
|
||||
public RemoteAttestation(byte[] requestId, RemoteAttestationKeys keys) {
|
||||
this.requestId = requestId;
|
||||
this.keys = keys;
|
||||
}
|
||||
|
||||
public byte[] getRequestId() {
|
||||
return requestId;
|
||||
}
|
||||
|
||||
public RemoteAttestationKeys getKeys() {
|
||||
return keys;
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
package org.session.libsignal.service.internal.contacts.crypto;
|
||||
|
||||
|
||||
import org.whispersystems.curve25519.Curve25519;
|
||||
import org.whispersystems.curve25519.Curve25519KeyPair;
|
||||
import org.session.libsignal.libsignal.kdf.HKDFv3;
|
||||
import org.session.libsignal.libsignal.util.ByteUtil;
|
||||
|
||||
public class RemoteAttestationKeys {
|
||||
|
||||
private final byte[] clientKey = new byte[32];
|
||||
private final byte[] serverKey = new byte[32];
|
||||
|
||||
public RemoteAttestationKeys(Curve25519KeyPair keyPair, byte[] serverPublicEphemeral, byte[] serverPublicStatic) {
|
||||
byte[] ephemeralToEphemeral = Curve25519.getInstance(Curve25519.BEST).calculateAgreement(serverPublicEphemeral, keyPair.getPrivateKey());
|
||||
byte[] ephemeralToStatic = Curve25519.getInstance(Curve25519.BEST).calculateAgreement(serverPublicStatic, keyPair.getPrivateKey());
|
||||
|
||||
byte[] masterSecret = ByteUtil.combine(ephemeralToEphemeral, ephemeralToStatic );
|
||||
byte[] publicKeys = ByteUtil.combine(keyPair.getPublicKey(), serverPublicEphemeral, serverPublicStatic);
|
||||
|
||||
HKDFv3 generator = new HKDFv3();
|
||||
byte[] keys = generator.deriveSecrets(masterSecret, publicKeys, null, clientKey.length + serverKey.length);
|
||||
|
||||
System.arraycopy(keys, 0, clientKey, 0, clientKey.length);
|
||||
System.arraycopy(keys, clientKey.length, serverKey, 0, serverKey.length);
|
||||
}
|
||||
|
||||
public byte[] getClientKey() {
|
||||
return clientKey;
|
||||
}
|
||||
|
||||
public byte[] getServerKey() {
|
||||
return serverKey;
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package org.session.libsignal.service.internal.contacts.crypto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class SignatureBodyEntity {
|
||||
|
||||
@JsonProperty
|
||||
private byte[] isvEnclaveQuoteBody;
|
||||
|
||||
@JsonProperty
|
||||
private String isvEnclaveQuoteStatus;
|
||||
|
||||
@JsonProperty
|
||||
private Long version;
|
||||
|
||||
@JsonProperty
|
||||
private String timestamp;
|
||||
|
||||
public byte[] getIsvEnclaveQuoteBody() {
|
||||
return isvEnclaveQuoteBody;
|
||||
}
|
||||
|
||||
public String getIsvEnclaveQuoteStatus() {
|
||||
return isvEnclaveQuoteStatus;
|
||||
}
|
||||
|
||||
public Long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public String getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
package org.session.libsignal.service.internal.contacts.crypto;
|
||||
|
||||
import org.session.libsignal.utilities.Base64;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.net.URLDecoder;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
import java.security.cert.CertPath;
|
||||
import java.security.cert.CertPathValidator;
|
||||
import java.security.cert.CertPathValidatorException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.PKIXParameters;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class SigningCertificate {
|
||||
|
||||
private final CertPath path;
|
||||
|
||||
public SigningCertificate(String certificateChain, KeyStore trustStore)
|
||||
throws CertificateException, CertPathValidatorException
|
||||
{
|
||||
try {
|
||||
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
|
||||
Collection<X509Certificate> certificatesCollection = (Collection<X509Certificate>) certificateFactory.generateCertificates(new ByteArrayInputStream(URLDecoder.decode(certificateChain).getBytes()));
|
||||
List<X509Certificate> certificates = new LinkedList<X509Certificate>(certificatesCollection);
|
||||
PKIXParameters pkixParameters = new PKIXParameters(trustStore);
|
||||
CertPathValidator validator = CertPathValidator.getInstance("PKIX");
|
||||
|
||||
this.path = certificateFactory.generateCertPath(certificates);
|
||||
|
||||
pkixParameters.setRevocationEnabled(false);
|
||||
validator.validate(path, pkixParameters);
|
||||
verifyDistinguishedName(path);
|
||||
} catch (KeyStoreException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void verifySignature(String body, String encodedSignature)
|
||||
throws SignatureException
|
||||
{
|
||||
try {
|
||||
Signature signature = Signature.getInstance("SHA256withRSA");
|
||||
signature.initVerify(path.getCertificates().get(0));
|
||||
signature.update(body.getBytes());
|
||||
if (!signature.verify(Base64.decode(encodedSignature.getBytes()))) {
|
||||
throw new SignatureException("Signature verification failed.");
|
||||
}
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyDistinguishedName(CertPath path) throws CertificateException {
|
||||
X509Certificate leaf = (X509Certificate) path.getCertificates().get(0);
|
||||
String distinguishedName = leaf.getSubjectX500Principal().getName();
|
||||
|
||||
if (!"CN=Intel SGX Attestation Report Signing,O=Intel Corporation,L=Santa Clara,ST=CA,C=US".equals(distinguishedName)) {
|
||||
throw new CertificateException("Bad DN: " + distinguishedName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package org.session.libsignal.service.internal.contacts.crypto;
|
||||
|
||||
|
||||
public class UnauthenticatedQuoteException extends Exception {
|
||||
public UnauthenticatedQuoteException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public UnauthenticatedQuoteException(Exception nested) {
|
||||
super(nested);
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package org.session.libsignal.service.internal.contacts.crypto;
|
||||
|
||||
|
||||
public class UnauthenticatedResponseException extends Exception {
|
||||
public UnauthenticatedResponseException(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
public UnauthenticatedResponseException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.session.libsignal.service.internal.contacts.entities;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.session.libsignal.utilities.Hex;
|
||||
|
||||
|
||||
public class DiscoveryRequest {
|
||||
|
||||
@JsonProperty
|
||||
private int addressCount;
|
||||
|
||||
@JsonProperty
|
||||
private byte[] requestId;
|
||||
|
||||
@JsonProperty
|
||||
private byte[] iv;
|
||||
|
||||
@JsonProperty
|
||||
private byte[] data;
|
||||
|
||||
@JsonProperty
|
||||
private byte[] mac;
|
||||
|
||||
public DiscoveryRequest() {
|
||||
|
||||
}
|
||||
|
||||
public DiscoveryRequest(int addressCount, byte[] requestId, byte[] iv, byte[] data, byte[] mac) {
|
||||
this.addressCount = addressCount;
|
||||
this.requestId = requestId;
|
||||
this.iv = iv;
|
||||
this.data = data;
|
||||
this. mac = mac;
|
||||
}
|
||||
|
||||
public byte[] getRequestId() {
|
||||
return requestId;
|
||||
}
|
||||
|
||||
public byte[] getIv() {
|
||||
return iv;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public byte[] getMac() {
|
||||
return mac;
|
||||
}
|
||||
|
||||
public int getAddressCount() {
|
||||
return addressCount;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "{ addressCount: " + addressCount + ", ticket: " + Hex.toString(requestId) + ", iv: " + Hex.toString(iv) + ", data: " + Hex.toString(data) + ", mac: " + Hex.toString(mac) + "}";
|
||||
}
|
||||
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.session.libsignal.service.internal.contacts.entities;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.session.libsignal.utilities.Hex;
|
||||
|
||||
public class DiscoveryResponse {
|
||||
|
||||
@JsonProperty
|
||||
private byte[] iv;
|
||||
|
||||
@JsonProperty
|
||||
private byte[] data;
|
||||
|
||||
@JsonProperty
|
||||
private byte[] mac;
|
||||
|
||||
public DiscoveryResponse() {}
|
||||
|
||||
public DiscoveryResponse(byte[] iv, byte[] data, byte[] mac) {
|
||||
this.iv = iv;
|
||||
this.data = data;
|
||||
this.mac = mac;
|
||||
}
|
||||
|
||||
public byte[] getIv() {
|
||||
return iv;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public byte[] getMac() {
|
||||
return mac;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "{iv: " + (iv == null ? null : Hex.toString(iv)) + ", data: " + (data == null ? null: Hex.toString(data)) + ", mac: " + (mac == null ? null : Hex.toString(mac)) + "}";
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.session.libsignal.service.internal.contacts.entities;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class RemoteAttestationRequest {
|
||||
|
||||
@JsonProperty
|
||||
private byte[] clientPublic;
|
||||
|
||||
public RemoteAttestationRequest() {}
|
||||
|
||||
public RemoteAttestationRequest(byte[] clientPublic) {
|
||||
this.clientPublic = clientPublic;
|
||||
}
|
||||
|
||||
public byte[] getClientPublic() {
|
||||
return clientPublic;
|
||||
}
|
||||
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.session.libsignal.service.internal.contacts.entities;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class RemoteAttestationResponse {
|
||||
|
||||
@JsonProperty
|
||||
private byte[] serverEphemeralPublic;
|
||||
|
||||
@JsonProperty
|
||||
private byte[] serverStaticPublic;
|
||||
|
||||
@JsonProperty
|
||||
private byte[] quote;
|
||||
|
||||
@JsonProperty
|
||||
private byte[] iv;
|
||||
|
||||
@JsonProperty
|
||||
private byte[] ciphertext;
|
||||
|
||||
@JsonProperty
|
||||
private byte[] tag;
|
||||
|
||||
@JsonProperty
|
||||
private String signature;
|
||||
|
||||
@JsonProperty
|
||||
private String certificates;
|
||||
|
||||
@JsonProperty
|
||||
private String signatureBody;
|
||||
|
||||
public RemoteAttestationResponse(byte[] serverEphemeralPublic, byte[] serverStaticPublic,
|
||||
byte[] iv, byte[] ciphertext, byte[] tag,
|
||||
byte[] quote, String signature, String certificates, String signatureBody)
|
||||
{
|
||||
this.serverEphemeralPublic = serverEphemeralPublic;
|
||||
this.serverStaticPublic = serverStaticPublic;
|
||||
this.iv = iv;
|
||||
this.ciphertext = ciphertext;
|
||||
this.tag = tag;
|
||||
this.quote = quote;
|
||||
this.signature = signature;
|
||||
this.certificates = certificates;
|
||||
this.signatureBody = signatureBody;
|
||||
}
|
||||
|
||||
public RemoteAttestationResponse() {}
|
||||
|
||||
public byte[] getServerEphemeralPublic() {
|
||||
return serverEphemeralPublic;
|
||||
}
|
||||
|
||||
public byte[] getServerStaticPublic() {
|
||||
return serverStaticPublic;
|
||||
}
|
||||
|
||||
public byte[] getQuote() {
|
||||
return quote;
|
||||
}
|
||||
|
||||
public byte[] getIv() {
|
||||
return iv;
|
||||
}
|
||||
|
||||
public byte[] getCiphertext() {
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
public byte[] getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public String getCertificates() {
|
||||
return certificates;
|
||||
}
|
||||
|
||||
public String getSignatureBody() {
|
||||
return signatureBody;
|
||||
}
|
||||
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014-2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
|
||||
package org.session.libsignal.service.internal.util;
|
||||
|
||||
import org.session.libsignal.libsignal.util.Pair;
|
||||
import org.session.libsignal.service.api.push.TrustStore;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
/**
|
||||
* Trust manager that defers to a system X509 trust manager, and
|
||||
* additionally rejects certificates if they have a blacklisted
|
||||
* serial.
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*/
|
||||
public class BlacklistingTrustManager implements X509TrustManager {
|
||||
|
||||
private static final List<Pair<String, BigInteger>> BLACKLIST = new LinkedList<Pair<String, BigInteger>>() {{
|
||||
add(new Pair<String, BigInteger>("Open Whisper Systems", new BigInteger("4098")));
|
||||
}};
|
||||
|
||||
public static TrustManager[] createFor(TrustManager[] trustManagers) {
|
||||
for (TrustManager trustManager : trustManagers) {
|
||||
if (trustManager instanceof X509TrustManager) {
|
||||
TrustManager[] results = new BlacklistingTrustManager[1];
|
||||
results[0] = new BlacklistingTrustManager((X509TrustManager)trustManager);
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
throw new AssertionError("No X509 Trust Managers!");
|
||||
}
|
||||
|
||||
public static TrustManager[] createFor(TrustStore trustStore) {
|
||||
try {
|
||||
InputStream keyStoreInputStream = trustStore.getKeyStoreInputStream();
|
||||
KeyStore keyStore = KeyStore.getInstance("BKS");
|
||||
|
||||
keyStore.load(keyStoreInputStream, trustStore.getKeyStorePassword().toCharArray());
|
||||
|
||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
|
||||
trustManagerFactory.init(keyStore);
|
||||
|
||||
return BlacklistingTrustManager.createFor(trustManagerFactory.getTrustManagers());
|
||||
} catch (KeyStoreException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (CertificateException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final X509TrustManager trustManager;
|
||||
|
||||
public BlacklistingTrustManager(X509TrustManager trustManager) {
|
||||
this.trustManager = trustManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType)
|
||||
throws CertificateException
|
||||
{
|
||||
trustManager.checkClientTrusted(chain, authType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType)
|
||||
throws CertificateException
|
||||
{
|
||||
trustManager.checkServerTrusted(chain, authType);
|
||||
|
||||
for (X509Certificate certificate : chain) {
|
||||
for (Pair<String, BigInteger> blacklistedSerial : BLACKLIST) {
|
||||
if (certificate.getIssuerDN().getName().equals(blacklistedSerial.first()) &&
|
||||
certificate.getSerialNumber().equals(blacklistedSerial.second()))
|
||||
{
|
||||
throw new CertificateException("Blacklisted Serial: " + certificate.getSerialNumber());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return trustManager.getAcceptedIssuers();
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014-2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
|
||||
package org.session.libsignal.service.internal.util;
|
||||
|
||||
import org.session.libsignal.service.api.util.CredentialsProvider;
|
||||
|
||||
public class StaticCredentialsProvider implements CredentialsProvider {
|
||||
|
||||
private final String user;
|
||||
private final String password;
|
||||
private final String signalingKey;
|
||||
|
||||
public StaticCredentialsProvider(String user, String password, String signalingKey) {
|
||||
this.user = user;
|
||||
this.password = password;
|
||||
this.signalingKey = signalingKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSignalingKey() {
|
||||
return signalingKey;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user