mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-24 04:52:05 +01:00
Introduce exception, add documentation
This commit is contained in:
parent
a234760233
commit
c1603139be
5 changed files with 214 additions and 36 deletions
|
@ -34,6 +34,7 @@ import org.jivesoftware.smackx.ox.OpenPgpProvider;
|
||||||
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
||||||
|
import org.jivesoftware.smackx.ox.exception.CorruptedOpenPgpKeyException;
|
||||||
|
|
||||||
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.BouncyGPG;
|
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.BouncyGPG;
|
||||||
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.algorithms.PublicKeySize;
|
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.algorithms.PublicKeySize;
|
||||||
|
@ -68,24 +69,32 @@ public class BouncyCastleOpenPgpProvider implements OpenPgpProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PubkeyElement createPubkeyElement() throws IOException, PGPException {
|
public PubkeyElement createPubkeyElement() throws CorruptedOpenPgpKeyException {
|
||||||
PGPPublicKey pubKey = ourKeys.getPublicKeyRings().getPublicKey(ourKeyId);
|
try {
|
||||||
PubkeyElement.PubkeyDataElement dataElement = new PubkeyElement.PubkeyDataElement(
|
PGPPublicKey pubKey = ourKeys.getPublicKeyRings().getPublicKey(ourKeyId);
|
||||||
Base64.encode(pubKey.getEncoded()));
|
PubkeyElement.PubkeyDataElement dataElement = new PubkeyElement.PubkeyDataElement(
|
||||||
return new PubkeyElement(dataElement, new Date());
|
Base64.encode(pubKey.getEncoded()));
|
||||||
|
return new PubkeyElement(dataElement, new Date());
|
||||||
|
} catch (PGPException | IOException e) {
|
||||||
|
throw new CorruptedOpenPgpKeyException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPubkeyElement(PubkeyElement element, BareJid jid) throws IOException, PGPException {
|
public void processPubkeyElement(PubkeyElement element, BareJid jid) throws CorruptedOpenPgpKeyException {
|
||||||
byte[] decoded = Base64.decode(element.getDataElement().getB64Data());
|
byte[] decoded = Base64.decode(element.getDataElement().getB64Data());
|
||||||
|
|
||||||
InMemoryKeyring contactsKeyring = theirKeys.get(jid);
|
try {
|
||||||
if (contactsKeyring == null) {
|
InMemoryKeyring contactsKeyring = theirKeys.get(jid);
|
||||||
contactsKeyring = KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys());
|
if (contactsKeyring == null) {
|
||||||
theirKeys.put(jid, contactsKeyring);
|
contactsKeyring = KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys());
|
||||||
}
|
theirKeys.put(jid, contactsKeyring);
|
||||||
|
}
|
||||||
|
|
||||||
contactsKeyring.addPublicKey(decoded);
|
contactsKeyring.addPublicKey(decoded);
|
||||||
|
} catch (IOException | PGPException e) {
|
||||||
|
throw new CorruptedOpenPgpKeyException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -188,10 +197,14 @@ public class BouncyCastleOpenPgpProvider implements OpenPgpProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFingerprint() throws IOException, PGPException {
|
public String getFingerprint() throws CorruptedOpenPgpKeyException {
|
||||||
return new String(Hex.encode(ourKeys.getKeyFingerPrintCalculator()
|
try {
|
||||||
.calculateFingerprint(ourKeys.getPublicKeyRings().getPublicKey(ourKeyId)
|
return new String(Hex.encode(ourKeys.getKeyFingerPrintCalculator()
|
||||||
.getPublicKeyPacket())), Charset.forName("UTF-8")).toUpperCase();
|
.calculateFingerprint(ourKeys.getPublicKeyRings().getPublicKey(ourKeyId)
|
||||||
|
.getPublicKeyPacket())), Charset.forName("UTF-8")).toUpperCase();
|
||||||
|
} catch (IOException | PGPException e) {
|
||||||
|
throw new CorruptedOpenPgpKeyException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PGPKeyRingGenerator generateKey(BareJid owner) throws NoSuchAlgorithmException, PGPException {
|
public static PGPKeyRingGenerator generateKey(BareJid owner) throws NoSuchAlgorithmException, PGPException {
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.jivesoftware.smack.util.Async;
|
||||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||||
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
||||||
|
import org.jivesoftware.smackx.ox.exception.CorruptedOpenPgpKeyException;
|
||||||
import org.jivesoftware.smackx.pep.PEPListener;
|
import org.jivesoftware.smackx.pep.PEPListener;
|
||||||
import org.jivesoftware.smackx.pep.PEPManager;
|
import org.jivesoftware.smackx.pep.PEPManager;
|
||||||
import org.jivesoftware.smackx.pubsub.EventElement;
|
import org.jivesoftware.smackx.pubsub.EventElement;
|
||||||
|
@ -49,16 +50,45 @@ public final class OpenPgpManager extends Manager {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(OpenPgpManager.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(OpenPgpManager.class.getName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the OX metadata node.
|
||||||
|
*
|
||||||
|
* @see <a href="https://xmpp.org/extensions/xep-0373.html#announcing-pubkey-list">XEP-0373 §4.2</a>.
|
||||||
|
*/
|
||||||
public static final String PEP_NODE_PUBLIC_KEYS = "urn:xmpp:openpgp:0:public-keys";
|
public static final String PEP_NODE_PUBLIC_KEYS = "urn:xmpp:openpgp:0:public-keys";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feature to be announced using the {@link ServiceDiscoveryManager} to subscribe to the OX metadata node.
|
||||||
|
*
|
||||||
|
* @see <a href="https://xmpp.org/extensions/xep-0373.html#pubsub-notifications">XEP-0373 §4.4</a>.
|
||||||
|
*/
|
||||||
public static final String PEP_NODE_PUBLIC_KEYS_NOTIFY = PEP_NODE_PUBLIC_KEYS + "+notify";
|
public static final String PEP_NODE_PUBLIC_KEYS_NOTIFY = PEP_NODE_PUBLIC_KEYS + "+notify";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the OX public key node, which contains the key with id {@code id}.
|
||||||
|
*
|
||||||
|
* @param id upper case hex encoded OpenPGP v4 fingerprint of the key.
|
||||||
|
* @return PEP node name.
|
||||||
|
*/
|
||||||
public static String PEP_NODE_PUBLIC_KEY(String id) {
|
public static String PEP_NODE_PUBLIC_KEY(String id) {
|
||||||
return PEP_NODE_PUBLIC_KEYS + ":" + id;
|
return PEP_NODE_PUBLIC_KEYS + ":" + id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of instances.
|
||||||
|
*/
|
||||||
private static final Map<XMPPConnection, OpenPgpManager> INSTANCES = new WeakHashMap<>();
|
private static final Map<XMPPConnection, OpenPgpManager> INSTANCES = new WeakHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link OpenPgpProvider} responsible for processing keys, encrypting and decrypting messages and so on.
|
||||||
|
*/
|
||||||
private OpenPgpProvider provider;
|
private OpenPgpProvider provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor to avoid instantiation without putting the object into {@code INSTANCES}.
|
||||||
|
*
|
||||||
|
* @param connection xmpp connection.
|
||||||
|
*/
|
||||||
private OpenPgpManager(XMPPConnection connection) {
|
private OpenPgpManager(XMPPConnection connection) {
|
||||||
super(connection);
|
super(connection);
|
||||||
|
|
||||||
|
@ -68,6 +98,12 @@ public final class OpenPgpManager extends Manager {
|
||||||
.addFeature(PEP_NODE_PUBLIC_KEYS_NOTIFY);
|
.addFeature(PEP_NODE_PUBLIC_KEYS_NOTIFY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the instance of the {@link OpenPgpManager} which belongs to the {@code connection}.
|
||||||
|
*
|
||||||
|
* @param connection xmpp connection.
|
||||||
|
* @return instance of the manager.
|
||||||
|
*/
|
||||||
public static OpenPgpManager getInstanceFor(XMPPConnection connection) {
|
public static OpenPgpManager getInstanceFor(XMPPConnection connection) {
|
||||||
OpenPgpManager manager = INSTANCES.get(connection);
|
OpenPgpManager manager = INSTANCES.get(connection);
|
||||||
if (manager == null) {
|
if (manager == null) {
|
||||||
|
@ -77,11 +113,32 @@ public final class OpenPgpManager extends Manager {
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the {@link OpenPgpProvider} which will be used to process incoming OpenPGP elements,
|
||||||
|
* as well as to execute cryptographic operations.
|
||||||
|
*
|
||||||
|
* @param provider OpenPgpProvider.
|
||||||
|
*/
|
||||||
public void setOpenPgpProvider(OpenPgpProvider provider) {
|
public void setOpenPgpProvider(OpenPgpProvider provider) {
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void publishPublicKey() throws Exception {
|
/**
|
||||||
|
* Publish the users OpenPGP public key to the public key node if necessary.
|
||||||
|
* Also announce the key to other users by updating the metadata node.
|
||||||
|
*
|
||||||
|
* @see <a href="https://xmpp.org/extensions/xep-0373.html#annoucning-pubkey">XEP-0373 §4.1</a>.
|
||||||
|
*
|
||||||
|
* @throws CorruptedOpenPgpKeyException if our OpenPGP key is corrupted and for that reason cannot be serialized.
|
||||||
|
* @throws InterruptedException
|
||||||
|
* @throws PubSubException.NotALeafNodeException
|
||||||
|
* @throws XMPPException.XMPPErrorException
|
||||||
|
* @throws SmackException.NotConnectedException
|
||||||
|
* @throws SmackException.NoResponseException
|
||||||
|
*/
|
||||||
|
public void publishPublicKey()
|
||||||
|
throws CorruptedOpenPgpKeyException, InterruptedException, PubSubException.NotALeafNodeException,
|
||||||
|
XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException {
|
||||||
ensureProviderIsSet();
|
ensureProviderIsSet();
|
||||||
PubkeyElement pubkeyElement = provider.createPubkeyElement();
|
PubkeyElement pubkeyElement = provider.createPubkeyElement();
|
||||||
|
|
||||||
|
@ -96,9 +153,11 @@ public final class OpenPgpManager extends Manager {
|
||||||
if (items.isEmpty()) {
|
if (items.isEmpty()) {
|
||||||
LOGGER.log(Level.FINE, "Node " + keyNodeName + " is empty. Publish.");
|
LOGGER.log(Level.FINE, "Node " + keyNodeName + " is empty. Publish.");
|
||||||
keyNode.publish(new PayloadItem<>(pubkeyElement));
|
keyNode.publish(new PayloadItem<>(pubkeyElement));
|
||||||
|
} else {
|
||||||
|
LOGGER.log(Level.FINE, "Node " + keyNodeName + " already contains key. Skip.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Publish ID to metadata node
|
// Fetch IDs from metadata node
|
||||||
LeafNode metadataNode = pm.getOrCreateLeafNode(PEP_NODE_PUBLIC_KEYS);
|
LeafNode metadataNode = pm.getOrCreateLeafNode(PEP_NODE_PUBLIC_KEYS);
|
||||||
List<PayloadItem<PublicKeysListElement>> metadataItems = metadataNode.getItems(1);
|
List<PayloadItem<PublicKeysListElement>> metadataItems = metadataNode.getItems(1);
|
||||||
|
|
||||||
|
@ -112,9 +171,22 @@ public final class OpenPgpManager extends Manager {
|
||||||
}
|
}
|
||||||
builder.addMetadata(new PublicKeysListElement.PubkeyMetadataElement(fingerprint, new Date()));
|
builder.addMetadata(new PublicKeysListElement.PubkeyMetadataElement(fingerprint, new Date()));
|
||||||
|
|
||||||
|
// Publish IDs to metadata node
|
||||||
metadataNode.publish(new PayloadItem<>(builder.build()));
|
metadataNode.publish(new PayloadItem<>(builder.build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consult the public key metadata node and fetch a list of all of our published OpenPGP public keys.
|
||||||
|
* TODO: Add @see which points to the (for now missing) respective example in XEP-0373.
|
||||||
|
*
|
||||||
|
* @return content of our metadata node.
|
||||||
|
* @throws InterruptedException
|
||||||
|
* @throws PubSubException.NotALeafNodeException
|
||||||
|
* @throws SmackException.NoResponseException
|
||||||
|
* @throws SmackException.NotConnectedException
|
||||||
|
* @throws XMPPException.XMPPErrorException
|
||||||
|
* @throws PubSubException.NotAPubSubNodeException
|
||||||
|
*/
|
||||||
public PublicKeysListElement fetchPubkeysList()
|
public PublicKeysListElement fetchPubkeysList()
|
||||||
throws InterruptedException, PubSubException.NotALeafNodeException, SmackException.NoResponseException,
|
throws InterruptedException, PubSubException.NotALeafNodeException, SmackException.NoResponseException,
|
||||||
SmackException.NotConnectedException, XMPPException.XMPPErrorException,
|
SmackException.NotConnectedException, XMPPException.XMPPErrorException,
|
||||||
|
@ -122,18 +194,24 @@ public final class OpenPgpManager extends Manager {
|
||||||
return fetchPubkeysList(connection().getUser().asBareJid());
|
return fetchPubkeysList(connection().getUser().asBareJid());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deletePubkeysListNode()
|
/**
|
||||||
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
* Consult the public key metadata node of {@code contact} to fetch the list of their published OpenPGP public keys.
|
||||||
SmackException.NoResponseException {
|
* TODO: Add @see which points to the (for now missing) respective example in XEP-0373.
|
||||||
PubSubManager pm = PubSubManager.getInstance(connection(), connection().getUser().asBareJid());
|
*
|
||||||
pm.deleteNode(PEP_NODE_PUBLIC_KEYS);
|
* @param contact {@link BareJid} of the user we want to fetch the list from.
|
||||||
}
|
* @return content of {@code contact}'s metadata node.
|
||||||
|
* @throws InterruptedException
|
||||||
public PublicKeysListElement fetchPubkeysList(BareJid jid)
|
* @throws PubSubException.NotALeafNodeException
|
||||||
|
* @throws SmackException.NoResponseException
|
||||||
|
* @throws SmackException.NotConnectedException
|
||||||
|
* @throws XMPPException.XMPPErrorException
|
||||||
|
* @throws PubSubException.NotAPubSubNodeException
|
||||||
|
*/
|
||||||
|
public PublicKeysListElement fetchPubkeysList(BareJid contact)
|
||||||
throws InterruptedException, PubSubException.NotALeafNodeException, SmackException.NoResponseException,
|
throws InterruptedException, PubSubException.NotALeafNodeException, SmackException.NoResponseException,
|
||||||
SmackException.NotConnectedException, XMPPException.XMPPErrorException,
|
SmackException.NotConnectedException, XMPPException.XMPPErrorException,
|
||||||
PubSubException.NotAPubSubNodeException {
|
PubSubException.NotAPubSubNodeException {
|
||||||
PubSubManager pm = PubSubManager.getInstance(connection(), jid);
|
PubSubManager pm = PubSubManager.getInstance(connection(), contact);
|
||||||
|
|
||||||
LeafNode node = pm.getLeafNode(PEP_NODE_PUBLIC_KEYS);
|
LeafNode node = pm.getLeafNode(PEP_NODE_PUBLIC_KEYS);
|
||||||
List<PayloadItem<PublicKeysListElement>> list = node.getItems(1);
|
List<PayloadItem<PublicKeysListElement>> list = node.getItems(1);
|
||||||
|
@ -145,11 +223,41 @@ public final class OpenPgpManager extends Manager {
|
||||||
return list.get(0).getPayload();
|
return list.get(0).getPayload();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PubkeyElement fetchPubkey(BareJid jid, String v4_fingerprint)
|
/**
|
||||||
|
* Delete our metadata node.
|
||||||
|
*
|
||||||
|
* @throws XMPPException.XMPPErrorException
|
||||||
|
* @throws SmackException.NotConnectedException
|
||||||
|
* @throws InterruptedException
|
||||||
|
* @throws SmackException.NoResponseException
|
||||||
|
*/
|
||||||
|
public void deletePubkeysListNode()
|
||||||
|
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||||
|
SmackException.NoResponseException {
|
||||||
|
PubSubManager pm = PubSubManager.getInstance(connection(), connection().getUser().asBareJid());
|
||||||
|
pm.deleteNode(PEP_NODE_PUBLIC_KEYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the OpenPGP public key of a {@code contact}, identified by its OpenPGP {@code v4_fingerprint}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://xmpp.org/extensions/xep-0373.html#discover-pubkey">XEP-0373 §4.3</a>.
|
||||||
|
*
|
||||||
|
* @param contact {@link BareJid} of the contact we want to fetch a key from.
|
||||||
|
* @param v4_fingerprint upper case, hex encoded v4 fingerprint of the contacts key.
|
||||||
|
* @return {@link PubkeyElement} containing the requested public key.
|
||||||
|
* @throws InterruptedException
|
||||||
|
* @throws PubSubException.NotALeafNodeException
|
||||||
|
* @throws SmackException.NoResponseException
|
||||||
|
* @throws SmackException.NotConnectedException
|
||||||
|
* @throws XMPPException.XMPPErrorException
|
||||||
|
* @throws PubSubException.NotAPubSubNodeException
|
||||||
|
*/
|
||||||
|
public PubkeyElement fetchPubkey(BareJid contact, String v4_fingerprint)
|
||||||
throws InterruptedException, PubSubException.NotALeafNodeException, SmackException.NoResponseException,
|
throws InterruptedException, PubSubException.NotALeafNodeException, SmackException.NoResponseException,
|
||||||
SmackException.NotConnectedException, XMPPException.XMPPErrorException,
|
SmackException.NotConnectedException, XMPPException.XMPPErrorException,
|
||||||
PubSubException.NotAPubSubNodeException {
|
PubSubException.NotAPubSubNodeException {
|
||||||
PubSubManager pm = PubSubManager.getInstance(connection(), jid);
|
PubSubManager pm = PubSubManager.getInstance(connection(), contact);
|
||||||
|
|
||||||
LeafNode node = pm.getLeafNode(PEP_NODE_PUBLIC_KEY(v4_fingerprint));
|
LeafNode node = pm.getLeafNode(PEP_NODE_PUBLIC_KEY(v4_fingerprint));
|
||||||
List<PayloadItem<PubkeyElement>> list = node.getItems(1);
|
List<PayloadItem<PubkeyElement>> list = node.getItems(1);
|
||||||
|
@ -161,6 +269,9 @@ public final class OpenPgpManager extends Manager {
|
||||||
return list.get(0).getPayload();
|
return list.get(0).getPayload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Implement and document.
|
||||||
|
*/
|
||||||
public void depositSecretKey() {
|
public void depositSecretKey() {
|
||||||
ensureProviderIsSet();
|
ensureProviderIsSet();
|
||||||
// Create key backup by appending serialized unencrypted secret keys.
|
// Create key backup by appending serialized unencrypted secret keys.
|
||||||
|
@ -169,13 +280,20 @@ public final class OpenPgpManager extends Manager {
|
||||||
// Display the backup key to the user
|
// Display the backup key to the user
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOurFingerprint() throws Exception {
|
/**
|
||||||
|
* Return the upper-case hex encoded OpenPGP v4 fingerprint of our key pair.
|
||||||
|
*
|
||||||
|
* @return fingerprint.
|
||||||
|
* @throws CorruptedOpenPgpKeyException if for some reason we cannot determine our fingerprint.
|
||||||
|
*/
|
||||||
|
public String getOurFingerprint() throws CorruptedOpenPgpKeyException {
|
||||||
ensureProviderIsSet();
|
ensureProviderIsSet();
|
||||||
return provider.getFingerprint();
|
return provider.getFingerprint();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throw an {@link IllegalStateException} if no {@link OpenPgpProvider} is set.
|
* Throw an {@link IllegalStateException} if no {@link OpenPgpProvider} is set.
|
||||||
|
* The OpenPgpProvider is used to process information related to RFC-4880.
|
||||||
*/
|
*/
|
||||||
private void ensureProviderIsSet() {
|
private void ensureProviderIsSet() {
|
||||||
if (provider == null) {
|
if (provider == null) {
|
||||||
|
@ -183,6 +301,18 @@ public final class OpenPgpManager extends Manager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine, if we can sync secret keys using private PEP nodes as described in the XEP.
|
||||||
|
* Requirements on the server side are support for PEP and support for the whitelist access model of PubSub.
|
||||||
|
*
|
||||||
|
* @see <a href="https://xmpp.org/extensions/xep-0373.html#synchro-pep">XEP-0373 §5</a> for more information.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @throws XMPPException.XMPPErrorException
|
||||||
|
* @throws SmackException.NotConnectedException
|
||||||
|
* @throws InterruptedException
|
||||||
|
* @throws SmackException.NoResponseException
|
||||||
|
*/
|
||||||
public boolean canSyncSecretKey()
|
public boolean canSyncSecretKey()
|
||||||
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||||
SmackException.NoResponseException {
|
SmackException.NoResponseException {
|
||||||
|
@ -192,9 +322,14 @@ public final class OpenPgpManager extends Manager {
|
||||||
return pep && whitelist;
|
return pep && whitelist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link PEPListener} that listens for changes to the OX public keys metadata node.
|
||||||
|
*
|
||||||
|
* @see <a href="https://xmpp.org/extensions/xep-0373.html#pubsub-notifications">XEP-0373 §4.4</a>.
|
||||||
|
*/
|
||||||
private final PEPListener metadataListener = new PEPListener() {
|
private final PEPListener metadataListener = new PEPListener() {
|
||||||
@Override
|
@Override
|
||||||
public void eventReceived(EntityBareJid from, final EventElement event, Message message) {
|
public void eventReceived(final EntityBareJid from, final EventElement event, Message message) {
|
||||||
if (PEP_NODE_PUBLIC_KEYS.equals(event.getEvent().getNode())) {
|
if (PEP_NODE_PUBLIC_KEYS.equals(event.getEvent().getNode())) {
|
||||||
LOGGER.log(Level.INFO, "Received OpenPGP metadata update from " + from);
|
LOGGER.log(Level.INFO, "Received OpenPGP metadata update from " + from);
|
||||||
Async.go(new Runnable() {
|
Async.go(new Runnable() {
|
||||||
|
@ -204,6 +339,11 @@ public final class OpenPgpManager extends Manager {
|
||||||
PayloadItem<?> payload = (PayloadItem) items.getItems().get(0);
|
PayloadItem<?> payload = (PayloadItem) items.getItems().get(0);
|
||||||
PublicKeysListElement listElement = (PublicKeysListElement) payload.getPayload();
|
PublicKeysListElement listElement = (PublicKeysListElement) payload.getPayload();
|
||||||
|
|
||||||
|
try {
|
||||||
|
provider.processPublicKeysListElement(listElement, from.asBareJid());
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.log(Level.WARNING, "Error processing OpenPGP metadata update from " + from, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, "ProcessOXPublicKey");
|
}, "ProcessOXPublicKey");
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Set;
|
||||||
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
||||||
|
import org.jivesoftware.smackx.ox.exception.CorruptedOpenPgpKeyException;
|
||||||
|
|
||||||
import org.jxmpp.jid.BareJid;
|
import org.jxmpp.jid.BareJid;
|
||||||
|
|
||||||
|
@ -35,9 +36,9 @@ public interface OpenPgpProvider {
|
||||||
|
|
||||||
OpenPgpElement encrypt(InputStream inputStream, Set<BareJid> recipients) throws Exception;
|
OpenPgpElement encrypt(InputStream inputStream, Set<BareJid> recipients) throws Exception;
|
||||||
|
|
||||||
PubkeyElement createPubkeyElement() throws Exception;
|
PubkeyElement createPubkeyElement() throws CorruptedOpenPgpKeyException;
|
||||||
|
|
||||||
void processPubkeyElement(PubkeyElement element, BareJid from) throws Exception;
|
void processPubkeyElement(PubkeyElement element, BareJid from) throws CorruptedOpenPgpKeyException;
|
||||||
|
|
||||||
void processPublicKeysListElement(PublicKeysListElement listElement, BareJid from) throws Exception;
|
void processPublicKeysListElement(PublicKeysListElement listElement, BareJid from) throws Exception;
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ public interface OpenPgpProvider {
|
||||||
* Return the OpenPGP v4-fingerprint of our key in hexadecimal upper case.
|
* Return the OpenPGP v4-fingerprint of our key in hexadecimal upper case.
|
||||||
*
|
*
|
||||||
* @return fingerprint
|
* @return fingerprint
|
||||||
* @throws Exception
|
* @throws CorruptedOpenPgpKeyException if for some reason the fingerprint cannot be derived from the key pair.
|
||||||
*/
|
*/
|
||||||
String getFingerprint() throws Exception;
|
String getFingerprint() throws CorruptedOpenPgpKeyException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smackx.ox;
|
package org.jivesoftware.smackx.ox.exception;
|
||||||
|
|
||||||
public class CorruptedOpenPgpKeyException extends Exception {
|
public class CorruptedOpenPgpKeyException extends Exception {
|
||||||
|
|
||||||
|
@ -23,4 +23,8 @@ public class CorruptedOpenPgpKeyException extends Exception {
|
||||||
public CorruptedOpenPgpKeyException() {
|
public CorruptedOpenPgpKeyException() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CorruptedOpenPgpKeyException(Exception cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2017 Florian Schmaus.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Exceptions for XEP-0373: OpenPGP for XMPP.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.ox.exception;
|
Loading…
Reference in a new issue