From 15eee8e65ff3f5d62e3303caf7fb36a5184a4872 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Sun, 8 Jul 2018 18:23:08 +0200 Subject: [PATCH] Implement new OpenPgpProvider --- .../smackx/ox/OpenPgpV4Fingerprint.java | 129 ------------------ .../smackx/ox/element/OpenPgpElement.java | 8 ++ .../smackx/ox/v2/OpenPgpContact.java | 47 +++++++ .../smackx/ox/v2/OpenPgpProvider.java | 12 +- .../smackx/ox/v2/OpenPgpSelf.java | 52 +++++++ .../smackx/ox/v2/PainlessOpenPgpProvider.java | 127 +++++++++++++++++ .../{ => abstr}/AbstractOpenPgpKeyStore.java | 3 +- .../AbstractOpenPgpMetadataStore.java | 3 +- .../AbstractOpenPgpStore.java} | 70 ++++------ .../AbstractOpenPgpTrustStore.java | 3 +- .../{ => definition}/OpenPgpKeyStore.java | 2 +- .../OpenPgpMetadataStore.java | 2 +- .../ox/v2/store/definition/OpenPgpStore.java | 19 +++ .../{ => definition}/OpenPgpTrustStore.java | 2 +- .../filebased/FileBasedOpenPgpKeyStore.java | 2 +- .../FileBasedOpenPgpMetadataStore.java | 2 +- .../filebased/FileBasedOpenPgpStore.java | 4 +- .../filebased/FileBasedOpenPgpTrustStore.java | 2 +- 18 files changed, 301 insertions(+), 188 deletions(-) delete mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpV4Fingerprint.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/OpenPgpContact.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/OpenPgpSelf.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/PainlessOpenPgpProvider.java rename smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/{ => abstr}/AbstractOpenPgpKeyStore.java (96%) rename smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/{ => abstr}/AbstractOpenPgpMetadataStore.java (93%) rename smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/{OpenPgpStore.java => abstr/AbstractOpenPgpStore.java} (65%) rename smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/{ => abstr}/AbstractOpenPgpTrustStore.java (93%) rename smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/{ => definition}/OpenPgpKeyStore.java (96%) rename smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/{ => definition}/OpenPgpMetadataStore.java (94%) create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/definition/OpenPgpStore.java rename smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/{ => definition}/OpenPgpTrustStore.java (94%) diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpV4Fingerprint.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpV4Fingerprint.java deleted file mode 100644 index 20cb5a84a..000000000 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpV4Fingerprint.java +++ /dev/null @@ -1,129 +0,0 @@ -/** - * - * Copyright 2018 Paul Schaub. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.smackx.ox; - -import javax.xml.bind.DatatypeConverter; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.text.ParseException; -import java.util.Arrays; - -import org.jivesoftware.smack.util.Objects; - -import org.bouncycastle.openpgp.PGPPublicKey; -import org.bouncycastle.util.encoders.Hex; - -/** - * This class represents an hex encoded, uppercase OpenPGP v4 fingerprint. - */ -public class OpenPgpV4Fingerprint implements CharSequence, Comparable { - - private final String fingerprint; - - /** - * Create an {@link OpenPgpV4Fingerprint}. - * @see - * XEP-0373 §4.1: The OpenPGP Public-Key Data Node about how to obtain the fingerprint - * @param fingerprint hexadecimal representation of the fingerprint. - */ - public OpenPgpV4Fingerprint(String fingerprint) throws ParseException { - String fp = Objects.requireNonNull(fingerprint) - .trim() - .toUpperCase(); - if (!isValid(fp)) { - throw new ParseException("Fingerprint " + fingerprint + - " does not appear to be a valid OpenPGP v4 fingerprint.", 0); - } - this.fingerprint = fp; - } - - public OpenPgpV4Fingerprint(byte[] bytes) throws ParseException { - this(new String(bytes, Charset.forName("UTF-8"))); - } - - public OpenPgpV4Fingerprint(PGPPublicKey key) throws ParseException { - this(Hex.encode(key.getFingerprint())); - } - - /** - * Check, whether the fingerprint consists of 40 valid hexadecimal characters. - * @param fp fingerprint to check. - * @return true if fingerprint is valid. - */ - private boolean isValid(String fp) { - return fp.matches("[0-9A-F]{40}"); - } - - /** - * Return the key id of the OpenPGP public key this {@link OpenPgpV4Fingerprint} belongs to. - * - * @see - * RFC-4880 §12.2: Key IDs and Fingerprints - * @return key id - */ - public long getKeyId() { - byte[] bytes = DatatypeConverter.parseHexBinary(this.toString()); - byte[] lower8Bytes = Arrays.copyOfRange(bytes, 12, 20); - ByteBuffer byteBuffer = ByteBuffer.allocate(8); - byteBuffer.put(lower8Bytes); - byteBuffer.flip(); - return byteBuffer.getLong(); - } - - @Override - public boolean equals(Object other) { - if (other == null) { - return false; - } - - if (!(other instanceof CharSequence)) { - return false; - } - - return this.toString().equals(other.toString()); - } - - @Override - public int hashCode() { - return fingerprint.hashCode(); - } - - @Override - public int length() { - return fingerprint.length(); - } - - @Override - public char charAt(int i) { - return fingerprint.charAt(i); - } - - @Override - public CharSequence subSequence(int i, int i1) { - return fingerprint.subSequence(i, i1); - } - - @Override - public String toString() { - return fingerprint; - } - - @Override - public int compareTo(OpenPgpV4Fingerprint openPgpV4Fingerprint) { - return fingerprint.compareTo(openPgpV4Fingerprint.fingerprint); - } -} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpElement.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpElement.java index 72a21c875..4bef2cdff 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpElement.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpElement.java @@ -16,8 +16,12 @@ */ package org.jivesoftware.smackx.ox.element; +import java.io.ByteArrayInputStream; +import java.io.InputStream; + import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.util.XmlStringBuilder; +import org.jivesoftware.smackx.ox.util.Util; public class OpenPgpElement implements ExtensionElement { @@ -31,6 +35,10 @@ public class OpenPgpElement implements ExtensionElement { this.base64EncodedOpenPgpMessage = base64EncodedOpenPgpMessage; } + public InputStream toInputStream() { + return new ByteArrayInputStream(base64EncodedOpenPgpMessage.getBytes(Util.UTF8)); + } + public String getEncryptedBase64MessageContent() { return base64EncodedOpenPgpMessage; } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/OpenPgpContact.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/OpenPgpContact.java new file mode 100644 index 000000000..a2ca7d250 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/OpenPgpContact.java @@ -0,0 +1,47 @@ +package org.jivesoftware.smackx.ox.v2; + +import java.io.IOException; +import java.util.Set; +import java.util.logging.Logger; + +import org.jivesoftware.smackx.ox.v2.store.definition.OpenPgpStore; +import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPublicKeyRing; +import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; +import org.jxmpp.jid.BareJid; + +public class OpenPgpContact { + + private final Logger LOGGER; + + protected final BareJid jid; + protected final OpenPgpStore store; + + public OpenPgpContact(BareJid jid, OpenPgpStore store) { + this.jid = jid; + this.store = store; + LOGGER = Logger.getLogger(OpenPgpContact.class.getName() + ":" + jid.toString()); + } + + public PGPPublicKeyRingCollection getAnyPublicKeys() throws IOException, PGPException { + return store.getPublicKeysOf(jid); + } + + public PGPPublicKeyRingCollection getAnnouncedPublicKeys() throws IOException, PGPException { + PGPPublicKeyRingCollection anyKeys = getAnyPublicKeys(); + Set announced = store.getAnnouncedFingerprintsOf(jid).keySet(); + + PGPPublicKeyRingCollection announcedKeysCollection = anyKeys; + for (PGPPublicKeyRing ring : anyKeys) { + + OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(ring.getPublicKey()); + + if (!announced.contains(fingerprint)) { + announcedKeysCollection = PGPPublicKeyRingCollection.removePublicKeyRing(announcedKeysCollection, ring); + } + } + return announcedKeysCollection; + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/OpenPgpProvider.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/OpenPgpProvider.java index cd4c4407f..3bd6a1188 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/OpenPgpProvider.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/OpenPgpProvider.java @@ -16,22 +16,24 @@ */ package org.jivesoftware.smackx.ox.v2; +import java.io.IOException; import java.util.Collection; -import org.jivesoftware.smackx.ox.OpenPgpContact; import org.jivesoftware.smackx.ox.OpenPgpMessage; import org.jivesoftware.smackx.ox.element.CryptElement; import org.jivesoftware.smackx.ox.element.OpenPgpElement; import org.jivesoftware.smackx.ox.element.SignElement; import org.jivesoftware.smackx.ox.element.SigncryptElement; +import org.bouncycastle.openpgp.PGPException; + public interface OpenPgpProvider { - OpenPgpElement signAndEncrypt(SigncryptElement element, Collection recipients); + OpenPgpElement signAndEncrypt(SigncryptElement element, OpenPgpSelf self, Collection recipients) throws IOException, PGPException; - OpenPgpElement sign(SignElement element); + OpenPgpElement sign(SignElement element, OpenPgpSelf self) throws IOException, PGPException; - OpenPgpElement encrypt(CryptElement element, Collection recipients); + OpenPgpElement encrypt(CryptElement element, OpenPgpSelf self, Collection recipients) throws IOException, PGPException; - OpenPgpMessage decryptAndOrVerify(OpenPgpElement element); + OpenPgpMessage decryptAndOrVerify(OpenPgpElement element, OpenPgpSelf self, OpenPgpContact sender) throws IOException, PGPException; } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/OpenPgpSelf.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/OpenPgpSelf.java new file mode 100644 index 000000000..ff638becd --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/OpenPgpSelf.java @@ -0,0 +1,52 @@ +package org.jivesoftware.smackx.ox.v2; + +import java.io.IOException; + +import org.jivesoftware.smackx.ox.v2.store.definition.OpenPgpStore; +import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; +import org.jxmpp.jid.BareJid; + +public class OpenPgpSelf extends OpenPgpContact { + + public OpenPgpSelf(BareJid jid, OpenPgpStore store) { + super(jid, store); + } + + public boolean hasSecretKeyAvailable() throws IOException, PGPException { + return getSecretKeys() != null; + } + + public PGPSecretKeyRingCollection getSecretKeys() throws IOException, PGPException { + return store.getSecretKeysOf(jid); + } + + public PGPSecretKeyRing getSigningKeyRing() throws IOException, PGPException { + PGPSecretKeyRingCollection secretKeyRings = getSecretKeys(); + if (secretKeyRings == null) { + return null; + } + + PGPSecretKeyRing signingKeyRing = null; + for (PGPSecretKeyRing ring : secretKeyRings) { + if (signingKeyRing == null) { + signingKeyRing = ring; + continue; + } + + if (ring.getPublicKey().getCreationTime().after(signingKeyRing.getPublicKey().getCreationTime())) { + signingKeyRing = ring; + } + } + + return signingKeyRing; + } + + public OpenPgpV4Fingerprint getSigningKeyFingerprint() throws IOException, PGPException { + PGPSecretKeyRing signingKeyRing = getSigningKeyRing(); + return signingKeyRing != null ? new OpenPgpV4Fingerprint(signingKeyRing.getPublicKey()) : null; + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/PainlessOpenPgpProvider.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/PainlessOpenPgpProvider.java new file mode 100644 index 000000000..467ed70c4 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/PainlessOpenPgpProvider.java @@ -0,0 +1,127 @@ +package org.jivesoftware.smackx.ox.v2; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; + +import org.jivesoftware.smack.util.stringencoder.Base64; +import org.jivesoftware.smackx.ox.OpenPgpMessage; +import org.jivesoftware.smackx.ox.element.CryptElement; +import org.jivesoftware.smackx.ox.element.OpenPgpElement; +import org.jivesoftware.smackx.ox.element.SignElement; +import org.jivesoftware.smackx.ox.element.SigncryptElement; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; +import org.bouncycastle.util.io.Streams; +import org.pgpainless.pgpainless.PGPainless; +import org.pgpainless.pgpainless.decryption_verification.DecryptionStream; +import org.pgpainless.pgpainless.decryption_verification.PainlessResult; +import org.pgpainless.pgpainless.encryption_signing.EncryptionStream; + +public class PainlessOpenPgpProvider implements OpenPgpProvider { + + @Override + public OpenPgpElement signAndEncrypt(SigncryptElement element, OpenPgpSelf self, Collection recipients) + throws IOException, PGPException { + InputStream plainText = element.toInputStream(); + ByteArrayOutputStream cipherText = new ByteArrayOutputStream(); + + ArrayList recipientKeys = new ArrayList<>(); + for (OpenPgpContact contact : recipients) { + recipientKeys.add(contact.getAnnouncedPublicKeys()); + } + + EncryptionStream cipherStream = PGPainless.createEncryptor().onOutputStream(cipherText) + .toRecipients(recipientKeys.toArray(new PGPPublicKeyRingCollection[]{})) + .andToSelf(self.getAnnouncedPublicKeys()) + .usingSecureAlgorithms() + .signWith(null, self.getSigningKeyRing()) + .noArmor(); + + Streams.pipeAll(plainText, cipherStream); + plainText.close(); + cipherStream.flush(); + cipherStream.close(); + cipherText.close(); + + String base64 = Base64.encodeToString(cipherText.toByteArray()); + // TODO: Return feedback about encryption? + return new OpenPgpElement(base64); + } + + @Override + public OpenPgpElement sign(SignElement element, OpenPgpSelf self) + throws IOException, PGPException { + InputStream plainText = element.toInputStream(); + ByteArrayOutputStream cipherText = new ByteArrayOutputStream(); + + EncryptionStream cipherStream = PGPainless.createEncryptor().onOutputStream(cipherText) + .doNotEncrypt() + .signWith(null, self.getSigningKeyRing()) + .noArmor(); + + Streams.pipeAll(plainText, cipherStream); + plainText.close(); + cipherStream.flush(); + cipherStream.close(); + cipherText.close(); + + String base64 = Base64.encodeToString(cipherText.toByteArray()); + return new OpenPgpElement(base64); + } + + @Override + public OpenPgpElement encrypt(CryptElement element, OpenPgpSelf self, Collection recipients) + throws IOException, PGPException { + InputStream plainText = element.toInputStream(); + ByteArrayOutputStream cipherText = new ByteArrayOutputStream(); + + ArrayList recipientKeys = new ArrayList<>(); + for (OpenPgpContact contact : recipients) { + recipientKeys.add(contact.getAnnouncedPublicKeys()); + } + + EncryptionStream cipherStream = PGPainless.createEncryptor().onOutputStream(cipherText) + .toRecipients(recipientKeys.toArray(new PGPPublicKeyRingCollection[]{})) + .andToSelf(self.getAnnouncedPublicKeys()) + .usingSecureAlgorithms() + .doNotSign() + .noArmor(); + + Streams.pipeAll(plainText, cipherStream); + plainText.close(); + cipherStream.flush(); + cipherStream.close(); + cipherText.close(); + + String base64 = Base64.encodeToString(cipherText.toByteArray()); + // TODO: Return feedback about encryption? + return new OpenPgpElement(base64); + } + + @Override + public OpenPgpMessage decryptAndOrVerify(OpenPgpElement element, OpenPgpSelf self, OpenPgpContact sender) throws IOException, PGPException { + ByteArrayOutputStream plainText = new ByteArrayOutputStream(); + InputStream cipherText = element.toInputStream(); + + DecryptionStream cipherStream = PGPainless.createDecryptor().onInputStream(cipherText) + .decryptWith(null, self.getSecretKeys()) + .verifyWith(sender.getAnnouncedPublicKeys()) + .ignoreMissingPublicKeys() + .build(); + + Streams.pipeAll(cipherStream, plainText); + + cipherText.close(); + cipherStream.close(); + plainText.close(); + + PainlessResult info = cipherStream.getResult(); + + return new OpenPgpMessage(plainText.toByteArray(), new OpenPgpMessage.Metadata( + info.getDecryptionKeyId(), info.getVerifiedSignatureKeyIds())); + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpKeyStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/abstr/AbstractOpenPgpKeyStore.java similarity index 96% rename from smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpKeyStore.java rename to smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/abstr/AbstractOpenPgpKeyStore.java index 24367c884..2a2018dc4 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpKeyStore.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/abstr/AbstractOpenPgpKeyStore.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jivesoftware.smackx.ox.v2.store; +package org.jivesoftware.smackx.ox.v2.store.abstr; import java.io.IOException; import java.security.InvalidAlgorithmParameterException; @@ -24,6 +24,7 @@ import java.util.HashMap; import java.util.Map; import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; +import org.jivesoftware.smackx.ox.v2.store.definition.OpenPgpKeyStore; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPublicKeyRing; diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpMetadataStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/abstr/AbstractOpenPgpMetadataStore.java similarity index 93% rename from smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpMetadataStore.java rename to smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/abstr/AbstractOpenPgpMetadataStore.java index 03158dbf1..396f702e3 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpMetadataStore.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/abstr/AbstractOpenPgpMetadataStore.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jivesoftware.smackx.ox.v2.store; +package org.jivesoftware.smackx.ox.v2.store.abstr; import java.io.IOException; import java.util.Date; @@ -22,6 +22,7 @@ import java.util.HashMap; import java.util.Map; import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; +import org.jivesoftware.smackx.ox.v2.store.definition.OpenPgpMetadataStore; import org.jxmpp.jid.BareJid; diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/abstr/AbstractOpenPgpStore.java similarity index 65% rename from smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpStore.java rename to smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/abstr/AbstractOpenPgpStore.java index abbc1236a..3c8a23320 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpStore.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/abstr/AbstractOpenPgpStore.java @@ -14,20 +14,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jivesoftware.smackx.ox.v2.store; +package org.jivesoftware.smackx.ox.v2.store.abstr; 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.Set; +import java.util.Observable; +import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smackx.ox.OpenPgpContact; import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; import org.jivesoftware.smackx.ox.callback.SecretKeyPassphraseCallback; -import org.jivesoftware.smackx.ox.element.PublicKeysListElement; +import org.jivesoftware.smackx.ox.v2.store.definition.OpenPgpKeyStore; +import org.jivesoftware.smackx.ox.v2.store.definition.OpenPgpMetadataStore; +import org.jivesoftware.smackx.ox.v2.store.definition.OpenPgpStore; +import org.jivesoftware.smackx.ox.v2.store.definition.OpenPgpTrustStore; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPublicKeyRing; @@ -37,24 +42,26 @@ import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.jxmpp.jid.BareJid; import org.pgpainless.pgpainless.key.protection.SecretKeyRingProtector; -public abstract class OpenPgpStore implements OpenPgpKeyStore, OpenPgpMetadataStore, OpenPgpTrustStore { +public abstract class AbstractOpenPgpStore extends Observable implements OpenPgpStore { protected final OpenPgpKeyStore keyStore; protected final OpenPgpMetadataStore metadataStore; protected final OpenPgpTrustStore trustStore; protected SecretKeyPassphraseCallback secretKeyPassphraseCallback; + protected SecretKeyRingProtector unlocker; protected final Map contacts = new HashMap<>(); - public OpenPgpStore(OpenPgpKeyStore keyStore, - OpenPgpMetadataStore metadataStore, - OpenPgpTrustStore trustStore) { - this.keyStore = keyStore; - this.metadataStore = metadataStore; - this.trustStore = trustStore; + protected AbstractOpenPgpStore(OpenPgpKeyStore keyStore, + OpenPgpMetadataStore metadataStore, + OpenPgpTrustStore trustStore) { + this.keyStore = Objects.requireNonNull(keyStore); + this.metadataStore = Objects.requireNonNull(metadataStore); + this.trustStore = Objects.requireNonNull(trustStore); } - public OpenPgpContact getContact(BareJid jid) { + @Override + public OpenPgpContact getOpenPgpContact(BareJid jid) { OpenPgpContact contact = contacts.get(jid); if (contact != null) { return contact; @@ -64,11 +71,13 @@ public abstract class OpenPgpStore implements OpenPgpKeyStore, OpenPgpMetadataSt return null; } + @Override public void setKeyRingProtector(SecretKeyRingProtector protector) { - + this.unlocker = protector; } - public void setUnknownSecretKeyPassphraseCallback(SecretKeyPassphraseCallback callback) { + @Override + public void setSecretKeyPassphraseCallback(SecretKeyPassphraseCallback callback) { this.secretKeyPassphraseCallback = callback; } @@ -76,31 +85,11 @@ public abstract class OpenPgpStore implements OpenPgpKeyStore, OpenPgpMetadataSt OpenPgpKeyStore */ - @Override - public PGPPublicKeyRingCollection readPublicKeysOf(BareJid owner) throws IOException, PGPException { - return keyStore.readPublicKeysOf(owner); - } - - @Override - public void writePublicKeysOf(BareJid owner, PGPPublicKeyRingCollection publicKeys) throws IOException { - keyStore.writePublicKeysOf(owner, publicKeys); - } - @Override public PGPPublicKeyRingCollection getPublicKeysOf(BareJid owner) throws IOException, PGPException { return keyStore.getPublicKeysOf(owner); } - @Override - public PGPSecretKeyRingCollection readSecretKeysOf(BareJid owner) throws IOException, PGPException { - return keyStore.readSecretKeysOf(owner); - } - - @Override - public void writeSecretKeysOf(BareJid owner, PGPSecretKeyRingCollection secretKeys) throws IOException { - keyStore.writeSecretKeysOf(owner, secretKeys); - } - @Override public PGPSecretKeyRingCollection getSecretKeysOf(BareJid owner) throws IOException, PGPException { return keyStore.getSecretKeysOf(owner); @@ -126,18 +115,13 @@ public abstract class OpenPgpStore implements OpenPgpKeyStore, OpenPgpMetadataSt */ @Override - public Set getAnnouncedFingerprintsOf(BareJid contact) throws IOException { + public Map getAnnouncedFingerprintsOf(BareJid contact) throws IOException { return metadataStore.getAnnouncedFingerprintsOf(contact); } @Override - public Set readAnnouncedFingerprintsOf(BareJid contact) throws IOException { - return metadataStore.readAnnouncedFingerprintsOf(contact); - } - - @Override - public void writeAnnouncedFingerprintsOf(BareJid contact, PublicKeysListElement metadata) throws IOException { - metadataStore.writeAnnouncedFingerprintsOf(contact, metadata); + public void setAnnouncedFingerprintsOf(BareJid contact, Map data) throws IOException { + metadataStore.setAnnouncedFingerprintsOf(contact, data); } /* @@ -145,12 +129,12 @@ public abstract class OpenPgpStore implements OpenPgpKeyStore, OpenPgpMetadataSt */ @Override - public Trust getTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint) { + public Trust getTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException { return trustStore.getTrust(owner, fingerprint); } @Override - public void setTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint, Trust trust) { + public void setTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint, Trust trust) throws IOException { trustStore.setTrust(owner, fingerprint, trust); } } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpTrustStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/abstr/AbstractOpenPgpTrustStore.java similarity index 93% rename from smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpTrustStore.java rename to smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/abstr/AbstractOpenPgpTrustStore.java index b290b4bdd..32e5e5c59 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpTrustStore.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/abstr/AbstractOpenPgpTrustStore.java @@ -1,10 +1,11 @@ -package org.jivesoftware.smackx.ox.v2.store; +package org.jivesoftware.smackx.ox.v2.store.abstr; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; +import org.jivesoftware.smackx.ox.v2.store.definition.OpenPgpTrustStore; import org.jxmpp.jid.BareJid; diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpKeyStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/definition/OpenPgpKeyStore.java similarity index 96% rename from smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpKeyStore.java rename to smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/definition/OpenPgpKeyStore.java index 57d1fce1d..592a928e5 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpKeyStore.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/definition/OpenPgpKeyStore.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jivesoftware.smackx.ox.v2.store; +package org.jivesoftware.smackx.ox.v2.store.definition; import java.io.IOException; import java.security.InvalidAlgorithmParameterException; diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpMetadataStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/definition/OpenPgpMetadataStore.java similarity index 94% rename from smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpMetadataStore.java rename to smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/definition/OpenPgpMetadataStore.java index a02b49697..8ef8e66c4 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpMetadataStore.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/definition/OpenPgpMetadataStore.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jivesoftware.smackx.ox.v2.store; +package org.jivesoftware.smackx.ox.v2.store.definition; import java.io.IOException; import java.util.Date; diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/definition/OpenPgpStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/definition/OpenPgpStore.java new file mode 100644 index 000000000..25a751bdf --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/definition/OpenPgpStore.java @@ -0,0 +1,19 @@ +package org.jivesoftware.smackx.ox.v2.store.definition; + +import org.jivesoftware.smackx.ox.OpenPgpContact; +import org.jivesoftware.smackx.ox.callback.SecretKeyPassphraseCallback; + +import org.jxmpp.jid.BareJid; +import org.pgpainless.pgpainless.key.protection.SecretKeyRingProtector; + +public interface OpenPgpStore extends OpenPgpKeyStore, OpenPgpMetadataStore, OpenPgpTrustStore { + + OpenPgpContact getOpenPgpContact(BareJid contactsJid); + + void setKeyRingProtector(SecretKeyRingProtector unlocker); + + SecretKeyRingProtector getKeyRingProtector(); + + void setSecretKeyPassphraseCallback(SecretKeyPassphraseCallback callback); + +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpTrustStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/definition/OpenPgpTrustStore.java similarity index 94% rename from smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpTrustStore.java rename to smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/definition/OpenPgpTrustStore.java index 8edf18aa6..a7da9cad4 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpTrustStore.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/definition/OpenPgpTrustStore.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jivesoftware.smackx.ox.v2.store; +package org.jivesoftware.smackx.ox.v2.store.definition; import java.io.IOException; diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpKeyStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpKeyStore.java index ca5488d91..4337ccd2a 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpKeyStore.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpKeyStore.java @@ -26,7 +26,7 @@ import java.io.IOException; import java.io.OutputStream; import org.jivesoftware.smack.util.Objects; -import org.jivesoftware.smackx.ox.v2.store.AbstractOpenPgpKeyStore; +import org.jivesoftware.smackx.ox.v2.store.abstr.AbstractOpenPgpKeyStore; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpMetadataStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpMetadataStore.java index 5305bad4c..f636f3c77 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpMetadataStore.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpMetadataStore.java @@ -30,7 +30,7 @@ import java.util.logging.Logger; import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; import org.jivesoftware.smackx.ox.util.Util; -import org.jivesoftware.smackx.ox.v2.store.AbstractOpenPgpMetadataStore; +import org.jivesoftware.smackx.ox.v2.store.abstr.AbstractOpenPgpMetadataStore; import org.jxmpp.jid.BareJid; import org.jxmpp.util.XmppDateTime; diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpStore.java index 5dcd3aad0..b77d25623 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpStore.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpStore.java @@ -19,11 +19,11 @@ package org.jivesoftware.smackx.ox.v2.store.filebased; import java.io.File; import org.jivesoftware.smack.util.Objects; -import org.jivesoftware.smackx.ox.v2.store.OpenPgpStore; +import org.jivesoftware.smackx.ox.v2.store.abstr.AbstractOpenPgpStore; import org.jxmpp.jid.BareJid; -public class FileBasedOpenPgpStore extends OpenPgpStore { +public class FileBasedOpenPgpStore extends AbstractOpenPgpStore { public FileBasedOpenPgpStore(File basePath) { super(new FileBasedOpenPgpKeyStore(basePath), diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpTrustStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpTrustStore.java index 300eb44a2..3b6ca328c 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpTrustStore.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpTrustStore.java @@ -27,7 +27,7 @@ import java.util.logging.Logger; import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; import org.jivesoftware.smackx.ox.util.Util; -import org.jivesoftware.smackx.ox.v2.store.AbstractOpenPgpTrustStore; +import org.jivesoftware.smackx.ox.v2.store.abstr.AbstractOpenPgpTrustStore; import org.jxmpp.jid.BareJid;