Search in sources :

Example 1 with OmemoElement

use of org.jivesoftware.smackx.omemo.element.OmemoElement in project Smack by igniterealtime.

the class OmemoService method onOmemoMessageStanzaReceived.

@Override
public void onOmemoMessageStanzaReceived(Stanza stanza, OmemoManager.LoggedInOmemoManager managerGuard) throws IOException {
    OmemoManager manager = managerGuard.get();
    // Avoid the ratchet being manipulated and the bundle being published multiple times simultaneously
    synchronized (manager) {
        OmemoDevice userDevice = manager.getOwnDevice();
        OmemoElement element = (OmemoElement) stanza.getExtensionElement(OmemoElement.NAME_ENCRYPTED, OmemoElement_VAxolotl.NAMESPACE);
        if (element == null) {
            return;
        }
        OmemoMessage.Received decrypted;
        BareJid sender;
        try {
            MultiUserChat muc = getMuc(manager.getConnection(), stanza.getFrom());
            if (muc != null) {
                Occupant occupant = muc.getOccupant(stanza.getFrom().asEntityFullJidIfPossible());
                if (occupant == null) {
                    LOGGER.log(Level.WARNING, "Cannot decrypt OMEMO MUC message; MUC Occupant is null.");
                    return;
                }
                Jid occupantJid = occupant.getJid();
                if (occupantJid == null) {
                    LOGGER.log(Level.WARNING, "Cannot decrypt OMEMO MUC message; Senders Jid is null. " + stanza.getFrom());
                    return;
                }
                sender = occupantJid.asBareJid();
                // try is for this
                decrypted = decryptMessage(managerGuard, sender, element);
                manager.notifyOmemoMucMessageReceived(muc, stanza, decrypted);
            } else {
                sender = stanza.getFrom().asBareJid();
                // and this
                decrypted = decryptMessage(managerGuard, sender, element);
                manager.notifyOmemoMessageReceived(stanza, decrypted);
            }
            if (decrypted.isPreKeyMessage() && OmemoConfiguration.getCompleteSessionWithEmptyMessage()) {
                LOGGER.log(Level.FINE, "Received a preKeyMessage from " + decrypted.getSenderDevice() + ".\n" + "Complete the session by sending an empty response message.");
                try {
                    sendRatchetUpdate(managerGuard, decrypted.getSenderDevice());
                } catch (CannotEstablishOmemoSessionException e) {
                    throw new AssertionError("Since we successfully received a message, we MUST be able to " + "establish a session. " + e);
                } catch (NoSuchAlgorithmException | InterruptedException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
                    LOGGER.log(Level.WARNING, "Cannot send a ratchet update message.", e);
                }
            }
        } catch (NoRawSessionException e) {
            OmemoDevice device = e.getDeviceWithoutSession();
            LOGGER.log(Level.WARNING, "No raw session found for contact " + device + ". ", e);
            if (OmemoConfiguration.getRepairBrokenSessionsWithPreKeyMessages()) {
                repairBrokenSessionWithPreKeyMessage(managerGuard, device);
            }
        } catch (CorruptedOmemoKeyException | CryptoFailedException e) {
            LOGGER.log(Level.WARNING, "Could not decrypt incoming message: ", e);
        }
        // Upload fresh bundle.
        if (getOmemoStoreBackend().loadOmemoPreKeys(userDevice).size() < OmemoConstants.PRE_KEY_COUNT_PER_BUNDLE) {
            LOGGER.log(Level.FINE, "We used up a preKey. Upload a fresh bundle.");
            try {
                getOmemoStoreBackend().replenishKeys(userDevice);
                OmemoBundleElement bundleElement = getOmemoStoreBackend().packOmemoBundle(userDevice);
                publishBundle(manager.getConnection(), userDevice, bundleElement);
            } catch (CorruptedOmemoKeyException | InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | XMPPException.XMPPErrorException | NotALeafNodeException e) {
                LOGGER.log(Level.WARNING, "Could not republish replenished bundle.", e);
            }
        }
    }
}
Also used : CryptoFailedException(org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException) MultiUserChat(org.jivesoftware.smackx.muc.MultiUserChat) OmemoDevice(org.jivesoftware.smackx.omemo.internal.OmemoDevice) EntityBareJid(org.jxmpp.jid.EntityBareJid) Jid(org.jxmpp.jid.Jid) BareJid(org.jxmpp.jid.BareJid) NotALeafNodeException(org.jivesoftware.smackx.pubsub.PubSubException.NotALeafNodeException) EntityBareJid(org.jxmpp.jid.EntityBareJid) BareJid(org.jxmpp.jid.BareJid) Occupant(org.jivesoftware.smackx.muc.Occupant) NoRawSessionException(org.jivesoftware.smackx.omemo.exceptions.NoRawSessionException) MessageOrOmemoMessage(org.jivesoftware.smackx.omemo.util.MessageOrOmemoMessage) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) OmemoBundleElement(org.jivesoftware.smackx.omemo.element.OmemoBundleElement) CannotEstablishOmemoSessionException(org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException) CorruptedOmemoKeyException(org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException) OmemoElement(org.jivesoftware.smackx.omemo.element.OmemoElement)

