OmemoMessage.java

  1. /**
  2.  *
  3.  * Copyright 2017 Paul Schaub
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.jivesoftware.smackx.omemo;

  18. import static org.jivesoftware.smackx.omemo.util.OmemoConstants.BODY_OMEMO_HINT;
  19. import static org.jivesoftware.smackx.omemo.util.OmemoConstants.OMEMO;
  20. import static org.jivesoftware.smackx.omemo.util.OmemoConstants.OMEMO_NAMESPACE_V_AXOLOTL;

  21. import java.util.HashMap;
  22. import java.util.HashSet;
  23. import java.util.Set;

  24. import org.jivesoftware.smack.packet.Message;
  25. import org.jivesoftware.smack.packet.MessageBuilder;

  26. import org.jivesoftware.smackx.eme.element.ExplicitMessageEncryptionElement;
  27. import org.jivesoftware.smackx.hints.element.StoreHint;
  28. import org.jivesoftware.smackx.omemo.element.OmemoElement;
  29. import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
  30. import org.jivesoftware.smackx.omemo.trust.OmemoFingerprint;

  31. import org.jxmpp.jid.Jid;

  32. public class OmemoMessage {

  33.     private final OmemoElement element;
  34.     private final byte[] messageKey, iv;

  35.     OmemoMessage(OmemoElement element, byte[] key, byte[] iv) {
  36.         this.element = element;
  37.         this.messageKey = key;
  38.         this.iv = iv;
  39.     }

  40.     /**
  41.      * Return the original OmemoElement (<encrypted/>).
  42.      *
  43.      * @return omemoElement of the message
  44.      */
  45.     public OmemoElement getElement() {
  46.         return element;
  47.     }

  48.     /**
  49.      * Return the messageKey (or transported key in case of a KeyTransportMessage).
  50.      *
  51.      * @return encryption key that protects the message payload
  52.      */
  53.     public byte[] getKey() {
  54.         return messageKey.clone();
  55.     }

  56.     /**
  57.      * Return the initialization vector belonging to the key.
  58.      *
  59.      * @return initialization vector
  60.      */
  61.     public byte[] getIv() {
  62.         return iv.clone();
  63.     }

  64.     /**
  65.      * Outgoing OMEMO message.
  66.      */
  67.     public static class Sent extends OmemoMessage {
  68.         private final Set<OmemoDevice> intendedDevices = new HashSet<>();
  69.         private final HashMap<OmemoDevice, Throwable> skippedDevices = new HashMap<>();

  70.         /**
  71.          * Create a new outgoing OMEMO message.
  72.          *
  73.          * @param element OmemoElement
  74.          * @param key messageKey (or transported key)
  75.          * @param iv initialization vector belonging to key
  76.          * @param intendedDevices devices the client intended to encrypt the message for
  77.          * @param skippedDevices devices which were skipped during encryption process because encryption
  78.          *                       failed for some reason
  79.          */
  80.         Sent(OmemoElement element, byte[] key, byte[] iv, Set<OmemoDevice> intendedDevices, HashMap<OmemoDevice, Throwable> skippedDevices) {
  81.             super(element, key, iv);
  82.             this.intendedDevices.addAll(intendedDevices);
  83.             this.skippedDevices.putAll(skippedDevices);
  84.         }

  85.         /**
  86.          * Return a list of all devices the sender originally intended to encrypt the message for.
  87.          *
  88.          * @return list of intended recipients.
  89.          */
  90.         public Set<OmemoDevice> getIntendedDevices() {
  91.             return intendedDevices;
  92.         }

  93.         /**
  94.          * Return a map of all skipped recipients and the reasons for skipping.
  95.          *
  96.          * @return map of skipped recipients and reasons for that.
  97.          */
  98.         public HashMap<OmemoDevice, Throwable> getSkippedDevices() {
  99.             return skippedDevices;
  100.         }

  101.         /**
  102.          * Determine, if some recipients were skipped during encryption.
  103.          *
  104.          * @return true if recipients were skipped.
  105.          */
  106.         public boolean isMissingRecipients() {
  107.             return !getSkippedDevices().isEmpty();
  108.         }

  109.         /**
  110.          * Return the OmemoElement wrapped in a Message ready to be sent.
  111.          * The message is addressed to recipient, contains the OmemoElement
  112.          * as well as an optional clear text hint as body, a MAM storage hint
  113.          * and an EME hint about OMEMO encryption.
  114.          *
  115.          * @param messageBuilder a message builder which will be used to build the message.
  116.          * @param recipient recipient for the to-field of the message.
  117.          * @return the build message.
  118.          */
  119.         public Message buildMessage(MessageBuilder messageBuilder, Jid recipient) {
  120.             messageBuilder.ofType(Message.Type.chat).to(recipient);

  121.             messageBuilder.addExtension(getElement());

  122.             if (OmemoConfiguration.getAddOmemoHintBody()) {
  123.                 messageBuilder.setBody(BODY_OMEMO_HINT);
  124.             }

  125.             StoreHint.set(messageBuilder);
  126.             messageBuilder.addExtension(new ExplicitMessageEncryptionElement(OMEMO_NAMESPACE_V_AXOLOTL, OMEMO));

  127.             return messageBuilder.build();
  128.         }
  129.     }

  130.     /**
  131.      * Incoming OMEMO message.
  132.      */
  133.     public static class Received extends OmemoMessage {
  134.         private final String message;
  135.         private final OmemoFingerprint sendersFingerprint;
  136.         private final OmemoDevice senderDevice;
  137.         private final boolean preKeyMessage;

  138.         /**
  139.          * Create a new incoming OMEMO message.
  140.          *
  141.          * @param element original OmemoElement
  142.          * @param key message key (or transported key)
  143.          * @param iv respective initialization vector
  144.          * @param body decrypted body
  145.          * @param sendersFingerprint OmemoFingerprint of the senders identityKey
  146.          * @param senderDevice OmemoDevice of the sender
  147.          * @param preKeyMessage if this was a preKeyMessage or not
  148.          */
  149.         Received(OmemoElement element, byte[] key, byte[] iv, String body, OmemoFingerprint sendersFingerprint, OmemoDevice senderDevice, boolean preKeyMessage) {
  150.             super(element, key, iv);
  151.             this.message = body;
  152.             this.sendersFingerprint = sendersFingerprint;
  153.             this.senderDevice = senderDevice;
  154.             this.preKeyMessage = preKeyMessage;
  155.         }

  156.         /**
  157.          * Return the decrypted body of the message.
  158.          *
  159.          * @return decrypted body
  160.          */
  161.         public String getBody() {
  162.             return message;
  163.         }

  164.         /**
  165.          * Return the fingerprint of the messages sender device.
  166.          *
  167.          * @return fingerprint of sender
  168.          */
  169.         public OmemoFingerprint getSendersFingerprint() {
  170.             return sendersFingerprint;
  171.         }

  172.         /**
  173.          * Return the OmemoDevice which sent the message.
  174.          *
  175.          * @return OMEMO device that sent the message.
  176.          */
  177.         public OmemoDevice getSenderDevice() {
  178.             return senderDevice;
  179.         }

  180.         /**
  181.          * Return true, if this message was sent as a preKeyMessage.
  182.          *
  183.          * @return preKeyMessage or not
  184.          */
  185.         boolean isPreKeyMessage() {
  186.             return preKeyMessage;
  187.         }

  188.         /**
  189.          * Return true, if the message was a KeyTransportMessage.
  190.          * A KeyTransportMessage is a OmemoMessage without a payload.
  191.          *
  192.          * @return keyTransportMessage?
  193.          */
  194.         public boolean isKeyTransportMessage() {
  195.             return message == null;
  196.         }
  197.     }
  198. }