204 lines
9.1 KiB
Java
204 lines
9.1 KiB
Java
package org.mercury_im.messenger.core.store.crypto;
|
|
|
|
import org.bouncycastle.openpgp.PGPException;
|
|
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
|
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
|
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.mercury_im.messenger.core.data.repository.OpenPgpTrustRepository;
|
|
import org.pgpainless.key.OpenPgpV4Fingerprint;
|
|
|
|
import java.io.IOException;
|
|
import java.util.Date;
|
|
import java.util.Map;
|
|
import java.util.NoSuchElementException;
|
|
import java.util.UUID;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
|
|
import io.reactivex.disposables.CompositeDisposable;
|
|
|
|
public class MercuryOpenPgpStore extends AbstractOpenPgpStore {
|
|
|
|
protected static final Logger LOGGER = Logger.getLogger(MercuryOpenPgpStore.class.getName());
|
|
|
|
public MercuryOpenPgpStore(UUID accountId, OpenPgpRepository repository, OpenPgpTrustRepository trustRepository, SchedulersFacade schedulers) {
|
|
this(
|
|
new KeyStore(accountId, repository, schedulers),
|
|
new MetadataStore(accountId, repository, schedulers),
|
|
new TrustStore(accountId, trustRepository, schedulers));
|
|
}
|
|
|
|
public MercuryOpenPgpStore(AbstractOpenPgpKeyStore keyStore,
|
|
AbstractOpenPgpMetadataStore metadataStore,
|
|
AbstractOpenPgpTrustStore trustStore) {
|
|
super(keyStore, metadataStore, trustStore);
|
|
}
|
|
|
|
public static class KeyStore extends AbstractOpenPgpKeyStore {
|
|
|
|
private final CompositeDisposable disposable = new CompositeDisposable();
|
|
private final OpenPgpRepository repository;
|
|
private final SchedulersFacade schedulers;
|
|
|
|
private final UUID accountId;
|
|
|
|
|
|
public KeyStore(UUID accountId, OpenPgpRepository repository, SchedulersFacade schedulers) {
|
|
this.accountId = accountId;
|
|
this.repository = repository;
|
|
this.schedulers = schedulers;
|
|
}
|
|
|
|
@Override
|
|
protected PGPPublicKeyRingCollection readPublicKeysOf(BareJid owner)
|
|
throws IOException, PGPException {
|
|
try {
|
|
return repository.loadPublicKeysOf(accountId, owner.asEntityBareJidIfPossible())
|
|
.blockingGet();
|
|
} catch (NoSuchElementException e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void writePublicKeysOf(BareJid owner, PGPPublicKeyRingCollection publicKeys)
|
|
throws IOException {
|
|
disposable.add(repository.storePublicKeysOf(accountId, owner.asEntityBareJidIfPossible(), publicKeys)
|
|
.subscribeOn(schedulers.getIoScheduler())
|
|
.subscribe(
|
|
() -> MercuryOpenPgpStore.LOGGER.log(Level.FINER, "Successfully wrote OX public keys for " + owner + " (accountId=" + accountId + ")"),
|
|
e -> MercuryOpenPgpStore.LOGGER.log(Level.SEVERE, "Error writing OX public keys for " + owner + " (accountId=" + accountId + ")")
|
|
));
|
|
}
|
|
|
|
@Override
|
|
protected PGPSecretKeyRingCollection readSecretKeysOf(BareJid owner)
|
|
throws IOException, PGPException {
|
|
try {
|
|
return repository.loadSecretKeysOf(accountId, owner.asEntityBareJidIfPossible())
|
|
.blockingGet();
|
|
} catch (NoSuchElementException e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void writeSecretKeysOf(BareJid owner, PGPSecretKeyRingCollection secretKeys)
|
|
throws IOException {
|
|
disposable.add(repository.storeSecretKeysOf(accountId, owner.asEntityBareJidIfPossible(), secretKeys)
|
|
.subscribeOn(schedulers.getIoScheduler())
|
|
.subscribe(
|
|
() -> MercuryOpenPgpStore.LOGGER.log(Level.FINER, "Successfully wrote OX secret keys for " + owner + " (accountId=" + accountId + ")"),
|
|
e -> MercuryOpenPgpStore.LOGGER.log(Level.SEVERE, "Error writing OX secret keys for " + owner + " (accountId=" + accountId + ")")
|
|
));
|
|
}
|
|
|
|
@Override
|
|
protected Map<OpenPgpV4Fingerprint, Date> readKeyFetchDates(BareJid owner)
|
|
throws IOException {
|
|
return repository.loadPublicKeyFetchDates(accountId, owner.asEntityBareJidIfPossible())
|
|
.blockingGet();
|
|
}
|
|
|
|
@Override
|
|
protected void writeKeyFetchDates(BareJid owner, Map<OpenPgpV4Fingerprint, Date> dates)
|
|
throws IOException {
|
|
disposable.add(repository.storePublicKeyFetchDates(accountId, owner.asEntityBareJidIfPossible(), dates)
|
|
.subscribeOn(schedulers.getIoScheduler())
|
|
.subscribe(
|
|
() -> MercuryOpenPgpStore.LOGGER.log(Level.FINER, "Successfully updated OX fetch dates for " + owner + " (accountId=" + accountId + ")"),
|
|
e -> MercuryOpenPgpStore.LOGGER.log(Level.SEVERE, "Error updating OX key fetch dates for " + owner + " (accountId=" + accountId + ")")
|
|
));
|
|
}
|
|
|
|
@Override
|
|
protected void finalize() throws Throwable {
|
|
disposable.dispose();
|
|
super.finalize();
|
|
}
|
|
}
|
|
|
|
public static class MetadataStore extends AbstractOpenPgpMetadataStore {
|
|
|
|
private final CompositeDisposable disposable = new CompositeDisposable();
|
|
private final OpenPgpRepository repository;
|
|
private final SchedulersFacade schedulers;
|
|
|
|
private final UUID accountId;
|
|
|
|
public MetadataStore(UUID accountId, OpenPgpRepository repository, SchedulersFacade schedulers) {
|
|
this.accountId = accountId;
|
|
this.repository = repository;
|
|
this.schedulers = schedulers;
|
|
}
|
|
|
|
@Override
|
|
protected Map<OpenPgpV4Fingerprint, Date> readAnnouncedFingerprintsOf(BareJid contact)
|
|
throws IOException {
|
|
return repository.loadAnnouncedFingerprints(accountId, contact.asEntityBareJidIfPossible())
|
|
.blockingGet();
|
|
}
|
|
|
|
@Override
|
|
protected void writeAnnouncedFingerprintsOf(BareJid contact, Map<OpenPgpV4Fingerprint, Date> metadata)
|
|
throws IOException {
|
|
disposable.add(
|
|
repository.storeAnnouncedFingerprints(accountId, contact.asEntityBareJidIfPossible(), metadata)
|
|
.subscribeOn(schedulers.getIoScheduler())
|
|
.subscribe(
|
|
() -> MercuryOpenPgpStore.LOGGER.log(Level.FINER, "Successfully updated announced OX fingerprints for " + contact + " (accountId=" + accountId + ")"),
|
|
e -> MercuryOpenPgpStore.LOGGER.log(Level.SEVERE, "Error updating announced OX fingerprints for " + contact + " (accountId=" + accountId + ")")
|
|
));
|
|
}
|
|
|
|
@Override
|
|
protected void finalize() throws Throwable {
|
|
disposable.dispose();
|
|
super.finalize();
|
|
}
|
|
}
|
|
|
|
public static class TrustStore extends AbstractOpenPgpTrustStore {
|
|
|
|
private final CompositeDisposable disposable = new CompositeDisposable();
|
|
private final OpenPgpTrustRepository repository;
|
|
private final SchedulersFacade schedulers;
|
|
|
|
private final UUID accountId;
|
|
|
|
public TrustStore(UUID accountId, OpenPgpTrustRepository repository, SchedulersFacade schedulers) {
|
|
this.accountId = accountId;
|
|
this.repository = repository;
|
|
this.schedulers = schedulers;
|
|
}
|
|
|
|
@Override
|
|
protected Trust readTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException {
|
|
return repository.loadTrust(accountId, owner.asEntityBareJidIfPossible(), fingerprint)
|
|
.blockingGet();
|
|
}
|
|
|
|
@Override
|
|
protected void writeTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint, Trust trust) throws IOException {
|
|
disposable.add(repository.storeTrust(accountId, owner.asEntityBareJidIfPossible(), fingerprint, trust)
|
|
.subscribeOn(schedulers.getIoScheduler())
|
|
.subscribe(
|
|
() -> MercuryOpenPgpStore.LOGGER.log(Level.FINER, "Successfully set trust in key " + fingerprint + " to " + trust + " for " + owner + " (accountId=" + accountId + ")"),
|
|
e -> MercuryOpenPgpStore.LOGGER.log(Level.SEVERE, "Error setting trust in key " + fingerprint + " to " + trust + " for " + owner + " (accountId=" + accountId + ")")
|
|
));
|
|
}
|
|
|
|
@Override
|
|
protected void finalize() throws Throwable {
|
|
disposable.dispose();
|
|
super.finalize();
|
|
}
|
|
}
|
|
}
|