Example 2 with OmemoElement

use of org.jivesoftware.smackx.omemo.element.OmemoElement in project Smack by igniterealtime.

the class OmemoService method decryptMamQueryResult.

/**
 * Decrypt a possible OMEMO encrypted messages in a {@link MamManager.MamQuery}.
 * The returned list contains wrappers that either hold an {@link OmemoMessage} in case the message was decrypted
 * properly, otherwise it contains the message itself.
 *
 * @param managerGuard authenticated OmemoManager.
 * @param mamQuery Mam archive query
 * @return list of {@link MessageOrOmemoMessage MessageOrOmemoMessages}.
 *
 * @throws IOException if an I/O error occurred.
 */
List<MessageOrOmemoMessage> decryptMamQueryResult(OmemoManager.LoggedInOmemoManager managerGuard, MamManager.MamQuery mamQuery) throws IOException {
    List<MessageOrOmemoMessage> result = new ArrayList<>();
    for (Message message : mamQuery.getMessages()) {
        if (OmemoManager.stanzaContainsOmemoElement(message)) {
            OmemoElement element = (OmemoElement) message.getExtensionElement(OmemoElement.NAME_ENCRYPTED, OmemoConstants.OMEMO_NAMESPACE_V_AXOLOTL);
            // Decrypt OMEMO messages
            try {
                OmemoMessage.Received omemoMessage = decryptMessage(managerGuard, message.getFrom().asBareJid(), element);
                result.add(new MessageOrOmemoMessage(omemoMessage));
            } catch (NoRawSessionException | CorruptedOmemoKeyException | CryptoFailedException e) {
                LOGGER.log(Level.WARNING, "decryptMamQueryResult failed to decrypt message from " + message.getFrom() + " due to corrupted session/key: " + e.getMessage());
                result.add(new MessageOrOmemoMessage(message));
            }
        } else {
            // Wrap cleartext messages
            result.add(new MessageOrOmemoMessage(message));
        }
    }
    return result;
}
Also used : CryptoFailedException(org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException) MessageOrOmemoMessage(org.jivesoftware.smackx.omemo.util.MessageOrOmemoMessage) MessageOrOmemoMessage(org.jivesoftware.smackx.omemo.util.MessageOrOmemoMessage) Message(org.jivesoftware.smack.packet.Message) NoRawSessionException(org.jivesoftware.smackx.omemo.exceptions.NoRawSessionException) ArrayList(java.util.ArrayList) MessageOrOmemoMessage(org.jivesoftware.smackx.omemo.util.MessageOrOmemoMessage) OmemoElement(org.jivesoftware.smackx.omemo.element.OmemoElement) CorruptedOmemoKeyException(org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException)

Example 3 with OmemoElement

use of org.jivesoftware.smackx.omemo.element.OmemoElement in project Smack by igniterealtime.

the class OmemoService method onOmemoCarbonCopyReceived.

