clean up: signal service protocols

This commit is contained in:
Ryan ZHAO 2021-02-22 10:41:27 +11:00
parent 88bbc0b677
commit 1db9ccdf27
39 changed files with 2 additions and 1936 deletions

View File

@ -81,7 +81,6 @@ import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
import org.thoughtcrime.securesms.notifications.NotificationChannels; import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.notifications.OptimizedMessageNotifier; import org.thoughtcrime.securesms.notifications.OptimizedMessageNotifier;
import org.thoughtcrime.securesms.providers.BlobProvider; import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
import org.thoughtcrime.securesms.service.ExpiringMessageManager; import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.service.LocalBackupListener; import org.thoughtcrime.securesms.service.LocalBackupListener;

View File

@ -2,11 +2,8 @@ package org.thoughtcrime.securesms.dependencies;
import android.content.Context; 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.SignalServiceMessageReceiver;
import org.session.libsignal.service.api.SignalServiceMessageSender; 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.ApplicationContext;
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl; import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl;
import org.thoughtcrime.securesms.database.DatabaseFactory; 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.SendReadReceiptJob;
import org.thoughtcrime.securesms.jobs.TypingSendJob; import org.thoughtcrime.securesms.jobs.TypingSendJob;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository; import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.loki.api.SessionProtocolImpl; import org.thoughtcrime.securesms.loki.api.SessionProtocolImpl;
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment; import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
import org.thoughtcrime.securesms.util.RealtimeSleepTimer;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import network.loki.messenger.BuildConfig;
@Module(complete = false, injects = {PushGroupSendJob.class, @Module(complete = false, injects = {PushGroupSendJob.class,
PushTextSendJob.class, PushTextSendJob.class,
@ -52,8 +46,6 @@ import network.loki.messenger.BuildConfig;
public class SignalCommunicationModule { public class SignalCommunicationModule {
private static final String TAG = SignalCommunicationModule.class.getSimpleName();
private final Context context; private final Context context;
private SignalServiceMessageSender messageSender; private SignalServiceMessageSender messageSender;
@ -66,8 +58,7 @@ public class SignalCommunicationModule {
@Provides @Provides
public synchronized SignalServiceMessageSender provideSignalMessageSender() { public synchronized SignalServiceMessageSender provideSignalMessageSender() {
if (this.messageSender == null) { if (this.messageSender == null) {
this.messageSender = new SignalServiceMessageSender(new DynamicCredentialsProvider(context), this.messageSender = new SignalServiceMessageSender(new SignalProtocolStoreImpl(context),
new SignalProtocolStoreImpl(context),
TextSecurePreferences.getLocalNumber(context), TextSecurePreferences.getLocalNumber(context),
DatabaseFactory.getLokiAPIDatabase(context), DatabaseFactory.getLokiAPIDatabase(context),
DatabaseFactory.getLokiThreadDatabase(context), DatabaseFactory.getLokiThreadDatabase(context),
@ -89,54 +80,4 @@ public class SignalCommunicationModule {
return this.messageReceiver; 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);
}
}
} }

View File

@ -25,7 +25,6 @@ import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.providers.BlobProvider; import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.BitmapUtil;
import org.session.libsignal.service.api.util.InvalidNumberException;
import org.session.libsignal.service.internal.push.SignalServiceProtos.GroupContext; import org.session.libsignal.service.internal.push.SignalServiceProtos.GroupContext;
import java.util.Collection; import java.util.Collection;
@ -137,7 +136,6 @@ public class GroupManager {
@Nullable Bitmap avatar, @Nullable Bitmap avatar,
@Nullable String name, @Nullable String name,
@NonNull Set<Recipient> admins) @NonNull Set<Recipient> admins)
throws InvalidNumberException
{ {
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context); final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
final Set<Address> memberAddresses = getMemberAddresses(members); final Set<Address> memberAddresses = getMemberAddresses(members);

View File

@ -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";
}
}

View File

@ -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";
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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";
}
}

View File

@ -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();
}
}
}
}

View File

@ -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.SignalServiceAddress;
import org.session.libsignal.service.api.push.exceptions.PushNetworkException; import org.session.libsignal.service.api.push.exceptions.PushNetworkException;
import org.session.libsignal.service.api.push.exceptions.UnregisteredUserException; 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.crypto.PaddingInputStream;
import org.session.libsignal.service.internal.push.OutgoingPushMessage; import org.session.libsignal.service.internal.push.OutgoingPushMessage;
import org.session.libsignal.service.internal.push.OutgoingPushMessageList; 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.AttachmentCipherOutputStreamFactory;
import org.session.libsignal.service.internal.push.http.OutputStreamFactory; import org.session.libsignal.service.internal.push.http.OutputStreamFactory;
import org.session.libsignal.utilities.Base64; 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.service.internal.util.Util;
import org.session.libsignal.utilities.concurrent.SettableFuture; import org.session.libsignal.utilities.concurrent.SettableFuture;
import org.session.libsignal.service.loki.api.LokiDotNetAPI; import org.session.libsignal.service.loki.api.LokiDotNetAPI;
@ -75,7 +73,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import kotlin.Unit; import kotlin.Unit;
import kotlin.jvm.functions.Function1; import kotlin.jvm.functions.Function1;
@ -91,8 +88,6 @@ public class SignalServiceMessageSender {
private static final String TAG = SignalServiceMessageSender.class.getSimpleName(); private static final String TAG = SignalServiceMessageSender.class.getSimpleName();
private final IdentityKeyStore store; private final IdentityKeyStore store;
private final SignalServiceAddress localAddress;
// Loki // Loki
private final String userPublicKey; private final String userPublicKey;
private final LokiAPIDatabaseProtocol apiDatabase; private final LokiAPIDatabaseProtocol apiDatabase;
@ -103,29 +98,7 @@ public class SignalServiceMessageSender {
private final LokiOpenGroupDatabaseProtocol openGroupDatabase; private final LokiOpenGroupDatabaseProtocol openGroupDatabase;
private final Broadcaster broadcaster; private final Broadcaster broadcaster;
/** public SignalServiceMessageSender(IdentityKeyStore store,
* 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,
String userPublicKey, String userPublicKey,
LokiAPIDatabaseProtocol apiDatabase, LokiAPIDatabaseProtocol apiDatabase,
LokiThreadDatabaseProtocol threadDatabase, LokiThreadDatabaseProtocol threadDatabase,
@ -136,7 +109,6 @@ public class SignalServiceMessageSender {
Broadcaster broadcaster) Broadcaster broadcaster)
{ {
this.store = store; this.store = store;
this.localAddress = new SignalServiceAddress(credentialsProvider.getUser());
this.userPublicKey = userPublicKey; this.userPublicKey = userPublicKey;
this.apiDatabase = apiDatabase; this.apiDatabase = apiDatabase;
this.threadDatabase = threadDatabase; this.threadDatabase = threadDatabase;
@ -517,7 +489,6 @@ public class SignalServiceMessageSender {
throws IOException throws IOException
{ {
List<SendMessageResult> results = new LinkedList<>(); List<SendMessageResult> results = new LinkedList<>();
SignalServiceAddress ownAddress = localAddress;
Iterator<SignalServiceAddress> recipientIterator = recipients.iterator(); Iterator<SignalServiceAddress> recipientIterator = recipients.iterator();
Iterator<Optional<UnidentifiedAccess>> unidentifiedAccessIterator = unidentifiedAccess.iterator(); Iterator<Optional<UnidentifiedAccess>> unidentifiedAccessIterator = unidentifiedAccess.iterator();

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -1,5 +0,0 @@
package org.session.libsignal.service.api.util;
public interface SleepTimer {
public void sleep(long millis) throws InterruptedException;
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -1,9 +0,0 @@
package org.session.libsignal.service.api.websocket;
public interface ConnectivityListener {
void onConnected();
void onConnecting();
void onDisconnected();
void onAuthenticationFailure();
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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) + "}";
}
}

View File

@ -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)) + "}";
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}