From 30e7bd46a799c43991aed70221756cf581d0e0f0 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Sat, 4 Jul 2020 19:50:10 +0200 Subject: [PATCH] Sending/Receiving encrypted messages barely works now --- app/src/main/AndroidManifest.xml | 2 +- .../android/MercuryImApplication.java | 15 +++------ .../android/di/component/AppComponent.java | 5 ++- ...ice.java => MercuryForegroundService.java} | 16 +++++----- .../android/ui/chat/AndroidChatViewModel.java | 2 +- .../detail/ContactDetailViewModel.java | 3 +- .../data/repository/RxOpenPgpRepository.java | 31 +++++++++---------- .../mercury_im/messenger/core/Messenger.java | 24 ++++++++++++++ .../core/crypto/MercuryOpenPgpManager.java | 7 +++++ .../store/message/MercuryMessageStore.java | 7 +++++ .../core/xmpp/MercuryConnectionManager.java | 2 +- 11 files changed, 71 insertions(+), 43 deletions(-) rename app/src/main/java/org/mercury_im/messenger/android/service/{MercuryConnectionService.java => MercuryForegroundService.java} (86%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bfc8e61..844307c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -35,7 +35,7 @@ android:label="@string/title_activity_settings" /> - + \ No newline at end of file diff --git a/app/src/main/java/org/mercury_im/messenger/android/MercuryImApplication.java b/app/src/main/java/org/mercury_im/messenger/android/MercuryImApplication.java index a2ddb3e..2ecad3f 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/MercuryImApplication.java +++ b/app/src/main/java/org/mercury_im/messenger/android/MercuryImApplication.java @@ -11,7 +11,7 @@ import org.mercury_im.messenger.core.data.repository.AccountRepository; import org.mercury_im.messenger.android.di.component.AppComponent; import org.mercury_im.messenger.android.di.module.AppModule; import org.mercury_im.messenger.entity.Account; -import org.mercury_im.messenger.android.service.MercuryConnectionService; +import org.mercury_im.messenger.android.service.MercuryForegroundService; import org.mercury_im.messenger.core.xmpp.CsiManager; import java.util.List; @@ -23,11 +23,6 @@ import io.reactivex.disposables.CompositeDisposable; public class MercuryImApplication extends Application { - static { - // Initialize Smack etc. - // new MercuryConfiguration(); - } - private static MercuryImApplication INSTANCE; private AppComponent appComponent; private ClientStateHandler clientStateHandler = new ClientStateHandler(); @@ -105,8 +100,8 @@ public class MercuryImApplication extends Application { } private void startForegroundService() { - Intent startIntent = new Intent(getApplicationContext(), MercuryConnectionService.class); - startIntent.setAction(MercuryConnectionService.ACTION_START); + Intent startIntent = new Intent(getApplicationContext(), MercuryForegroundService.class); + startIntent.setAction(MercuryForegroundService.ACTION_START); if (Build.VERSION.SDK_INT < 26) { startService(startIntent); } else { @@ -115,8 +110,8 @@ public class MercuryImApplication extends Application { } private void stopForegroundService() { - Intent stopIntent = new Intent(getApplicationContext(), MercuryConnectionService.class); - stopIntent.setAction(MercuryConnectionService.ACTION_STOP); + Intent stopIntent = new Intent(getApplicationContext(), MercuryForegroundService.class); + stopIntent.setAction(MercuryForegroundService.ACTION_STOP); startService(stopIntent); } } diff --git a/app/src/main/java/org/mercury_im/messenger/android/di/component/AppComponent.java b/app/src/main/java/org/mercury_im/messenger/android/di/component/AppComponent.java index 269f449..ea553f7 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/di/component/AppComponent.java +++ b/app/src/main/java/org/mercury_im/messenger/android/di/component/AppComponent.java @@ -3,14 +3,13 @@ package org.mercury_im.messenger.android.di.component; import org.mercury_im.messenger.android.MercuryImApplication; import org.mercury_im.messenger.android.di.module.AndroidDatabaseModule; import org.mercury_im.messenger.android.di.module.AndroidSchedulersModule; -import org.mercury_im.messenger.core.di.module.OpenPgpModule; import org.mercury_im.messenger.core.di.module.RxMercuryMessageStoreFactoryModule; import org.mercury_im.messenger.core.di.module.RxMercuryRosterStoreFactoryModule; import org.mercury_im.messenger.core.di.module.XmppTcpConnectionFactoryModule; import org.mercury_im.messenger.data.di.RepositoryModule; import org.mercury_im.messenger.android.di.module.AppModule; import org.mercury_im.messenger.core.di.module.ViewModelModule; -import org.mercury_im.messenger.android.service.MercuryConnectionService; +import org.mercury_im.messenger.android.service.MercuryForegroundService; import org.mercury_im.messenger.core.store.caps.MercuryEntityCapsStore; import org.mercury_im.messenger.android.ui.MainActivity; import org.mercury_im.messenger.android.ui.account.AndroidAccountsViewModel; @@ -90,7 +89,7 @@ public interface AppComponent { // Services - void inject(MercuryConnectionService service); + void inject(MercuryForegroundService service); void inject(MercuryEntityCapsStore store); } diff --git a/app/src/main/java/org/mercury_im/messenger/android/service/MercuryConnectionService.java b/app/src/main/java/org/mercury_im/messenger/android/service/MercuryForegroundService.java similarity index 86% rename from app/src/main/java/org/mercury_im/messenger/android/service/MercuryConnectionService.java rename to app/src/main/java/org/mercury_im/messenger/android/service/MercuryForegroundService.java index f2ee92b..1585380 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/service/MercuryConnectionService.java +++ b/app/src/main/java/org/mercury_im/messenger/android/service/MercuryForegroundService.java @@ -10,21 +10,19 @@ import android.os.IBinder; import androidx.annotation.NonNull; import androidx.core.app.NotificationCompat; -import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smackx.ping.android.ServerPingWithAlarmManager; +import org.mercury_im.messenger.R; import org.mercury_im.messenger.android.MercuryImApplication; import org.mercury_im.messenger.android.Notifications; -import org.mercury_im.messenger.R; import org.mercury_im.messenger.android.ui.MainActivity; /** - * Started, Bound Service, which is responsible for managing {@link XMPPConnection XMPPConnections} - * affiliated with registered accounts. + * Started, Bound Service, which is responsible keeping the application alive when the app is not open. */ -public class MercuryConnectionService extends Service { +public class MercuryForegroundService extends Service { private static final String APP = "org.mercury-im.messenger"; - private static final String SERVICE = APP + ".MercuryConnectionService"; + private static final String SERVICE = APP + ".MercuryForegroundService"; private static final String ACTION = SERVICE + ".ACTION"; @@ -105,13 +103,13 @@ public class MercuryConnectionService extends Service { public class Binder extends android.os.Binder { - private final MercuryConnectionService service; + private final MercuryForegroundService service; - public Binder(MercuryConnectionService service) { + public Binder(MercuryForegroundService service) { this.service = service; } - public MercuryConnectionService getService() { + public MercuryForegroundService getService() { return service; } } diff --git a/app/src/main/java/org/mercury_im/messenger/android/ui/chat/AndroidChatViewModel.java b/app/src/main/java/org/mercury_im/messenger/android/ui/chat/AndroidChatViewModel.java index 517afc6..8df6167 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/ui/chat/AndroidChatViewModel.java +++ b/app/src/main/java/org/mercury_im/messenger/android/ui/chat/AndroidChatViewModel.java @@ -133,7 +133,7 @@ public class AndroidChatViewModel extends ViewModel implements MercuryAndroidVie } public void sendMessage(String body) { - disposable.add(messenger.sendMessage(getContact().getValue(), body) + disposable.add(messenger.sendEncryptedMessage(getContact().getValue(), body) .subscribeOn(schedulers.getIoScheduler()) .observeOn(schedulers.getUiScheduler()) .subscribe()); diff --git a/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailViewModel.java b/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailViewModel.java index 334d0d8..25d52e0 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailViewModel.java +++ b/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailViewModel.java @@ -61,7 +61,8 @@ public class ContactDetailViewModel extends ViewModel { private MutableLiveData contactName = new MutableLiveData<>("Alice Wonderland"); private MutableLiveData contactAccountAddress = new MutableLiveData<>("mad@hatter.lit"); private MutableLiveData> contactGroups = new MutableLiveData<>(Collections.emptyList()); - private MutableLiveData> contactFingerprints = new MutableLiveData<>(Collections.singletonList(new OpenPgpV4Fingerprint("1357B01865B2503C18453D208CAC2A9678548E35"))); + private MutableLiveData> contactFingerprints = + new MutableLiveData<>(Collections.singletonList(new OpenPgpV4Fingerprint("1234567890ABCDEF1234567890ABCDEF01234567"))); private Roster roster; diff --git a/data/src/main/java/org/mercury_im/messenger/data/repository/RxOpenPgpRepository.java b/data/src/main/java/org/mercury_im/messenger/data/repository/RxOpenPgpRepository.java index f6f993e..d02eee5 100644 --- a/data/src/main/java/org/mercury_im/messenger/data/repository/RxOpenPgpRepository.java +++ b/data/src/main/java/org/mercury_im/messenger/data/repository/RxOpenPgpRepository.java @@ -184,8 +184,8 @@ public class RxOpenPgpRepository implements OpenPgpRepository { @Override public Observable> observeFingerprintsOf(UUID accountId, String peerAddress) { return data.select(OpenPgpPublicKeyRing.class) - //.where(OpenPgpPublicKeyRing.ACCOUNT_ID.eq(accountId)) - .where(OpenPgpPublicKeyRing.OWNER.eq(JidCreate.entityBareFromOrThrowUnchecked(peerAddress))) + .where(OpenPgpPublicKeyRing.ACCOUNT_ID.eq(accountId)) + .and(OpenPgpPublicKeyRing.OWNER.eq(JidCreate.entityBareFromOrThrowUnchecked(peerAddress))) .get().observableResult() .map(result -> { OpenPgpPublicKeyRing model = new ResultDelegate<>(result).firstOrNull(); @@ -203,20 +203,17 @@ public class RxOpenPgpRepository implements OpenPgpRepository { @Override public Single> loadPublicKeyFetchDates(UUID accountId, EntityBareJid owner) { - return data.select(OpenPgpKeyFetchDate.class) - .where(OpenPgpKeyFetchDate.ACCOUNT_ID.eq(accountId)) - .and(OpenPgpKeyFetchDate.OWNER.eq(owner)) - .get() - .observableResult() - .map(ResultDelegate::toList) - .single(Collections.emptyList()) - .map(list -> { - Map map = new ConcurrentHashMap<>(); - for (OpenPgpKeyFetchDate date : list) { - map.put(date.getFingerprint(), date.getFetchDate()); - } - return map; - }) - .doOnError(e -> Logger.getLogger(RxOpenPgpRepository.class.getName()).log(Level.SEVERE, "Error observing public keys", e)); + List fetchDates = + data.select(OpenPgpKeyFetchDate.class) + .where(OpenPgpKeyFetchDate.ACCOUNT_ID.eq(accountId)) + .and(OpenPgpKeyFetchDate.OWNER.eq(owner)) + .get() + .toList(); + + Map map = new ConcurrentHashMap<>(); + for (OpenPgpKeyFetchDate date : fetchDates) { + map.put(date.getFingerprint(), date.getFetchDate()); + } + return Single.just(map); } } diff --git a/domain/src/main/java/org/mercury_im/messenger/core/Messenger.java b/domain/src/main/java/org/mercury_im/messenger/core/Messenger.java index 88b8f2a..b9ff192 100644 --- a/domain/src/main/java/org/mercury_im/messenger/core/Messenger.java +++ b/domain/src/main/java/org/mercury_im/messenger/core/Messenger.java @@ -1,10 +1,14 @@ package org.mercury_im.messenger.core; +import org.bouncycastle.openpgp.PGPException; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.chat2.ChatManager; import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.roster.RosterEntry; +import org.jivesoftware.smackx.ox.OpenPgpContact; +import org.jivesoftware.smackx.ox.OpenPgpManager; +import org.jivesoftware.smackx.ox_im.OXInstantMessagingManager; import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.stringprep.XmppStringprepException; @@ -14,7 +18,9 @@ import org.mercury_im.messenger.core.exception.ContactAlreadyAddedException; import org.mercury_im.messenger.core.xmpp.MercuryConnection; import org.mercury_im.messenger.core.xmpp.MercuryConnectionManager; import org.mercury_im.messenger.entity.contact.Peer; +import org.pgpainless.key.OpenPgpV4Fingerprint; +import java.io.IOException; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; @@ -110,6 +116,24 @@ public class Messenger { .send(body); } + public Completable sendEncryptedMessage(Peer contact, String body) { + return Completable.fromAction(() -> doSendEncryptedMessage(contact, body)); + } + + public void doSendEncryptedMessage(Peer contact, String body) throws ConnectionNotFoundException, + InterruptedException, PGPException, SmackException.NotConnectedException, + SmackException.NotLoggedInException, IOException { + MercuryConnection connection = getConnection(contact.getAccount().getId()); + OpenPgpManager oxManager = OpenPgpManager.getInstanceFor(connection.getConnection()); + OXInstantMessagingManager oximManager = OXInstantMessagingManager.getInstanceFor(connection.getConnection()); + OpenPgpContact oxContact = oxManager.getOpenPgpContact(contact.getJid()); + for (OpenPgpV4Fingerprint fingerprint : oxContact.getUndecidedFingerprints()) { + oxContact.trust(fingerprint); + } + oxContact.getAnnouncedPublicKeys(); + oximManager.sendOxMessage(oxManager.getOpenPgpContact(contact.getJid()), body); + } + private MercuryConnection getConnection(UUID accountId) throws ConnectionNotFoundException { MercuryConnection connection = getConnectionManager().getConnection(accountId); if (connection == null) { diff --git a/domain/src/main/java/org/mercury_im/messenger/core/crypto/MercuryOpenPgpManager.java b/domain/src/main/java/org/mercury_im/messenger/core/crypto/MercuryOpenPgpManager.java index ef91ed8..d58cc16 100644 --- a/domain/src/main/java/org/mercury_im/messenger/core/crypto/MercuryOpenPgpManager.java +++ b/domain/src/main/java/org/mercury_im/messenger/core/crypto/MercuryOpenPgpManager.java @@ -1,5 +1,7 @@ package org.mercury_im.messenger.core.crypto; +import org.bouncycastle.openpgp.PGPPublicKeyRing; +import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; import org.jivesoftware.smack.AbstractConnectionListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smackx.ox.OpenPgpManager; @@ -17,6 +19,7 @@ import org.mercury_im.messenger.core.data.repository.Repositories; import org.mercury_im.messenger.core.store.crypto.MercuryOpenPgpStore; import org.mercury_im.messenger.core.store.message.MercuryMessageStore; import org.mercury_im.messenger.core.xmpp.MercuryConnection; +import org.pgpainless.key.OpenPgpV4Fingerprint; import java.util.logging.Level; import java.util.logging.Logger; @@ -70,6 +73,10 @@ public class MercuryOpenPgpManager { //() -> "RW8X-367S-A2C3-QYAL-VG6E-Z2IM"); //() -> "KISJ-5Z1T-FGDW-WMDK-SC2U-SQUA"); () -> "71ZA-Y416-UA7A-7NCE-3SNM-88EF"); + PGPPublicKeyRingCollection keys = oxManager.getOpenPgpSelf().getAnyPublicKeys(); + for (PGPPublicKeyRing key : keys) { + oxManager.getOpenPgpSelf().trust(new OpenPgpV4Fingerprint(key)); + } LOGGER.log(Level.INFO, "Successfully restored secret key backup!"); } catch (NoBackupFoundException | PubSubException.NotALeafNodeException | InvalidBackupCodeException e) { LOGGER.log(Level.INFO, "Error restoring secret key backup.", e); diff --git a/domain/src/main/java/org/mercury_im/messenger/core/store/message/MercuryMessageStore.java b/domain/src/main/java/org/mercury_im/messenger/core/store/message/MercuryMessageStore.java index 7aa9010..e417f71 100644 --- a/domain/src/main/java/org/mercury_im/messenger/core/store/message/MercuryMessageStore.java +++ b/domain/src/main/java/org/mercury_im/messenger/core/store/message/MercuryMessageStore.java @@ -4,6 +4,7 @@ import org.jivesoftware.smack.chat2.IncomingChatMessageListener; import org.jivesoftware.smack.chat2.OutgoingChatMessageListener; import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smackx.delay.packet.DelayInformation; +import org.jivesoftware.smackx.eme.element.ExplicitMessageEncryptionElement; import org.jivesoftware.smackx.ox.OpenPgpContact; import org.jivesoftware.smackx.ox.element.SigncryptElement; import org.jivesoftware.smackx.ox_im.OxMessageListener; @@ -58,6 +59,9 @@ public class MercuryMessageStore implements IncomingChatMessageListener, Outgoin public void newIncomingMessage(EntityBareJid from, org.jivesoftware.smack.packet.Message smackMessage, org.jivesoftware.smack.chat2.Chat smackChat) { + if (ExplicitMessageEncryptionElement.from(smackMessage) != null) { + return; + } Message message = new Message(); message.setDirection(MessageDirection.incoming); DelayInformation delayInformation = DelayInformation.from(smackMessage); @@ -74,6 +78,9 @@ public class MercuryMessageStore implements IncomingChatMessageListener, Outgoin public void newOutgoingMessage(EntityBareJid to, MessageBuilder smackMessage, org.jivesoftware.smack.chat2.Chat smackChat) { + if (smackMessage.hasExtension(ExplicitMessageEncryptionElement.QNAME)) { + return; + } Message message = new Message(); message.setDirection(MessageDirection.outgoing); message.setTimestamp(new Date()); diff --git a/domain/src/main/java/org/mercury_im/messenger/core/xmpp/MercuryConnectionManager.java b/domain/src/main/java/org/mercury_im/messenger/core/xmpp/MercuryConnectionManager.java index 506ee5d..a917961 100644 --- a/domain/src/main/java/org/mercury_im/messenger/core/xmpp/MercuryConnectionManager.java +++ b/domain/src/main/java/org/mercury_im/messenger/core/xmpp/MercuryConnectionManager.java @@ -82,7 +82,7 @@ public class MercuryConnectionManager { this.cryptoManager = cryptoManager; this.schedulers = schedulers; - //EntityCapsManager.setPersistentCache(entityCapsStore); + EntityCapsManager.setPersistentCache(entityCapsStore); start(); }