107 lines
5.5 KiB
Java
107 lines
5.5 KiB
Java
package org.mercury_im.messenger.core.store.crypto;
|
|
|
|
import org.jivesoftware.smackx.ikey.record.IkeyRecord;
|
|
import org.jivesoftware.smackx.ox.store.abstr.AbstractOpenPgpTrustStore;
|
|
import org.jxmpp.jid.BareJid;
|
|
import org.jxmpp.jid.EntityBareJid;
|
|
import org.mercury_im.messenger.core.SchedulersFacade;
|
|
import org.mercury_im.messenger.core.crypto.ikey.IkeyRepository;
|
|
import org.mercury_im.messenger.core.data.repository.IkeyKeyRepository;
|
|
import org.mercury_im.messenger.core.data.repository.IkeyRecordRepository;
|
|
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
|
|
import org.mercury_im.messenger.core.data.repository.OpenPgpTrustRepository;
|
|
import org.pgpainless.key.OpenPgpV4Fingerprint;
|
|
|
|
import java.io.IOException;
|
|
import java.util.UUID;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
|
|
import io.reactivex.Completable;
|
|
import io.reactivex.Maybe;
|
|
import io.reactivex.Single;
|
|
import io.reactivex.disposables.CompositeDisposable;
|
|
|
|
public class IkeyAwareOpenPgpStore extends MercuryOpenPgpStore {
|
|
|
|
public IkeyAwareOpenPgpStore(UUID accountId,
|
|
OpenPgpRepository openPgpRepository,
|
|
OpenPgpTrustRepository openPgpTrustRepository,
|
|
IkeyRepository ikeyRepository,
|
|
SchedulersFacade schedulersFacade) {
|
|
this(accountId, openPgpRepository, openPgpTrustRepository, ikeyRepository, ikeyRepository, schedulersFacade);
|
|
}
|
|
|
|
public IkeyAwareOpenPgpStore(UUID accountId,
|
|
OpenPgpRepository openPgpRepository,
|
|
OpenPgpTrustRepository openPgpTrustRepository,
|
|
IkeyKeyRepository ikeyKeyRepository,
|
|
IkeyRecordRepository ikeyRecordRepository,
|
|
SchedulersFacade schedulers) {
|
|
super(new KeyStore(accountId, openPgpRepository, schedulers),
|
|
new MetadataStore(accountId, openPgpRepository, schedulers),
|
|
new TrustStore(accountId, openPgpTrustRepository, ikeyKeyRepository, ikeyRecordRepository, schedulers));
|
|
}
|
|
|
|
public static class TrustStore extends AbstractOpenPgpTrustStore {
|
|
|
|
private static final Logger LOGGER = Logger.getLogger(TrustStore.class.getName());
|
|
|
|
private final UUID accountId;
|
|
private final OpenPgpTrustRepository openPgpTrustRepository;
|
|
private final IkeyKeyRepository ikeyKeyRepository;
|
|
private final IkeyRecordRepository ikeyRecordRepository;
|
|
private final SchedulersFacade schedulers;
|
|
|
|
private final CompositeDisposable disposable = new CompositeDisposable();
|
|
|
|
public TrustStore(UUID accountId, OpenPgpTrustRepository openPgpTrustRepository, IkeyKeyRepository ikeyKeyRepository, IkeyRecordRepository ikeyRecordRepository, SchedulersFacade schedulersFacade) {
|
|
this.accountId = accountId;
|
|
this.openPgpTrustRepository = openPgpTrustRepository;
|
|
this.ikeyKeyRepository = ikeyKeyRepository;
|
|
this.ikeyRecordRepository = ikeyRecordRepository;
|
|
this.schedulers = schedulersFacade;
|
|
}
|
|
|
|
@Override
|
|
protected Trust readTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException {
|
|
EntityBareJid jid = owner.asEntityBareJidOrThrow();
|
|
Trust trust = readIkeyTrust(jid, fingerprint)
|
|
.blockingGet();
|
|
return trust == null ? Trust.undecided : trust;
|
|
}
|
|
|
|
private Single<Trust> readIkeyTrust(EntityBareJid owner, OpenPgpV4Fingerprint fingerprint) {
|
|
return ikeyRecordRepository.loadRecord(accountId, owner)
|
|
.filter(record -> record.getTrust() == Trust.trusted)
|
|
.filter(record -> record.hasSubordinate(fingerprint))
|
|
.map(IkeyRecord::getTrust)
|
|
.map(trust -> trust == Trust.trusted ? Trust.ikey_trusted : trust)
|
|
.firstElement()
|
|
.flatMap(t -> t == Trust.undecided ? readManualTrust(owner, fingerprint).toMaybe() : Maybe.just(t))
|
|
.switchIfEmpty(readManualTrust(owner, fingerprint));
|
|
}
|
|
|
|
private Single<Trust> readManualTrust(EntityBareJid owner, OpenPgpV4Fingerprint fingerprint) {
|
|
return openPgpTrustRepository.loadTrust(accountId, owner, fingerprint)
|
|
.doOnSuccess(trust -> LOGGER.log(Level.INFO, "Read manual trust " + trust + " for device key " + fingerprint + " of contact " + owner));
|
|
}
|
|
|
|
private Completable writeManualTrust(EntityBareJid owner, OpenPgpV4Fingerprint fingerprint, Trust trust) {
|
|
return openPgpTrustRepository.storeTrust(accountId, owner.asEntityBareJidIfPossible(), fingerprint, trust)
|
|
.doOnComplete(() -> LOGGER.log(Level.INFO,
|
|
"Successfully marked device key " + fingerprint + " of " + owner + " as " + trust));
|
|
}
|
|
|
|
@Override
|
|
protected void writeTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint, Trust trust) throws IOException {
|
|
EntityBareJid jid = owner.asEntityBareJidOrThrow();
|
|
disposable.add(
|
|
writeManualTrust(jid, fingerprint, trust)
|
|
.compose(schedulers.executeUiSafeCompletable())
|
|
.subscribe(() -> {},
|
|
e -> LOGGER.log(Level.SEVERE, "An error happened while marking device key " + fingerprint + " of " + jid + " as " + trust, e)));
|
|
}
|
|
}
|
|
}
|