Package org.jivesoftware.smackx.omemo
Class OmemoManager
- java.lang.Object
-
- org.jivesoftware.smack.Manager
-
- org.jivesoftware.smackx.omemo.OmemoManager
-
public final class OmemoManager extends Manager
Manager that allows sending messages encrypted with OMEMO. This class also provides some methods useful for a client that implements OMEMO.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static interface
OmemoManager.InitializationFinishedCallback
Callback which can be used to get notified, when the OmemoManager finished initializing.static class
OmemoManager.LoggedInOmemoManager
Guard class which ensures that the wrapped OmemoManager knows its BareJid.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description void
addOmemoMessageListener(OmemoMessageListener listener)
Add an OmemoMessageListener.void
addOmemoMucMessageListener(OmemoMucMessageListener listener)
Add an OmemoMucMessageListener.boolean
contactSupportsOmemo(BareJid contact)
Returns true, if the contact has any active devices published in a deviceList.OmemoMessage.Received
decrypt(BareJid sender, OmemoElement omemoElement)
Manually decrypt an OmemoElement.java.util.List<MessageOrOmemoMessage>
decryptMamQueryResult(MamManager.MamQuery mamQuery)
Decrypt messages from a MAM query.void
distrustOmemoIdentity(OmemoDevice device, OmemoFingerprint fingerprint)
Distrust the fingerprint/OmemoDevice tuple.OmemoMessage.Sent
encrypt(java.util.Set<BareJid> recipients, java.lang.String message)
OMEMO encrypt a cleartext message for multiple recipients.OmemoMessage.Sent
encrypt(MultiUserChat muc, java.lang.String message)
Encrypt a message for all recipients in the MultiUserChat.OmemoMessage.Sent
encrypt(BareJid recipient, java.lang.String message)
OMEMO encrypt a cleartext message for a single recipient.java.util.HashMap<OmemoDevice,OmemoFingerprint>
getActiveFingerprints(BareJid contact)
Return all OmemoFingerprints of active devices of a contact.java.lang.Integer
getDeviceId()
Return the deviceId of this OmemoManager.java.util.Set<OmemoDevice>
getDevicesOf(BareJid contact)
Return a set of all OMEMO capable devices of a contact.OmemoFingerprint
getFingerprint(OmemoDevice device)
Get the fingerprint of a contacts device.static OmemoManager
getInstanceFor(XMPPConnection connection)
Returns an OmemoManager instance for the given connection.static OmemoManager
getInstanceFor(XMPPConnection connection, java.lang.Integer deviceId)
Return an OmemoManager instance for the given connection and deviceId.OmemoDevice
getOwnDevice()
Return the OmemoDevice of the user.OmemoFingerprint
getOwnFingerprint()
Return the fingerprint of our identity key.BareJid
getOwnJid()
Return the BareJid of the user.void
initialize()
Initializes the OmemoManager.void
initializeAsync(OmemoManager.InitializationFinishedCallback finishedCallback)
Initialize the manager without blocking.boolean
isDecidedOmemoIdentity(OmemoDevice device, OmemoFingerprint fingerprint)
Returns true, if the fingerprint/OmemoDevice tuple is decided by the user.boolean
isTrustedOmemoIdentity(OmemoDevice device, OmemoFingerprint fingerprint)
Returns true, if the fingerprint/OmemoDevice tuple is trusted, otherwise false.boolean
multiUserChatSupportsOmemo(MultiUserChat multiUserChat)
Returns true, if the MUC with the EntityBareJid multiUserChat is non-anonymous and members only (prerequisite for OMEMO encryption in MUC).void
purgeDeviceList()
Publish a new device list with just our own deviceId in it.static int
randomDeviceId()
Returns a pseudo random number from the interval [1, Integer.MAX_VALUE].void
rebuildSessionWith(OmemoDevice contactsDevice)
Build a fresh session with a contacts device.void
removeOmemoMessageListener(OmemoMessageListener listener)
Remove an OmemoMessageListener.void
removeOmemoMucMessageListener(OmemoMucMessageListener listener)
Remove an OmemoMucMessageListener.void
requestDeviceListUpdateFor(BareJid contact)
Request a deviceList update from contact contact.void
resumeStanzaAndPEPListeners()
Register stanza listeners needed for OMEMO.void
rotateSignedPreKey()
Rotate the signedPreKey published in our OmemoBundle and republish it.void
sendRatchetUpdateMessage(OmemoDevice recipient)
Send a ratchet update message.static boolean
serverSupportsOmemo(XMPPConnection connection, DomainBareJid server)
Returns true, if the Server supports PEP.void
setTrustCallback(OmemoTrustCallback callback)
Set a TrustCallback for this particular OmemoManager.void
stopStanzaAndPEPListeners()
Remove active stanza listeners needed for OMEMO.void
trustOmemoIdentity(OmemoDevice device, OmemoFingerprint fingerprint)
Trust that a fingerprint belongs to an OmemoDevice.-
Methods inherited from class org.jivesoftware.smack.Manager
connection, getAuthenticatedConnectionOrThrow, schedule, schedule, scheduleBlocking
-
-
-
-
Method Detail
-
getInstanceFor
public static OmemoManager getInstanceFor(XMPPConnection connection, java.lang.Integer deviceId)
Return an OmemoManager instance for the given connection and deviceId. If there was an OmemoManager for the connection and id before, return it. Otherwise create a new OmemoManager instance and return it.- Parameters:
connection
- XmppConnection.deviceId
- MUST NOT be null and MUST be greater than 0.- Returns:
- OmemoManager instance for the given connection and deviceId.
-
getInstanceFor
public static OmemoManager getInstanceFor(XMPPConnection connection)
Returns an OmemoManager instance for the given connection. If there was one manager for the connection before, return it. If there were multiple managers before, return the one with the lowest deviceId. If there was no manager before, return a new one. As soon as the connection gets authenticated, the manager will look for local deviceIDs and select the lowest one as its id. If there are not local deviceIds, the manager will assign itself a random id.- Parameters:
connection
- XmppConnection.- Returns:
- OmemoManager instance for the given connection and a determined deviceId.
-
setTrustCallback
public void setTrustCallback(OmemoTrustCallback callback)
Set a TrustCallback for this particular OmemoManager. TrustCallbacks are used to query and modify trust decisions.- Parameters:
callback
- trustCallback.
-
initialize
public void initialize() throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, java.lang.InterruptedException, SmackException.NoResponseException, SmackException.NotConnectedException, XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException, java.io.IOException
Initializes the OmemoManager. This method must be called before the manager can be used.- Throws:
CorruptedOmemoKeyException
- if the OMEMO key is corrupted.java.lang.InterruptedException
- if the calling thread was interrupted.SmackException.NoResponseException
- if there was no response from the remote entity.SmackException.NotConnectedException
- if the XMPP connection is not connected.XMPPException.XMPPErrorException
- if there was an XMPP error returned.SmackException.NotLoggedInException
- if the XMPP connection is not authenticated.PubSubException.NotALeafNodeException
- if a PubSub leaf node operation was attempted on a non-leaf node.java.io.IOException
- if an I/O error occurred.
-
initializeAsync
public void initializeAsync(OmemoManager.InitializationFinishedCallback finishedCallback)
Initialize the manager without blocking. Once the manager is successfully initialized, the finishedCallback will be notified. It will also get notified, if an error occurs.- Parameters:
finishedCallback
- callback that gets called once the manager is initialized.
-
getDevicesOf
public java.util.Set<OmemoDevice> getDevicesOf(BareJid contact) throws java.io.IOException
Return a set of all OMEMO capable devices of a contact. Note, that this method does not explicitly refresh the device list of the contact, so it might be outdated.- Parameters:
contact
- contact we want to get a set of device of.- Returns:
- set of known devices of that contact.
- Throws:
java.io.IOException
- if an I/O error occurred.- See Also:
requestDeviceListUpdateFor(BareJid)
-
encrypt
public OmemoMessage.Sent encrypt(BareJid recipient, java.lang.String message) throws CryptoFailedException, UndecidedOmemoIdentityException, java.lang.InterruptedException, SmackException.NotConnectedException, SmackException.NoResponseException, SmackException.NotLoggedInException, java.io.IOException
OMEMO encrypt a cleartext message for a single recipient. Note that this method does NOT set the 'to' attribute of the message.- Parameters:
recipient
- recipients bareJidmessage
- text to encrypt- Returns:
- encrypted message
- Throws:
CryptoFailedException
- when something crypto related failsUndecidedOmemoIdentityException
- When there are undecided devicesjava.lang.InterruptedException
- if the calling thread was interrupted.SmackException.NotConnectedException
- if the XMPP connection is not connected.SmackException.NoResponseException
- if there was no response from the remote entity.SmackException.NotLoggedInException
- if the XMPP connection is not authenticated.java.io.IOException
- if an I/O error occurred.
-
encrypt
public OmemoMessage.Sent encrypt(java.util.Set<BareJid> recipients, java.lang.String message) throws CryptoFailedException, UndecidedOmemoIdentityException, java.lang.InterruptedException, SmackException.NotConnectedException, SmackException.NoResponseException, SmackException.NotLoggedInException, java.io.IOException
OMEMO encrypt a cleartext message for multiple recipients.- Parameters:
recipients
- recipients barejidsmessage
- text to encrypt- Returns:
- encrypted message.
- Throws:
CryptoFailedException
- When something crypto related failsUndecidedOmemoIdentityException
- When there are undecided devices.java.lang.InterruptedException
- if the calling thread was interrupted.SmackException.NotConnectedException
- if the XMPP connection is not connected.SmackException.NoResponseException
- if there was no response from the remote entity.SmackException.NotLoggedInException
- if the XMPP connection is not authenticated.java.io.IOException
- if an I/O error occurred.
-
encrypt
public OmemoMessage.Sent encrypt(MultiUserChat muc, java.lang.String message) throws UndecidedOmemoIdentityException, CryptoFailedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, java.lang.InterruptedException, SmackException.NoResponseException, NoOmemoSupportException, SmackException.NotLoggedInException, java.io.IOException
Encrypt a message for all recipients in the MultiUserChat.- Parameters:
muc
- multiUserChatmessage
- message to send- Returns:
- encrypted message
- Throws:
UndecidedOmemoIdentityException
- when there are undecided devices.CryptoFailedException
- if the OMEMO cryptography failed.XMPPException.XMPPErrorException
- if there was an XMPP error returned.SmackException.NotConnectedException
- if the XMPP connection is not connected.java.lang.InterruptedException
- if the calling thread was interrupted.SmackException.NoResponseException
- if there was no response from the remote entity.NoOmemoSupportException
- When the muc doesn't support OMEMO.SmackException.NotLoggedInException
- if the XMPP connection is not authenticated.java.io.IOException
- if an I/O error occurred.
-
decrypt
public OmemoMessage.Received decrypt(BareJid sender, OmemoElement omemoElement) throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, NoRawSessionException, CryptoFailedException, java.io.IOException
Manually decrypt an OmemoElement. This method should only be used for use-cases, where the internal listeners don't pick up on an incoming message. (for example MAM query results).- Parameters:
sender
- bareJid of the message sender (must be the jid of the contact who sent the message)omemoElement
- omemoElement- Returns:
- decrypted OmemoMessage
- Throws:
SmackException.NotLoggedInException
- if the Manager is not authenticatedCorruptedOmemoKeyException
- if our or their key is corruptedNoRawSessionException
- if the message was not a preKeyMessage, but we had no session with the contactCryptoFailedException
- if decryption failsjava.io.IOException
- if an I/O error occurred.
-
decryptMamQueryResult
public java.util.List<MessageOrOmemoMessage> decryptMamQueryResult(MamManager.MamQuery mamQuery) throws SmackException.NotLoggedInException, java.io.IOException
Decrypt messages from a MAM query.- Parameters:
mamQuery
- The MAM query- Returns:
- list of decrypted OmemoMessages
- Throws:
SmackException.NotLoggedInException
- if the Manager is not authenticated.java.io.IOException
- if an I/O error occurred.
-
trustOmemoIdentity
public void trustOmemoIdentity(OmemoDevice device, OmemoFingerprint fingerprint)
Trust that a fingerprint belongs to an OmemoDevice. The fingerprint must be the lowercase, hexadecimal fingerprint of the identityKey of the device and must be of length 64.- Parameters:
device
- devicefingerprint
- fingerprint
-
distrustOmemoIdentity
public void distrustOmemoIdentity(OmemoDevice device, OmemoFingerprint fingerprint)
Distrust the fingerprint/OmemoDevice tuple. The fingerprint must be the lowercase, hexadecimal fingerprint of the identityKey of the device and must be of length 64.- Parameters:
device
- devicefingerprint
- fingerprint
-
isTrustedOmemoIdentity
public boolean isTrustedOmemoIdentity(OmemoDevice device, OmemoFingerprint fingerprint)
Returns true, if the fingerprint/OmemoDevice tuple is trusted, otherwise false. The fingerprint must be the lowercase, hexadecimal fingerprint of the identityKey of the device and must be of length 64.- Parameters:
device
- devicefingerprint
- fingerprint- Returns:
true
if this is a trusted OMEMO identity.
-
isDecidedOmemoIdentity
public boolean isDecidedOmemoIdentity(OmemoDevice device, OmemoFingerprint fingerprint)
Returns true, if the fingerprint/OmemoDevice tuple is decided by the user. The fingerprint must be the lowercase, hexadecimal fingerprint of the identityKey of the device and must be of length 64.- Parameters:
device
- devicefingerprint
- fingerprint- Returns:
true
if the trust is decided for the identity.
-
sendRatchetUpdateMessage
public void sendRatchetUpdateMessage(OmemoDevice recipient) throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, java.lang.InterruptedException, SmackException.NoResponseException, java.security.NoSuchAlgorithmException, SmackException.NotConnectedException, CryptoFailedException, CannotEstablishOmemoSessionException, java.io.IOException
Send a ratchet update message. This can be used to advance the ratchet of a session in order to maintain forward secrecy.- Parameters:
recipient
- recipient- Throws:
CorruptedOmemoKeyException
- When the used identityKeys are corruptedCryptoFailedException
- When something fails with the cryptoCannotEstablishOmemoSessionException
- When we can't establish a session with the recipientSmackException.NotLoggedInException
- if the XMPP connection is not authenticated.java.lang.InterruptedException
- if the calling thread was interrupted.SmackException.NoResponseException
- if there was no response from the remote entity.java.security.NoSuchAlgorithmException
- if no such algorithm is available.SmackException.NotConnectedException
- if the XMPP connection is not connected.java.io.IOException
- if an I/O error occurred.
-
contactSupportsOmemo
public boolean contactSupportsOmemo(BareJid contact) throws java.lang.InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException, java.io.IOException
Returns true, if the contact has any active devices published in a deviceList.- Parameters:
contact
- contact- Returns:
- true if contact has at least one OMEMO capable device.
- Throws:
SmackException.NotConnectedException
- if the XMPP connection is not connected.java.lang.InterruptedException
- if the calling thread was interrupted.SmackException.NoResponseException
- if there was no response from the remote entity.PubSubException.NotALeafNodeException
- if a PubSub leaf node operation was attempted on a non-leaf node.XMPPException.XMPPErrorException
- if there was an XMPP error returned.java.io.IOException
- if an I/O error occurred.
-
multiUserChatSupportsOmemo
public boolean multiUserChatSupportsOmemo(MultiUserChat multiUserChat) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, java.lang.InterruptedException, SmackException.NoResponseException
Returns true, if the MUC with the EntityBareJid multiUserChat is non-anonymous and members only (prerequisite for OMEMO encryption in MUC).- Parameters:
multiUserChat
- MUC- Returns:
- true if chat supports OMEMO
- Throws:
XMPPException.XMPPErrorException
- if there was an XMPP protocol level errorSmackException.NotConnectedException
- if the connection is not connectedjava.lang.InterruptedException
- if the thread is interruptedSmackException.NoResponseException
- if the server does not respond
-
serverSupportsOmemo
public static boolean serverSupportsOmemo(XMPPConnection connection, DomainBareJid server) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, java.lang.InterruptedException, SmackException.NoResponseException
Returns true, if the Server supports PEP.- Parameters:
connection
- XMPPConnectionserver
- domainBareJid of the server to test- Returns:
- true if server supports pep
- Throws:
XMPPException.XMPPErrorException
- if there was an XMPP error returned.SmackException.NotConnectedException
- if the XMPP connection is not connected.java.lang.InterruptedException
- if the calling thread was interrupted.SmackException.NoResponseException
- if there was no response from the remote entity.
-
getOwnFingerprint
public OmemoFingerprint getOwnFingerprint() throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, java.io.IOException
Return the fingerprint of our identity key.- Returns:
- our own OMEMO fingerprint
- Throws:
SmackException.NotLoggedInException
- if we don't know our bareJid yet.CorruptedOmemoKeyException
- if our identityKey is corrupted.java.io.IOException
- if an I/O error occurred.
-
getFingerprint
public OmemoFingerprint getFingerprint(OmemoDevice device) throws CannotEstablishOmemoSessionException, SmackException.NotLoggedInException, CorruptedOmemoKeyException, SmackException.NotConnectedException, java.lang.InterruptedException, SmackException.NoResponseException, java.io.IOException
Get the fingerprint of a contacts device.- Parameters:
device
- contacts OmemoDevice- Returns:
- fingerprint of the given OMEMO device.
- Throws:
CannotEstablishOmemoSessionException
- if we have no session yet, and are unable to create one.SmackException.NotLoggedInException
- if the XMPP connection is not authenticated.CorruptedOmemoKeyException
- if the copy of the fingerprint we have is corrupted.SmackException.NotConnectedException
- if the XMPP connection is not connected.java.lang.InterruptedException
- if the calling thread was interrupted.SmackException.NoResponseException
- if there was no response from the remote entity.java.io.IOException
- if an I/O error occurred.
-
getActiveFingerprints
public java.util.HashMap<OmemoDevice,OmemoFingerprint> getActiveFingerprints(BareJid contact) throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, CannotEstablishOmemoSessionException, SmackException.NotConnectedException, java.lang.InterruptedException, SmackException.NoResponseException, java.io.IOException
Return all OmemoFingerprints of active devices of a contact. TODO: Make more fail-safe- Parameters:
contact
- contact- Returns:
- Map of all active devices of the contact and their fingerprints.
- Throws:
SmackException.NotLoggedInException
- if the XMPP connection is not authenticated.CorruptedOmemoKeyException
- if the OMEMO key is corrupted.CannotEstablishOmemoSessionException
- if no OMEMO session could be established.SmackException.NotConnectedException
- if the XMPP connection is not connected.java.lang.InterruptedException
- if the calling thread was interrupted.SmackException.NoResponseException
- if there was no response from the remote entity.java.io.IOException
- if an I/O error occurred.
-
addOmemoMessageListener
public void addOmemoMessageListener(OmemoMessageListener listener)
Add an OmemoMessageListener. This listener will be informed about incoming OMEMO messages (as well as KeyTransportMessages) and OMEMO encrypted message carbons.- Parameters:
listener
- OmemoMessageListener
-
removeOmemoMessageListener
public void removeOmemoMessageListener(OmemoMessageListener listener)
Remove an OmemoMessageListener.- Parameters:
listener
- OmemoMessageListener
-
addOmemoMucMessageListener
public void addOmemoMucMessageListener(OmemoMucMessageListener listener)
Add an OmemoMucMessageListener. This listener will be informed about incoming OMEMO encrypted MUC messages.- Parameters:
listener
- OmemoMessageListener.
-
removeOmemoMucMessageListener
public void removeOmemoMucMessageListener(OmemoMucMessageListener listener)
Remove an OmemoMucMessageListener.- Parameters:
listener
- OmemoMucMessageListener
-
requestDeviceListUpdateFor
public void requestDeviceListUpdateFor(BareJid contact) throws java.lang.InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException, java.io.IOException
Request a deviceList update from contact contact.- Parameters:
contact
- contact we want to obtain the deviceList from.- Throws:
java.lang.InterruptedException
- if the calling thread was interrupted.PubSubException.NotALeafNodeException
- if a PubSub leaf node operation was attempted on a non-leaf node.XMPPException.XMPPErrorException
- if there was an XMPP error returned.SmackException.NotConnectedException
- if the XMPP connection is not connected.SmackException.NoResponseException
- if there was no response from the remote entity.java.io.IOException
- if an I/O error occurred.
-
purgeDeviceList
public void purgeDeviceList() throws SmackException.NotLoggedInException, java.lang.InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException, java.io.IOException, PubSubException.NotALeafNodeException
Publish a new device list with just our own deviceId in it.- Throws:
SmackException.NotLoggedInException
- if the XMPP connection is not authenticated.java.lang.InterruptedException
- if the calling thread was interrupted.XMPPException.XMPPErrorException
- if there was an XMPP error returned.SmackException.NotConnectedException
- if the XMPP connection is not connected.SmackException.NoResponseException
- if there was no response from the remote entity.java.io.IOException
- if an I/O error occurred.PubSubException.NotALeafNodeException
- if a PubSub leaf node operation was attempted on a non-leaf node.
-
rotateSignedPreKey
public void rotateSignedPreKey() throws CorruptedOmemoKeyException, SmackException.NotLoggedInException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, java.lang.InterruptedException, SmackException.NoResponseException, java.io.IOException, PubSubException.NotALeafNodeException
Rotate the signedPreKey published in our OmemoBundle and republish it. This should be done every now and then (7-14 days). The old signedPreKey should be kept for some more time (a month or so) to enable decryption of messages that have been sent since the key was changed.- Throws:
CorruptedOmemoKeyException
- When the IdentityKeyPair is damaged.java.lang.InterruptedException
- XMPP errorXMPPException.XMPPErrorException
- XMPP errorSmackException.NotConnectedException
- XMPP errorSmackException.NoResponseException
- XMPP errorSmackException.NotLoggedInException
- if the XMPP connection is not authenticated.java.io.IOException
- if an I/O error occurred.PubSubException.NotALeafNodeException
- if a PubSub leaf node operation was attempted on a non-leaf node.
-
randomDeviceId
public static int randomDeviceId()
Returns a pseudo random number from the interval [1, Integer.MAX_VALUE].- Returns:
- a random deviceId.
-
getDeviceId
public java.lang.Integer getDeviceId()
Return the deviceId of this OmemoManager.- Returns:
- this OmemoManagers deviceId.
-
getOwnDevice
public OmemoDevice getOwnDevice()
Return the OmemoDevice of the user.- Returns:
- our own OmemoDevice
-
resumeStanzaAndPEPListeners
public void resumeStanzaAndPEPListeners()
Register stanza listeners needed for OMEMO. This method is called automatically in the constructor and should only be used to restore the previous state afterstopStanzaAndPEPListeners()
was called.
-
stopStanzaAndPEPListeners
public void stopStanzaAndPEPListeners()
Remove active stanza listeners needed for OMEMO.
-
rebuildSessionWith
public void rebuildSessionWith(OmemoDevice contactsDevice) throws java.lang.InterruptedException, SmackException.NoResponseException, CorruptedOmemoKeyException, SmackException.NotConnectedException, CannotEstablishOmemoSessionException, SmackException.NotLoggedInException
Build a fresh session with a contacts device. This might come in handy if a session is broken.- Parameters:
contactsDevice
- OmemoDevice of a contact.- Throws:
java.lang.InterruptedException
- if the calling thread was interrupted.SmackException.NoResponseException
- if there was no response from the remote entity.CorruptedOmemoKeyException
- if our or their identityKey is corrupted.SmackException.NotConnectedException
- if the XMPP connection is not connected.CannotEstablishOmemoSessionException
- if no new session can be established.SmackException.NotLoggedInException
- if the connection is not authenticated.
-
-