Start OX implementation

This commit is contained in:
Paul Schaub 2020-06-13 19:14:38 +02:00
parent 9e646c1d41
commit 61de3cb22c
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
9 changed files with 372 additions and 1 deletions

View File

@ -27,6 +27,8 @@ dependencies {
api "io.requery:requery:$requeryVersion"
annotationProcessor "io.requery:requery-processor:$requeryVersion"
implementation 'com.google.code.findbugs:jsr305:3.0.2'
// JUnit for testing
testImplementation "junit:junit:$junitVersion"

View File

@ -0,0 +1,37 @@
package org.mercury_im.messenger.data.converter;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import javax.annotation.Nullable;
import io.requery.Converter;
public class EntityBareJidConverter implements Converter<EntityBareJid, String> {
@Override
public Class<EntityBareJid> getMappedType() {
return EntityBareJid.class;
}
@Override
public Class<String> getPersistedType() {
return String.class;
}
@Nullable
@Override
public Integer getPersistedSize() {
return null;
}
@Override
public String convertToPersisted(EntityBareJid value) {
return value == null ? null : value.asEntityBareJidString();
}
@Override
public EntityBareJid convertToMapped(Class<? extends EntityBareJid> type, @Nullable String value) {
return value == null ? null : JidCreate.entityBareFromOrThrowUnchecked(value);
}
}

View File

@ -0,0 +1,33 @@
package org.mercury_im.messenger.data.converter;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import io.requery.Converter;
public class OpenPgpV4FingerprintConverter implements Converter<OpenPgpV4Fingerprint, String> {
@Override
public Class<OpenPgpV4Fingerprint> getMappedType() {
return OpenPgpV4Fingerprint.class;
}
@Override
public Class<String> getPersistedType() {
return String.class;
}
@javax.annotation.Nullable
@Override
public Integer getPersistedSize() {
return null;
}
@Override
public String convertToPersisted(OpenPgpV4Fingerprint value) {
return value == null ? null : value.toString();
}
@Override
public OpenPgpV4Fingerprint convertToMapped(Class<? extends OpenPgpV4Fingerprint> type, @javax.annotation.Nullable String value) {
return value == null ? null : new OpenPgpV4Fingerprint(value);
}
}

View File

@ -22,7 +22,7 @@ import io.requery.converter.UUIDConverter;
public abstract class AbstractMessageModel implements Persistable {
@Key
@Convert(UUIDConverter.class)
@Convert(UUIDConverter.class)
UUID id;
@Column(nullable = false)

View File

@ -0,0 +1,46 @@
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;
@Column(name = "data", nullable = false)
byte[] bytes;
}

View File

@ -0,0 +1,46 @@
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;
@Column(name = "data", nullable = false)
byte[] bytes;
}

View File

@ -0,0 +1,53 @@
package org.mercury_im.messenger.data.repository;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
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 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;
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()).)
}
@Override
public Single<Integer> deletePublicKeyRing(UUID accountId, EntityBareJid jid, OpenPgpV4Fingerprint fingerprint) {
return data.delete(OpenPgpPublicKeyRing.class)
.where(OpenPgpPublicKeyRing.ACCOUNT_ID.eq(accountId))
.and(OpenPgpPublicKeyRing.OWNER.eq(jid))
.and(OpenPgpPublicKeyRing.FINGERPRINT.eq(fingerprint))
.get().single();
}
@Override
public Single<Integer> deleteSecretKeyRing(UUID accountId, EntityBareJid jid, OpenPgpV4Fingerprint fingerprint) {
return data.delete(OpenPgpSecretKeyRing.class)
.where(OpenPgpSecretKeyRing.ACCOUNT_ID.eq(accountId))
.and(OpenPgpPublicKeyRing.OWNER.eq(jid))
.and(OpenPgpSecretKeyRing.FINGERPRINT.eq(fingerprint))
.get().single();
}
}

View File

@ -0,0 +1,18 @@
package org.mercury_im.messenger.core.data.repository;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.jxmpp.jid.EntityBareJid;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import java.util.UUID;
import io.reactivex.Single;
public interface OpenPgpRepository {
Single<PGPPublicKeyRingCollection> loadPublicKeysOfContact(UUID accountId, EntityBareJid jid);
Single<Integer> deletePublicKeyRing(UUID accountId, EntityBareJid jid, OpenPgpV4Fingerprint fingerprint);
Single<Integer> deleteSecretKeyRing(UUID accountId, EntityBareJid jid, OpenPgpV4Fingerprint fingerprint);
}

View File

@ -0,0 +1,136 @@
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.jxmpp.jid.BareJid;
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.Map;
import java.util.UUID;
import javax.inject.Inject;
public class MercuryOpenPgpStore implements OpenPgpStore {
private final UUID accountId;
private SecretKeyRingProtector keyRingProtector;
private SecretKeyPassphraseCallback passphraseCallback;
@Inject
OpenPgpRepository repository;
public MercuryOpenPgpStore(UUID accountId) {
this.accountId = accountId;
}
@Override
public OpenPgpContact getOpenPgpContact(BareJid contactsJid) {
return null;
}
@Override
public void setKeyRingProtector(SecretKeyRingProtector unlocker) {
this.keyRingProtector = unlocker;
}
@Override
public SecretKeyRingProtector getKeyRingProtector() {
return keyRingProtector;
}
@Override
public void setSecretKeyPassphraseCallback(SecretKeyPassphraseCallback callback) {
passphraseCallback = callback;
}
@Override
public PGPPublicKeyRingCollection getPublicKeysOf(BareJid owner) throws IOException, PGPException {
return null;
}
@Override
public PGPSecretKeyRingCollection getSecretKeysOf(BareJid owner) throws IOException, PGPException {
return null;
}
@Override
public PGPPublicKeyRing getPublicKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException {
return null;
}
@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 {
}
}