Sending/Receiving encrypted messages barely works now

This commit is contained in:
Paul Schaub 2020-07-04 19:50:10 +02:00
parent 940a223563
commit 30e7bd46a7
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
11 changed files with 71 additions and 43 deletions

View File

@ -35,7 +35,7 @@
android:label="@string/title_activity_settings" />
<activity android:name=".android.ui.roster.contacts.detail.ContactDetailActivity" />
<service android:name=".android.service.MercuryConnectionService" />
<service android:name=".android.service.MercuryForegroundService" />
</application>
</manifest>

View File

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

View File

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

View File

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

View File

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

View File

@ -61,7 +61,8 @@ public class ContactDetailViewModel extends ViewModel {
private MutableLiveData<String> contactName = new MutableLiveData<>("Alice Wonderland");
private MutableLiveData<String> contactAccountAddress = new MutableLiveData<>("mad@hatter.lit");
private MutableLiveData<List<String>> contactGroups = new MutableLiveData<>(Collections.emptyList());
private MutableLiveData<List<OpenPgpV4Fingerprint>> contactFingerprints = new MutableLiveData<>(Collections.singletonList(new OpenPgpV4Fingerprint("1357B01865B2503C18453D208CAC2A9678548E35")));
private MutableLiveData<List<OpenPgpV4Fingerprint>> contactFingerprints =
new MutableLiveData<>(Collections.singletonList(new OpenPgpV4Fingerprint("1234567890ABCDEF1234567890ABCDEF01234567")));
private Roster roster;

View File

@ -184,8 +184,8 @@ public class RxOpenPgpRepository implements OpenPgpRepository {
@Override
public Observable<List<OpenPgpV4Fingerprint>> 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<Map<OpenPgpV4Fingerprint, Date>> 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<OpenPgpV4Fingerprint, Date> 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<OpenPgpKeyFetchDate> fetchDates =
data.select(OpenPgpKeyFetchDate.class)
.where(OpenPgpKeyFetchDate.ACCOUNT_ID.eq(accountId))
.and(OpenPgpKeyFetchDate.OWNER.eq(owner))
.get()
.toList();
Map<OpenPgpV4Fingerprint, Date> map = new ConcurrentHashMap<>();
for (OpenPgpKeyFetchDate date : fetchDates) {
map.put(date.getFingerprint(), date.getFetchDate());
}
return Single.just(map);
}
}

View File

@ -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) {

View File

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

View File

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

View File

@ -82,7 +82,7 @@ public class MercuryConnectionManager {
this.cryptoManager = cryptoManager;
this.schedulers = schedulers;
//EntityCapsManager.setPersistentCache(entityCapsStore);
EntityCapsManager.setPersistentCache(entityCapsStore);
start();
}