diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java index 1cefaaf48..594c8377f 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java @@ -140,6 +140,15 @@ import org.xmlpull.v1.XmlPullParserException; * {@link OpenPgpSelf}, which encapsulates your own OpenPGP identity. Both classes can be used to acquire information * about the OpenPGP keys of a user. * + *

Elements

+ * + * OpenPGP for XMPP defines multiple different element classes which contain the users messages. + * The outermost element is the {@link OpenPgpElement}, which contains an OpenPGP encrypted content element. + * + * The content can be either a {@link SignElement}, {@link CryptElement} or {@link SigncryptElement}, depending on the use-case. + * Those content elements contain the actual payload. If an {@link OpenPgpElement} is decrypted, it will be returned in + * form of an {@link OpenPgpMessage}, which represents the decrypted message + metadata. + * * @see * XEP-0373: OpenPGP for XMPP */ @@ -518,8 +527,21 @@ public final class OpenPgpManager extends Manager { } } - public OpenPgpMessage decryptOpenPgpElement(OpenPgpElement element, OpenPgpContact contact) throws SmackException.NotLoggedInException, IOException, PGPException { - return provider.decryptAndOrVerify(element, getOpenPgpSelf(), contact); + /** + * Decrypt and or verify an {@link OpenPgpElement} and return the decrypted {@link OpenPgpMessage}. + * + * @param element {@link OpenPgpElement} containing the message. + * @param sender {@link OpenPgpContact} who sent the message. + * + * @return decrypted and/or verified message + * + * @throws SmackException.NotLoggedInException in case we aren't logged in (we need to know our jid) + * @throws IOException IO error (reading keys, streams etc) + * @throws PGPException in case of an PGP error + */ + public OpenPgpMessage decryptOpenPgpElement(OpenPgpElement element, OpenPgpContact sender) + throws SmackException.NotLoggedInException, IOException, PGPException { + return provider.decryptAndOrVerify(element, getOpenPgpSelf(), sender); } private final IncomingChatMessageListener incomingOpenPgpMessageListener = diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpMessage.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpMessage.java index 61176586b..b2472576b 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpMessage.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpMessage.java @@ -31,7 +31,18 @@ import org.pgpainless.decryption_verification.OpenPgpMetadata; import org.xmlpull.v1.XmlPullParserException; /** - * This class embodies a decrypted {@link OpenPgpElement}. + * This class embodies a decrypted and/or verified {@link OpenPgpElement}. + *
+ * The content can be one of the following three {@link OpenPgpContentElement}s: + *

+ * {@link SignElement}: The content is expected to be signed with the senders key, but unencrypted.
+ * {@link CryptElement}: The content is expected to be encrypted, but not signed.
+ * {@link SigncryptElement}: The content is expected to be signed with the senders key and encrypted.
+ *
+ * To determine, of which nature the content of the message is, use {@link #getState()}. You should utilize this + * information to cast the return value of {@link #getOpenPgpContentElement()} correctly. + *
+ * Use {@link #getMetadata()} in order to get information about the messages encryption status, its signatures etc. */ public class OpenPgpMessage { diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpSelf.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpSelf.java index 38969af49..eeed7966a 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpSelf.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpSelf.java @@ -30,8 +30,18 @@ import org.jxmpp.jid.BareJid; import org.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.util.BCUtil; +/** + * This class acts as our own OpenPGP identity. It can be seen as a special view on the {@link OpenPgpStore}, giving + * access to our own encryption keys etc. + */ public class OpenPgpSelf extends OpenPgpContact { + /** + * Constructor. + * + * @param jid our own {@link BareJid}. This is needed to access our keys in the store. + * @param store the store. + */ OpenPgpSelf(BareJid jid, OpenPgpStore store) { super(jid, store); } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManager.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManager.java index 35964b17d..0056a121c 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManager.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManager.java @@ -38,6 +38,7 @@ import org.jivesoftware.smackx.ox.OpenPgpContact; import org.jivesoftware.smackx.ox.OpenPgpManager; import org.jivesoftware.smackx.ox.OpenPgpMessage; import org.jivesoftware.smackx.ox.crypto.OpenPgpElementAndMetadata; +import org.jivesoftware.smackx.ox.element.OpenPgpContentElement; import org.jivesoftware.smackx.ox.element.OpenPgpElement; import org.jivesoftware.smackx.ox.element.SigncryptElement; import org.jivesoftware.smackx.ox.listener.SigncryptElementReceivedListener; @@ -47,6 +48,7 @@ import org.jxmpp.jid.BareJid; import org.jxmpp.jid.Jid; import org.pgpainless.decryption_verification.OpenPgpMetadata; import org.pgpainless.key.OpenPgpV4Fingerprint; +import org.xmlpull.v1.XmlPullParserException; /** * Entry point of Smacks API for XEP-0374: OpenPGP for XMPP: Instant Messaging. @@ -314,6 +316,33 @@ public final class OXInstantMessagingManager extends Manager { return encrypted; } + /** + * Manually decrypt and verify an {@link OpenPgpElement}. + * + * @param element encrypted, signed {@link OpenPgpElement}. + * @param sender sender of the message. + * + * @return decrypted, verified message + * + * @throws SmackException.NotLoggedInException In case we are not logged in (we need our jid to access our keys) + * @throws PGPException in case of an PGP error + * @throws IOException in case of an IO error (reading keys, streams etc) + * @throws XmlPullParserException in case that the content of the {@link OpenPgpElement} is not a valid + * {@link OpenPgpContentElement} or broken XML. + * @throws IllegalArgumentException if the elements content is not a {@link SigncryptElement}. This happens, if the + * element likely is not an OX message. + */ + public OpenPgpMessage decryptAndVerify(OpenPgpElement element, OpenPgpContact sender) + throws SmackException.NotLoggedInException, PGPException, IOException, XmlPullParserException { + + OpenPgpMessage decrypted = openPgpManager.decryptOpenPgpElement(element, sender); + if (decrypted.getState() != OpenPgpMessage.State.signcrypt) { + throw new IllegalArgumentException("Decrypted message does appear to not be an OX message. (State: " + decrypted.getState() + ")"); + } + + return decrypted; + } + /** * Set a hint about the message being OX-IM encrypted as body of the message. *