Store and restore OX keys

This commit is contained in:
Paul Schaub 2020-06-15 17:41:13 +02:00
parent 61de3cb22c
commit f208a9f769
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
19 changed files with 310 additions and 215 deletions

View File

@ -3,6 +3,7 @@ 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;
@ -43,7 +44,8 @@ import dagger.Component;
ViewModelModule.class,
XmppTcpConnectionFactoryModule.class,
RxMercuryMessageStoreFactoryModule.class,
RxMercuryRosterStoreFactoryModule.class
RxMercuryRosterStoreFactoryModule.class,
OpenPgpModule.class
})
public interface AppComponent {

View File

@ -5,6 +5,7 @@ import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
import org.mercury_im.messenger.core.data.repository.EntityCapsRepository;
import org.mercury_im.messenger.core.data.repository.GroupChatRepository;
import org.mercury_im.messenger.core.data.repository.MessageRepository;
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
import org.mercury_im.messenger.core.data.repository.PeerRepository;
import org.mercury_im.messenger.core.data.repository.Repositories;
import org.mercury_im.messenger.data.mapping.AccountMapping;
@ -18,6 +19,7 @@ import org.mercury_im.messenger.data.repository.RxDirectChatRepository;
import org.mercury_im.messenger.data.repository.RxEntityCapsRepository;
import org.mercury_im.messenger.data.repository.RxGroupChatRepository;
import org.mercury_im.messenger.data.repository.RxMessageRepository;
import org.mercury_im.messenger.data.repository.RxOpenPgpRepository;
import org.mercury_im.messenger.data.repository.RxPeerRepository;
import javax.inject.Singleton;
@ -84,6 +86,13 @@ public class RepositoryModule {
return new RxEntityCapsRepository(data, entityCapsMapping);
}
@Provides
@Singleton
static OpenPgpRepository provideOpenPgpRepository(
ReactiveEntityStore<Persistable> data) {
return new RxOpenPgpRepository(data);
}
@Provides
@Singleton
static Repositories provideRepositories(
@ -92,8 +101,9 @@ public class RepositoryModule {
GroupChatRepository groupChatRepository,
MessageRepository messageRepository,
PeerRepository peerRepository,
RxEntityCapsRepository entityCapsRepository) {
EntityCapsRepository entityCapsRepository,
OpenPgpRepository openPgpRepository) {
return new Repositories(accountRepository, directChatRepository, groupChatRepository,
messageRepository, peerRepository, entityCapsRepository);
messageRepository, peerRepository, entityCapsRepository, openPgpRepository);
}
}

View File

@ -0,0 +1,27 @@
package org.mercury_im.messenger.data.model;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.data.converter.EntityBareJidConverter;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import java.util.Date;
import java.util.Map;
import io.requery.Column;
import io.requery.Convert;
import io.requery.Entity;
import io.requery.Key;
import io.requery.Table;
@Entity
@Table(name = "ox_key_fetch_dates")
public class AbstractOpenPgpKeyFetchDates {
@Key
@Column(name = "owner")
@Convert(EntityBareJidConverter.class)
EntityBareJid owner;
@Column(name = "fetch_dates")
Map<OpenPgpV4Fingerprint, Date> fetchDates;
}

View File