@Override
public void onOmemoCarbonCopyReceived(CarbonExtension.Direction direction, Message carbonCopy, Message wrappingMessage, OmemoManager.LoggedInOmemoManager managerGuard) throws IOException {
    OmemoManager manager = managerGuard.get();
    // Avoid the ratchet being manipulated and the bundle being published multiple times simultaneously
    synchronized (manager) {
        OmemoDevice userDevice = manager.getOwnDevice();
        OmemoElement element = (OmemoElement) carbonCopy.getExtensionElement(OmemoElement.NAME_ENCRYPTED, OmemoElement_VAxolotl.NAMESPACE);
        if (element == null) {
            return;
        }
        OmemoMessage.Received decrypted;
        BareJid sender = carbonCopy.getFrom().asBareJid();
        try {
            decrypted = decryptMessage(managerGuard, sender, element);
            manager.notifyOmemoCarbonCopyReceived(direction, carbonCopy, wrappingMessage, decrypted);
            if (decrypted.isPreKeyMessage() && OmemoConfiguration.getCompleteSessionWithEmptyMessage()) {
                LOGGER.log(Level.FINE, "Received a preKeyMessage in a carbon copy from " + decrypted.getSenderDevice() + ".\n" + "Complete the session by sending an empty response message.");
                try {
                    sendRatchetUpdate(managerGuard, decrypted.getSenderDevice());
                } catch (CannotEstablishOmemoSessionException e) {
                    throw new AssertionError("Since we successfully received a message, we MUST be able to " + "establish a session. " + e);
                } catch (NoSuchAlgorithmException | InterruptedException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
                    LOGGER.log(Level.WARNING, "Cannot send a ratchet update message.", e);
                }
            }
        } catch (NoRawSessionException e) {
            OmemoDevice device = e.getDeviceWithoutSession();
            LOGGER.log(Level.WARNING, "No raw session found for contact " + device + ". ", e);
            if (OmemoConfiguration.getRepairBrokenSessionsWithPreKeyMessages()) {
                repairBrokenSessionWithPreKeyMessage(managerGuard, device);
            }
        } catch (CorruptedOmemoKeyException | CryptoFailedException e) {
            LOGGER.log(Level.WARNING, "Could not decrypt incoming carbon copy: ", e);
        }
        // Upload fresh bundle.
        if (getOmemoStoreBackend().loadOmemoPreKeys(userDevice).size() < OmemoConstants.PRE_KEY_COUNT_PER_BUNDLE) {
            LOGGER.log(Level.FINE, "We used up a preKey. Upload a fresh bundle.");
            try {
                getOmemoStoreBackend().replenishKeys(userDevice);
                OmemoBundleElement bundleElement = getOmemoStoreBackend().packOmemoBundle(userDevice);
                publishBundle(manager.getConnection(), userDevice, bundleElement);
            } catch (CorruptedOmemoKeyException | InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | XMPPException.XMPPErrorException | NotALeafNodeException e) {
                LOGGER.log(Level.WARNING, "Could not republish replenished bundle.", e);
            }
        }
    }
}
Also used : CryptoFailedException(org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException) OmemoDevice(org.jivesoftware.smackx.omemo.internal.OmemoDevice) NotALeafNodeException(org.jivesoftware.smackx.pubsub.PubSubException.NotALeafNodeException) EntityBareJid(org.jxmpp.jid.EntityBareJid) BareJid(org.jxmpp.jid.BareJid) NoRawSessionException(org.jivesoftware.smackx.omemo.exceptions.NoRawSessionException) MessageOrOmemoMessage(org.jivesoftware.smackx.omemo.util.MessageOrOmemoMessage) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) OmemoBundleElement(org.jivesoftware.smackx.omemo.element.OmemoBundleElement) CannotEstablishOmemoSessionException(org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException) CorruptedOmemoKeyException(org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException) OmemoElement(org.jivesoftware.smackx.omemo.element.OmemoElement)

Example 4 with OmemoElement

use of org.jivesoftware.smackx.omemo.element.OmemoElement in project Smack by igniterealtime.

the class SignalOmemoManagerTest method stanzaRecognitionTest.