@ -2,41 +2,18 @@ package org.mercury_im.messenger.data.model;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.data.converter.EntityBareJidConverter;
import org.mercury_im.messenger.data.converter.OpenPgpV4FingerprintConverter;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import java.util.UUID;
import io.requery.CascadeAction;
import io.requery.Column;
import io.requery.Convert;
import io.requery.Entity;
import io.requery.ForeignKey;
import io.requery.Index;
import io.requery.Key;
import io.requery.ManyToOne;
import io.requery.Table;
import io.requery.converter.UUIDConverter;
@Entity
@Table(name = "ox_public_keys")
public class AbstractOpenPgpPublicKeyRing {
@Key
@Convert(UUIDConverter.class)
UUID id;
@Index("unique_address")
@ManyToOne(cascade = CascadeAction.NONE)
@ForeignKey(referencedColumn = "id")
AccountModel account;
@Column(name = "key_id", nullable = false)
long keyId;
@Column(name = "fingerprint", nullable = false)
@Convert(OpenPgpV4FingerprintConverter.class)
OpenPgpV4Fingerprint fingerprint;
@Column(name = "owner", nullable = false)
@Convert(EntityBareJidConverter.class)
EntityBareJid owner;

View File

@ -2,41 +2,18 @@ package org.mercury_im.messenger.data.model;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.data.converter.EntityBareJidConverter;
import org.mercury_im.messenger.data.converter.OpenPgpV4FingerprintConverter;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import java.util.UUID;
import io.requery.CascadeAction;
import io.requery.Column;
import io.requery.Convert;
import io.requery.Entity;
import io.requery.ForeignKey;
import io.requery.Index;
import io.requery.Key;
import io.requery.ManyToOne;
import io.requery.Table;
import io.requery.converter.UUIDConverter;
@Entity
@Table(name = "ox_secret_keys")
public class AbstractOpenPgpSecretKeyRing {
@Key
@Convert(UUIDConverter.class)
UUID id;
@Index("unique_address")
@ManyToOne(cascade = CascadeAction.NONE)
@ForeignKey(referencedColumn = "id")
AccountModel account;
@Column(name = "key_id", nullable = false)
long keyId;
@Column(name = "fingerprint", nullable = false)
@Convert(OpenPgpV4FingerprintConverter.class)
OpenPgpV4Fingerprint fingerprint;
@Column(name = "owner", nullable = false)
@Convert(EntityBareJidConverter.class)
EntityBareJid owner;

View File

@ -1,53 +1,78 @@
package org.mercury_im.messenger.data.repository;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
import org.mercury_im.messenger.data.model.OpenPgpPublicKeyRing;
import org.mercury_im.messenger.data.model.OpenPgpSecretKeyRing;
import org.pgpainless.PGPainless;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import java.util.UUID;
import javax.inject.Inject;
import io.reactivex.Completable;
import io.reactivex.Single;
import io.requery.Persistable;
import io.requery.query.ResultDelegate;
import io.requery.reactivex.ReactiveEntityStore;
public class RxOpenPgpRepository implements OpenPgpRepository {
private final ReactiveEntityStore<Persistable> data;
@Inject
public RxOpenPgpRepository(ReactiveEntityStore<Persistable> data) {
this.data = data;
}
@Override
public Single<PGPPublicKeyRingCollection> loadPublicKeysOfContact(UUID accountId, EntityBareJid jid) {
return data.select(OpenPgpPublicKeyRing.class)
.where(OpenPgpPublicKeyRing.ACCOUNT_ID.eq(accountId))
.and(OpenPgpPublicKeyRing.OWNER.eq(jid))
.get().observableResult()
.map(ResultDelegate::toList)
.map(keys -> PGPainless.readKeyRing().publicKeyRing(keys.get(0).getBytes()).)
public Completable storePublicKeysOf(EntityBareJid owner, PGPPublicKeyRingCollection keys) {
return Single.fromCallable(() -> {
OpenPgpPublicKeyRing keyRing = new OpenPgpPublicKeyRing();
keyRing.setOwner(owner);
keyRing.setBytes(keys.getEncoded());
return keyRing;
}).flatMap(data::upsert).ignoreElement();
}
@Override
public Single<Integer> deletePublicKeyRing(UUID accountId, EntityBareJid jid, OpenPgpV4Fingerprint fingerprint) {
public Single<PGPPublicKeyRingCollection> loadPublicKeysOf(EntityBareJid owner) {
return data.select(OpenPgpPublicKeyRing.class)
.where(OpenPgpPublicKeyRing.OWNER.eq(owner))
.limit(1).get()
.maybe().toSingle()
.map(keyring -> PGPainless.readKeyRing().publicKeyRingCollection(keyring.getBytes()));
}
@Override
public Single<Integer> deletePublicKeysOf(EntityBareJid owner) {
return data.delete(OpenPgpPublicKeyRing.class)
.where(OpenPgpPublicKeyRing.ACCOUNT_ID.eq(accountId))
.and(OpenPgpPublicKeyRing.OWNER.eq(jid))
.and(OpenPgpPublicKeyRing.FINGERPRINT.eq(fingerprint))
.where(OpenPgpPublicKeyRing.OWNER.eq(owner))
.get().single();
}
@Override
public Single<Integer> deleteSecretKeyRing(UUID accountId, EntityBareJid jid, OpenPgpV4Fingerprint fingerprint) {
public Completable storeSecretKeysOf(EntityBareJid owner, PGPSecretKeyRingCollection keys) {
return Single.fromCallable(() -> {
OpenPgpSecretKeyRing keyRing = new OpenPgpSecretKeyRing();
keyRing.setOwner(owner);
keyRing.setBytes(keys.getEncoded());
return keyRing;
}).flatMap(data::upsert).ignoreElement();
}
@Override
public Single<PGPSecretKeyRingCollection> loadSecretKeysOf(EntityBareJid owner) {
return data.select(OpenPgpSecretKeyRing.class)
.where(OpenPgpSecretKeyRing.OWNER.eq(owner))
.limit(1).get()
.maybe().toSingle()
.map(keyring -> PGPainless.readKeyRing().secretKeyRingCollection(keyring.getBytes()));
}
@Override
public Single<Integer> deleteSecretKeysOf(EntityBareJid owner) {
return data.delete(OpenPgpSecretKeyRing.class)
.where(OpenPgpSecretKeyRing.ACCOUNT_ID.eq(accountId))
.and(OpenPgpPublicKeyRing.OWNER.eq(jid))
.and(OpenPgpSecretKeyRing.FINGERPRINT.eq(fingerprint))
.where(OpenPgpPublicKeyRing.OWNER.eq(owner))
.get().single();
}
}

View File

@ -0,0 +1,69 @@
package org.mercury_im.messenger.core.crypto;
import org.jivesoftware.smack.AbstractConnectionListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smackx.ox.OpenPgpManager;
import org.jivesoftware.smackx.ox.crypto.OpenPgpProvider;
import org.jivesoftware.smackx.ox.exception.InvalidBackupCodeException;
import org.jivesoftware.smackx.ox.exception.NoBackupFoundException;
import org.jivesoftware.smackx.ox_im.OXInstantMessagingManager;
import org.jivesoftware.smackx.pubsub.PubSubException;
import org.mercury_im.messenger.core.xmpp.MercuryConnection;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
public class MercuryOpenPgpManager {
private static final Logger LOGGER = Logger.getLogger(MercuryOpenPgpManager.class.getName());
private final OpenPgpProvider openPgpProvider;
@Inject
public MercuryOpenPgpManager(OpenPgpProvider openPgpProvider) {
this.openPgpProvider = openPgpProvider;
}
public void initialize(MercuryConnection connection) {
if (connection.getConnection().isAuthenticated()) {
setup(connection);
} else {
connection.getConnection().addConnectionListener(new AbstractConnectionListener() {
@Override
public void authenticated(XMPPConnection con, boolean resumed) {
if (!resumed) {
setup(connection);
}
}
});
}
}
private void setup(MercuryConnection connection) {
try {
OpenPgpManager oxManager = OpenPgpManager.getInstanceFor(connection.getConnection());
oxManager.setOpenPgpProvider(openPgpProvider);
if (!oxManager.hasSecretKeysAvailable()) {
try {
oxManager.restoreSecretKeyServerBackup(
//() -> "RW8X-367S-A2C3-QYAL-VG6E-Z2IM");
() -> "KISJ-5Z1T-FGDW-WMDK-SC2U-SQUA");
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);
oxManager.generateAndImportKeyPair(connection.getAccount().getJid());
oxManager.backupSecretKeyToServer(
backupCode -> LOGGER.log(Level.INFO, "OpenPGP Backup Code: " + backupCode),
availableSecretKeys -> availableSecretKeys);
}
}
oxManager.announceSupportAndPublish();
OXInstantMessagingManager oximManager = OXInstantMessagingManager.getInstanceFor(connection.getConnection());
oximManager.announceSupportForOxInstantMessaging();
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -1,18 +1,23 @@
package org.mercury_im.messenger.core.data.repository;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.jxmpp.jid.EntityBareJid;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import java.util.UUID;
import io.reactivex.Completable;
import io.reactivex.Single;
public interface OpenPgpRepository {
Single<PGPPublicKeyRingCollection> loadPublicKeysOfContact(UUID accountId, EntityBareJid jid);
Completable storePublicKeysOf(EntityBareJid owner, PGPPublicKeyRingCollection keys);
Single<Integer> deletePublicKeyRing(UUID accountId, EntityBareJid jid, OpenPgpV4Fingerprint fingerprint);
Single<PGPPublicKeyRingCollection> loadPublicKeysOf(EntityBareJid owner);
Single<Integer> deleteSecretKeyRing(UUID accountId, EntityBareJid jid, OpenPgpV4Fingerprint fingerprint);
Single<Integer> deletePublicKeysOf(EntityBareJid owner);
Completable storeSecretKeysOf(EntityBareJid owner, PGPSecretKeyRingCollection keys);
Single<PGPSecretKeyRingCollection> loadSecretKeysOf(EntityBareJid owner);
Single<Integer> deleteSecretKeysOf(EntityBareJid owner);
}

View File

@ -3,15 +3,19 @@ package org.mercury_im.messenger.core.data.repository;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.Value;
@Singleton
@Value
public class Repositories {
private final AccountRepository accountRepository;
private final DirectChatRepository directChatRepository;
private final GroupChatRepository groupChatRepository;
private final MessageRepository messageRepository;
private final PeerRepository peerRepository;
private final EntityCapsRepository entityCapsRepository;
AccountRepository accountRepository;
DirectChatRepository directChatRepository;
GroupChatRepository groupChatRepository;
MessageRepository messageRepository;
PeerRepository peerRepository;
EntityCapsRepository entityCapsRepository;
OpenPgpRepository openPgpRepository;
@Inject
public Repositories(AccountRepository accountRepository,
@ -19,36 +23,14 @@ public class Repositories {
GroupChatRepository groupChatRepository,
MessageRepository messageRepository,
PeerRepository peerRepository,
EntityCapsRepository entityCapsRepository) {
EntityCapsRepository entityCapsRepository,
OpenPgpRepository openPgpRepository) {
this.accountRepository = accountRepository;
this.directChatRepository = directChatRepository;
this.groupChatRepository = groupChatRepository;
this.messageRepository = messageRepository;
this.peerRepository = peerRepository;
this.entityCapsRepository = entityCapsRepository;
}
public AccountRepository getAccountRepository() {
return accountRepository;
}
public DirectChatRepository getDirectChatRepository() {
return directChatRepository;
}
public GroupChatRepository getGroupChatRepository() {
return groupChatRepository;
}
public MessageRepository getMessageRepository() {
return messageRepository;
}
public PeerRepository getPeerRepository() {
return peerRepository;
}
public EntityCapsRepository getEntityCapsRepository() {
return entityCapsRepository;
this.openPgpRepository = openPgpRepository;
}
}

View File

@ -0,0 +1,29 @@
package org.mercury_im.messenger.core.di.module;
import org.jivesoftware.smackx.ox.crypto.OpenPgpProvider;
import org.jivesoftware.smackx.ox.crypto.PainlessOpenPgpProvider;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
import org.mercury_im.messenger.core.store.crypto.MercuryOpenPgpStore;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class OpenPgpModule {
@Provides
@Singleton
static OpenPgpStore provideOpenPgpStore(OpenPgpRepository openPgpRepository, SchedulersFacade schedulersFacade) {
return new MercuryOpenPgpStore(openPgpRepository, schedulersFacade);
}
@Provides
@Singleton
static OpenPgpProvider provideOpenPgpProvider(OpenPgpStore openPgpStore) {
return new PainlessOpenPgpProvider(openPgpStore);
}
}

View File

@ -1,136 +1,106 @@
package org.mercury_im.messenger.core.store.crypto;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.jivesoftware.smackx.ox.OpenPgpContact;
import org.jivesoftware.smackx.ox.callback.SecretKeyPassphraseCallback;
import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
import org.jivesoftware.smackx.ox.store.abstr.AbstractOpenPgpKeyStore;
import org.jivesoftware.smackx.ox.store.abstr.AbstractOpenPgpMetadataStore;
import org.jivesoftware.smackx.ox.store.abstr.AbstractOpenPgpStore;
import org.jivesoftware.smackx.ox.store.abstr.AbstractOpenPgpTrustStore;
import org.jxmpp.jid.BareJid;
import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.key.collection.PGPKeyRing;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.key.protection.UnprotectedKeysProtector;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.NoSuchElementException;
import javax.inject.Inject;
public class MercuryOpenPgpStore implements OpenPgpStore {
public class MercuryOpenPgpStore extends AbstractOpenPgpStore {
private final UUID accountId;
private SecretKeyRingProtector keyRingProtector;
private SecretKeyPassphraseCallback passphraseCallback;
private final OpenPgpRepository repository;
private final SchedulersFacade schedulers;
@Inject
OpenPgpRepository repository;
public MercuryOpenPgpStore(OpenPgpRepository repository, SchedulersFacade schedulers) {
super(new AbstractOpenPgpKeyStore() {
@Override
protected PGPPublicKeyRingCollection readPublicKeysOf(BareJid owner)
throws IOException, PGPException {
try {
return repository.loadPublicKeysOf(owner.asEntityBareJidIfPossible())
.blockingGet();
} catch (NoSuchElementException e) {
return null;
}
}
public MercuryOpenPgpStore(UUID accountId) {
this.accountId = accountId;
}
@Override
protected void writePublicKeysOf(BareJid owner, PGPPublicKeyRingCollection publicKeys)
throws IOException {
repository.storePublicKeysOf(owner.asEntityBareJidIfPossible(), publicKeys)
.subscribeOn(schedulers.getIoScheduler()).subscribe();
}
@Override
public OpenPgpContact getOpenPgpContact(BareJid contactsJid) {
return null;
}
@Override
protected PGPSecretKeyRingCollection readSecretKeysOf(BareJid owner)
throws IOException, PGPException {
try {
return repository.loadSecretKeysOf(owner.asEntityBareJidIfPossible())
.blockingGet();
} catch (NoSuchElementException e) {
return null;
}
}
@Override
public void setKeyRingProtector(SecretKeyRingProtector unlocker) {
this.keyRingProtector = unlocker;
}
@Override
protected void writeSecretKeysOf(BareJid owner, PGPSecretKeyRingCollection secretKeys)
throws IOException {
repository.storeSecretKeysOf(owner.asEntityBareJidIfPossible(), secretKeys)
.subscribeOn(schedulers.getIoScheduler()).subscribe();
}
@Override
public SecretKeyRingProtector getKeyRingProtector() {
return keyRingProtector;
}
@Override
protected Map<OpenPgpV4Fingerprint, Date> readKeyFetchDates(BareJid owner)
throws IOException {
return new HashMap<>();
}
@Override
public void setSecretKeyPassphraseCallback(SecretKeyPassphraseCallback callback) {
passphraseCallback = callback;
}
@Override
protected void writeKeyFetchDates(BareJid owner, Map<OpenPgpV4Fingerprint, Date> dates)
throws IOException {
@Override
public PGPPublicKeyRingCollection getPublicKeysOf(BareJid owner) throws IOException, PGPException {
return null;
}
}
}, new AbstractOpenPgpMetadataStore() {
@Override
protected Map<OpenPgpV4Fingerprint, Date> readAnnouncedFingerprintsOf(BareJid contact)
throws IOException {
return null;
}
@Override
public PGPSecretKeyRingCollection getSecretKeysOf(BareJid owner) throws IOException, PGPException {
return null;
}
@Override
protected void writeAnnouncedFingerprintsOf(BareJid contact, Map<OpenPgpV4Fingerprint, Date> metadata)
throws IOException {
@Override
public PGPPublicKeyRing getPublicKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException {
return null;
}
}
}, new AbstractOpenPgpTrustStore() {
@Override
protected Trust readTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint)
throws IOException {
return Trust.trusted;
}
@Override
public PGPSecretKeyRing getSecretKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException {
return null;
}
@Override
public void deletePublicKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException {
}
@Override
public void deleteSecretKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException {
}
@Override
public PGPKeyRing generateKeyRing(BareJid owner) throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
return null;
}
@Override
public void importSecretKey(BareJid owner, PGPSecretKeyRing secretKeys) throws IOException, PGPException, MissingUserIdOnKeyException {
}
@Override
public void importPublicKey(BareJid owner, PGPPublicKeyRing publicKeys) throws IOException, PGPException, MissingUserIdOnKeyException {
}
@Override
public Map<OpenPgpV4Fingerprint, Date> getPublicKeyFetchDates(BareJid contact) throws IOException {
return null;
}
@Override
public void setPublicKeyFetchDates(BareJid contact, Map<OpenPgpV4Fingerprint, Date> dates) throws IOException {
}
@Override
public Map<OpenPgpV4Fingerprint, Date> getAnnouncedFingerprintsOf(BareJid contact) throws IOException {
return null;
}
@Override
public void setAnnouncedFingerprintsOf(BareJid contact, Map<OpenPgpV4Fingerprint, Date> data) throws IOException {
}
@Override
public Trust getTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException {
return null;
}
@Override
public void setTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint, Trust trust) throws IOException {
@Override
protected void writeTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint, Trust trust)
throws IOException {
}
});
this.repository = repository;
this.schedulers = schedulers;
}
}

View File

@ -76,7 +76,7 @@ public class MercuryMessageStore implements IncomingChatMessageListener, Outgoin
message.setSender(account.getAddress());
message.setRecipient(to.asBareJid().toString());
if (smackMessage.getBody() != null) {
message.setBody(smackMessage.getBody().getMessage());
message.setBody(smackMessage.getBody());
}
disposable.add(writeMessageToStore(to.asEntityBareJidString(), message));
}

View File

@ -3,6 +3,7 @@ package org.mercury_im.messenger.core.xmpp;
import org.jivesoftware.smack.chat2.ChatManager;
import org.jivesoftware.smackx.caps.EntityCapsManager;
import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.crypto.MercuryOpenPgpManager;
import org.mercury_im.messenger.core.data.repository.AccountRepository;
import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
import org.mercury_im.messenger.core.data.repository.MessageRepository;
@ -48,6 +49,7 @@ public class MercuryConnectionManager {
private final PeerRepository peerRepository;
private final DirectChatRepository directChatRepository;
private final MessageRepository messageRepository;
private final MercuryOpenPgpManager cryptoManager;
private final SchedulersFacade schedulers;
private final Map<UUID, MercuryConnection> connectionsMap = new ConcurrentHashMap<>();
@ -67,6 +69,7 @@ public class MercuryConnectionManager {
MercuryEntityCapsStore entityCapsStore,
MercuryMessageStoreFactory messageStoreFactory,
XmppConnectionFactory connectionFactory,
MercuryOpenPgpManager cryptoManager,
SchedulersFacade schedulers) {
this.accountRepository = repositories.getAccountRepository();
this.rosterStoreBinder = rosterStoreBinder;
@ -76,6 +79,7 @@ public class MercuryConnectionManager {
this.messageRepository = repositories.getMessageRepository();
this.connectionFactory = connectionFactory;
this.messageStoreFactory = messageStoreFactory;
this.cryptoManager = cryptoManager;
this.schedulers = schedulers;
EntityCapsManager.setPersistentCache(entityCapsStore);
@ -156,7 +160,7 @@ public class MercuryConnectionManager {
chatManager.addIncomingListener(mercuryMessageStore);
chatManager.addOutgoingListener(mercuryMessageStore);
}));
cryptoManager.initialize(connection);
}
private void handleOptionalAccountChangedEvent(MercuryConnection connection, Optional<Account> event) {

View File

@ -1,6 +1,7 @@
package org.mercury_im.messenger.core.xmpp;
import org.jivesoftware.smack.ReconnectionManager;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.roster.Roster;
import org.jivesoftware.smackx.carbons.CarbonManager;
import org.jivesoftware.smackx.iqversion.VersionManager;
@ -11,6 +12,7 @@ import org.jivesoftware.smackx.sid.StableUniqueStanzaIdManager;
public class SmackConfig {
static void staticConfiguration() {
SmackConfiguration.DEBUG = true;
ReconnectionManager.setEnabledPerDefault(true);
ReconnectionManager.setDefaultReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.RANDOM_INCREASING_DELAY);

View File

@ -3,6 +3,8 @@ apply plugin: 'java-library'
dependencies {
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
implementation "org.jxmpp:jxmpp-jid:$jxmppVersion"
}
sourceCompatibility = "8"

View File

@ -1,5 +1,8 @@
package org.mercury_im.messenger.entity;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import java.util.UUID;
import lombok.Data;
@ -21,4 +24,8 @@ public class Account {
this.id = UUID.randomUUID();
this.rosterVersion = "";
}
public EntityBareJid getJid() {
return JidCreate.entityBareFromOrThrowUnchecked(getAddress());
}
}

View File

@ -1,5 +1,7 @@
package org.mercury_im.messenger.entity.contact;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.mercury_im.messenger.entity.Account;
import java.util.List;
@ -32,4 +34,8 @@ public class Peer {
}
return address.substring(0, address.indexOf('@'));
}
public EntityBareJid getJid() {
return JidCreate.entityBareFromOrThrowUnchecked(getAddress());
}
}

@ -1 +1 @@
Subproject commit 219efa564c222b7add06870bb51ba85dfe353cc7
Subproject commit 58ce1dd62f11b40a7063802fa079d827c90b0f84

View File

@ -4,6 +4,7 @@ ext {
// Smack Versions
// Quickly switch between unique and normal releases using the toggle below
jxmppVersion = '0.7.0-alpha6'
// Version Strings for non-unique releases
//*
smackVersion = shortVersion