@Test
public void stanzaRecognitionTest() throws Exception {
    String omemoXML = "<encrypted xmlns='eu.siacs.conversations.axolotl'><header sid='1009'><key rid='1337'>MwohBfRqBm2atj3fT0/KUDg59Cnvfpgoe/PLNIu1xgSXujEZEAAYACIwKh6TTC7VBQZcCcKnQlO+6s1GQ9DIRKH4JU7XrJ+JJnkPUwJ4VLSeOEQD7HmFbhQPTLZO0u/qlng=</key><iv>sN0amy4e2NBrlb4G/OjNIQ==</iv></header><payload>4xVUAeg4M0Mhk+5n3YG1x12Dw/cYTc0Z</payload></encrypted>";
    OmemoElement omemoElement = new OmemoVAxolotlProvider().parse(TestUtils.getParser(omemoXML));
    Message m = StanzaBuilder.buildMessage().addExtension(omemoElement).build();
    Message n = StanzaBuilder.buildMessage().build();
    assertTrue(OmemoManager.stanzaContainsOmemoElement(m));
    assertFalse(OmemoManager.stanzaContainsOmemoElement(n));
}
Also used : OmemoVAxolotlProvider(org.jivesoftware.smackx.omemo.provider.OmemoVAxolotlProvider) Message(org.jivesoftware.smack.packet.Message) OmemoElement(org.jivesoftware.smackx.omemo.element.OmemoElement) Test(org.junit.Test)

Example 5 with OmemoElement

use of org.jivesoftware.smackx.omemo.element.OmemoElement in project Smack by igniterealtime.

the class OmemoManager method sendRatchetUpdateMessage.

/**
 * Send a ratchet update message. This can be used to advance the ratchet of a session in order to maintain forward
 * secrecy.
 *
 * @param recipient recipient
 *
 * @throws CorruptedOmemoKeyException           When the used identityKeys are corrupted
 * @throws CryptoFailedException                When something fails with the crypto
 * @throws CannotEstablishOmemoSessionException When we can't establish a session with the recipient
 * @throws SmackException.NotLoggedInException if the XMPP connection is not authenticated.
 * @throws InterruptedException if the calling thread was interrupted.
 * @throws SmackException.NoResponseException if there was no response from the remote entity.
 * @throws NoSuchAlgorithmException if no such algorithm is available.
 * @throws SmackException.NotConnectedException if the XMPP connection is not connected.
 * @throws IOException if an I/O error occurred.
 */
public synchronized void sendRatchetUpdateMessage(OmemoDevice recipient) throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, InterruptedException, SmackException.NoResponseException, NoSuchAlgorithmException, SmackException.NotConnectedException, CryptoFailedException, CannotEstablishOmemoSessionException, IOException {
    XMPPConnection connection = connection();
    MessageBuilder message = connection.getStanzaFactory().buildMessageStanza().to(recipient.getJid());
    OmemoElement element = getOmemoService().createRatchetUpdateElement(new LoggedInOmemoManager(this), recipient);
    message.addExtension(element);
    // Set MAM Storage hint
    StoreHint.set(message);
    connection.sendStanza(message.build());
}
Also used : MessageBuilder(org.jivesoftware.smack.packet.MessageBuilder) XMPPConnection(org.jivesoftware.smack.XMPPConnection) OmemoElement(org.jivesoftware.smackx.omemo.element.OmemoElement)

Aggregations

OmemoElement (org.jivesoftware.smackx.omemo.element.OmemoElement)8 CorruptedOmemoKeyException (org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException)5 CryptoFailedException (org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException)5 MessageOrOmemoMessage (org.jivesoftware.smackx.omemo.util.MessageOrOmemoMessage)5 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)4 CannotEstablishOmemoSessionException (org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException)4 NoRawSessionException (org.jivesoftware.smackx.omemo.exceptions.NoRawSessionException)4 OmemoDevice (org.jivesoftware.smackx.omemo.internal.OmemoDevice)4 Message (org.jivesoftware.smack.packet.Message)3 OmemoBundleElement (org.jivesoftware.smackx.omemo.element.OmemoBundleElement)3 NotALeafNodeException (org.jivesoftware.smackx.pubsub.PubSubException.NotALeafNodeException)3 BareJid (org.jxmpp.jid.BareJid)3 EntityBareJid (org.jxmpp.jid.EntityBareJid)3 XMPPConnection (org.jivesoftware.smack.XMPPConnection)2 MultiUserChat (org.jivesoftware.smackx.muc.MultiUserChat)2 Occupant (org.jivesoftware.smackx.muc.Occupant)2 Jid (org.jxmpp.jid.Jid)2 InvalidAlgorithmParameterException (java.security.InvalidAlgorithmParameterException)1 InvalidKeyException (java.security.InvalidKeyException)1 ArrayList (java.util.ArrayList)1