Exemplo n.º 1
0
        protected override string Execute()
        {
            Log.Debug("DeliveryReceiptJob : Sending delivery receipt...");
            TextSecureAddress textSecureAddress = new TextSecureAddress(destination, new May<string>(relay));

            messageSender.sendDeliveryReceipt(textSecureAddress, (ulong)timestamp);

            return "";
        }
 /**
  * Construct a TextSecureMessageSender.
  *
  * @param url The URL of the TextSecure server.
  * @param trustStore The trust store containing the TextSecure server's signing TLS certificate.
  * @param user The TextSecure username (eg phone number).
  * @param password The TextSecure user's password.
  * @param store The AxolotlStore.
  * @param eventListener An optional event listener, which fires whenever sessions are
  *                      setup or torn down for a recipient.
  */
 public TextSecureMessageSender(String url, TrustStore trustStore,
                                String user, String password,
                                AxolotlStore store,
                                May<EventListener> eventListener, String userAgent)
 {
     this.socket = new PushServiceSocket(url, trustStore, new StaticCredentialsProvider(user, password, null), userAgent);
     this.store = store;
     this.localAddress = new TextSecureAddress(user);
     this.eventListener = eventListener;
 }
        public async Task <PreKeyBundle> getPreKey(TextSecureAddress destination, uint deviceId)// throws IOException
        {
            try
            {
                String path = string.Format(PREKEY_DEVICE_PATH, destination.getNumber(),
                                            deviceId.ToString());

                if (destination.getRelay().HasValue)
                {
                    path = path + "?relay=" + destination.getRelay().ForceGetValue();
                }

                String responseText = await makeRequest(path, "GET", null);

                PreKeyResponse response = JsonUtil.fromJson <PreKeyResponse>(responseText);

                if (response.getDevices() == null || response.getDevices().Count < 1)
                {
                    throw new Exception("Empty prekey list");
                }

                PreKeyResponseItem device                = response.getDevices()[0];
                ECPublicKey        preKey                = null;
                ECPublicKey        signedPreKey          = null;
                byte[]             signedPreKeySignature = null;
                int preKeyId       = -1;
                int signedPreKeyId = -1;

                if (device.getPreKey() != null)
                {
                    preKeyId = (int)device.getPreKey().getKeyId();// TODO: whacky
                    preKey   = device.getPreKey().getPublicKey();
                }

                if (device.getSignedPreKey() != null)
                {
                    signedPreKeyId        = (int)device.getSignedPreKey().getKeyId();// TODO: whacky
                    signedPreKey          = device.getSignedPreKey().getPublicKey();
                    signedPreKeySignature = device.getSignedPreKey().getSignature();
                }

                return(new PreKeyBundle(device.getRegistrationId(), device.getDeviceId(), (uint)preKeyId, preKey,
                                        (uint)signedPreKeyId, signedPreKey, signedPreKeySignature, response.getIdentityKey()));
            }

            /*catch (JsonUtil.JsonParseException e)
             * {
             *  throw new IOException(e);
             * }*/
            catch (NotFoundException nfe)
            {
                throw new UnregisteredUserException(destination.getNumber(), nfe);
            }
        }
        public override bool Equals(Object other)
        {
            if (other == null || !(other is TextSecureAddress))
            {
                return(false);
            }

            TextSecureAddress that = (TextSecureAddress)other;

            return(equals(this.e164number, that.e164number) &&
                   equals(this.relay, that.relay));
        }
        /**
         * Send a message to a single recipient.
         *
         * @param recipient The message's destination.
         * @param message The message.
         * @throws UntrustedIdentityException
         * @throws IOException
         */
        public async void sendMessage(TextSecureAddress recipient, TextSecureDataMessage message)
        {
            byte[] content = await createMessageContent(message);
            ulong timestamp = message.getTimestamp();
            SendMessageResponse response = sendMessage(recipient, timestamp, content, true);

            if (response != null && response.getNeedsSync())
            {
                byte[] syncMessage = createMultiDeviceSentTranscriptContent(content, new May<TextSecureAddress>(recipient), timestamp);
                sendMessage(localAddress, timestamp, syncMessage, false);
            }

            if (message.isEndSession())
            {
                store.DeleteAllSessions(recipient.getNumber());

                if (eventListener.HasValue)
                {
                    eventListener.ForceGetValue().onSecurityEvent(recipient);
                }
            }
        }
 /**
  * Send a delivery receipt for a received message.  It is not necessary to call this
  * when receiving messages through {@link org.whispersystems.textsecure.api.TextSecureMessagePipe}.
  * @param recipient The sender of the received message you're acknowledging.
  * @param messageId The message id of the received message you're acknowledging.
  * @throws IOException
  */
 public void sendDeliveryReceipt(TextSecureAddress recipient, ulong messageId)
 {
     this.socket.sendReceipt(recipient.getNumber(), messageId, recipient.getRelay());
 }
 private void handleStaleDevices(TextSecureAddress recipient, StaleDevices staleDevices)
 {
     foreach (uint staleDeviceId in staleDevices.getStaleDevices())
     {
         store.DeleteSession(new AxolotlAddress(recipient.getNumber(), staleDeviceId));
     }
 }
        private async void handleMismatchedDevices(PushServiceSocket socket, TextSecureAddress recipient,
                                           MismatchedDevices mismatchedDevices)
        {
            try
            {
                foreach (uint extraDeviceId in mismatchedDevices.getExtraDevices())
                {
                    store.DeleteSession(new AxolotlAddress(recipient.getNumber(), extraDeviceId));
                }

                foreach (uint missingDeviceId in mismatchedDevices.getMissingDevices())
                {
                    PreKeyBundle preKey = await socket.getPreKey(recipient, missingDeviceId);

                    try
                    {
                        SessionBuilder sessionBuilder = new SessionBuilder(store, new AxolotlAddress(recipient.getNumber(), missingDeviceId));
                        sessionBuilder.process(preKey);
                    }
                    catch (libaxolotl.exceptions.UntrustedIdentityException e)
                    {
                        throw new UntrustedIdentityException("Untrusted identity key!", recipient.getNumber(), preKey.getIdentityKey());
                    }
                }
            }
            catch (InvalidKeyException e)
            {
                throw new Exception(e.Message);
            }
        }
        private OutgoingPushMessage getEncryptedMessage(PushServiceSocket socket, TextSecureAddress recipient, uint deviceId, byte[] plaintext, bool legacy)
        {
            AxolotlAddress axolotlAddress = new AxolotlAddress(recipient.getNumber(), deviceId);
            TextSecureCipher cipher = new TextSecureCipher(localAddress, store);

            if (!store.ContainsSession(axolotlAddress))
            {
                try
                {
                    List<PreKeyBundle> preKeys = socket.getPreKeys(recipient, deviceId).Result;

                    foreach (PreKeyBundle preKey in preKeys)
                    {
                        try
                        {
                            AxolotlAddress preKeyAddress = new AxolotlAddress(recipient.getNumber(), preKey.getDeviceId());
                            SessionBuilder sessionBuilder = new SessionBuilder(store, preKeyAddress);
                            sessionBuilder.process(preKey);
                        }
                        catch (libaxolotl.exceptions.UntrustedIdentityException e)
                        {
                            throw new UntrustedIdentityException("Untrusted identity key!", recipient.getNumber(), preKey.getIdentityKey());
                        }
                    }

                    if (eventListener.HasValue)
                    {
                        eventListener.ForceGetValue().onSecurityEvent(recipient);
                    }
                }
                catch (InvalidKeyException e)
                {
                    throw new Exception(e.Message);
                }
            }

            return cipher.encrypt(axolotlAddress, plaintext, legacy);
        }
        private OutgoingPushMessageList getEncryptedMessages(PushServiceSocket socket,
                                                   TextSecureAddress recipient,
                                                   ulong timestamp,
                                                   byte[] plaintext,
                                                   bool legacy)
        {
            List<OutgoingPushMessage> messages = new List<OutgoingPushMessage>();

            if (!recipient.Equals(localAddress))
            {
                messages.Add(getEncryptedMessage(socket, recipient, TextSecureAddress.DEFAULT_DEVICE_ID, plaintext, legacy));
            }

            foreach (uint deviceId in store.GetSubDeviceSessions(recipient.getNumber()))
            {
                messages.Add(getEncryptedMessage(socket, recipient, deviceId, plaintext, legacy));
            }

            return new OutgoingPushMessageList(recipient.getNumber(), timestamp, recipient.getRelay().HasValue ? recipient.getRelay().ForceGetValue() : null, messages);
        }
        private SendMessageResponse sendMessage(TextSecureAddress recipient, ulong timestamp, byte[] content, bool legacy)
        {
            for (int i = 0; i < 3; i++)
            {
                try
                {
                    OutgoingPushMessageList messages = getEncryptedMessages(socket, recipient, timestamp, content,
                        legacy);
                    return socket.sendMessage(messages).Result;
                }
                catch (MismatchedDevicesException mde)
                {
                    Debug.WriteLine(mde.Message, TAG);
                    handleMismatchedDevices(socket, recipient, mde.MismatchedDevices);
                }
                catch (StaleDevicesException ste)
                {
                    //Log.w(TAG, ste);
                    handleStaleDevices(recipient, ste.StaleDevices);
                }
                catch (PushNetworkException e)
                {
                    
                }
            }

            throw new Exception("Failed to resolve conflicts after 3 attempts!");
        }
Exemplo n.º 12
0
 public TextSecureCipher(TextSecureAddress localAddress, AxolotlStore axolotlStore)
 {
     this.axolotlStore = axolotlStore;
     this.localAddress = localAddress;
 }
        public async Task <List <PreKeyBundle> > getPreKeys(TextSecureAddress destination, uint deviceIdInteger)// throws IOException
        {
            try
            {
                String deviceId = deviceIdInteger.ToString();

                if (deviceId.Equals("1"))
                {
                    deviceId = "*";
                }

                String path = String.Format(PREKEY_DEVICE_PATH, destination.getNumber(), deviceId);

                if (destination.getRelay().HasValue)
                {
                    path = path + "?relay=" + destination.getRelay().ForceGetValue();
                }

                String responseText = await makeRequest(path, "GET", null);

                PreKeyResponse      response = JsonUtil.fromJson <PreKeyResponse>(responseText);
                List <PreKeyBundle> bundles  = new List <PreKeyBundle>();

                foreach (PreKeyResponseItem device in response.getDevices())
                {
                    ECPublicKey preKey                = null;
                    ECPublicKey signedPreKey          = null;
                    byte[]      signedPreKeySignature = null;
                    int         preKeyId              = -1;
                    int         signedPreKeyId        = -1;

                    if (device.getSignedPreKey() != null)
                    {
                        signedPreKey          = device.getSignedPreKey().getPublicKey();
                        signedPreKeyId        = (int)device.getSignedPreKey().getKeyId(); // TODO: whacky
                        signedPreKeySignature = device.getSignedPreKey().getSignature();
                    }

                    if (device.getPreKey() != null)
                    {
                        preKeyId = (int)device.getPreKey().getKeyId();// TODO: whacky
                        preKey   = device.getPreKey().getPublicKey();
                    }

                    bundles.Add(new PreKeyBundle(device.getRegistrationId(), device.getDeviceId(), (uint)preKeyId,
                                                 preKey, (uint)signedPreKeyId, signedPreKey, signedPreKeySignature,
                                                 response.getIdentityKey()));        // TODO: whacky
                }

                return(bundles);
            }

            /*catch (JsonUtil.JsonParseException e)
             * {
             *  throw new IOException(e);
             * }*/
            catch (NotFoundException nfe)
            {
                throw new UnregisteredUserException(destination.getNumber(), nfe);
            }
        }
Exemplo n.º 14
0
        public async Task<PreKeyBundle> getPreKey(TextSecureAddress destination, uint deviceId)// throws IOException
        {
            try
            {
                String path = string.Format(PREKEY_DEVICE_PATH, destination.getNumber(),
                                            deviceId.ToString());

                if (destination.getRelay().HasValue)
                {
                    path = path + "?relay=" + destination.getRelay().ForceGetValue();
                }

                String responseText = await makeRequest(path, "GET", null);
                PreKeyResponse response = JsonUtil.fromJson<PreKeyResponse>(responseText);

                if (response.getDevices() == null || response.getDevices().Count < 1)
                    throw new Exception("Empty prekey list");

                PreKeyResponseItem device = response.getDevices()[0];
                ECPublicKey preKey = null;
                ECPublicKey signedPreKey = null;
                byte[] signedPreKeySignature = null;
                int preKeyId = -1;
                int signedPreKeyId = -1;

                if (device.getPreKey() != null)
                {
                    preKeyId = (int)device.getPreKey().getKeyId();// TODO: whacky
                    preKey = device.getPreKey().getPublicKey();
                }

                if (device.getSignedPreKey() != null)
                {
                    signedPreKeyId = (int)device.getSignedPreKey().getKeyId();// TODO: whacky
                    signedPreKey = device.getSignedPreKey().getPublicKey();
                    signedPreKeySignature = device.getSignedPreKey().getSignature();
                }

                return new PreKeyBundle(device.getRegistrationId(), device.getDeviceId(), (uint)preKeyId, preKey,
                                        (uint)signedPreKeyId, signedPreKey, signedPreKeySignature, response.getIdentityKey());
            }
            /*catch (JsonUtil.JsonParseException e)
            {
                throw new IOException(e);
            }*/
            catch (NotFoundException nfe)
            {
                throw new UnregisteredUserException(destination.getNumber(), nfe);
            }
        }
Exemplo n.º 15
0
        public async Task<List<PreKeyBundle>> getPreKeys(TextSecureAddress destination, uint deviceIdInteger)// throws IOException
        {
            try
            {
                String deviceId = deviceIdInteger.ToString();

                if (deviceId.Equals("1"))
                    deviceId = "*";

                String path = String.Format(PREKEY_DEVICE_PATH, destination.getNumber(), deviceId);

                if (destination.getRelay().HasValue)
                {
                    path = path + "?relay=" + destination.getRelay().ForceGetValue();
                }

                String responseText = await makeRequest(path, "GET", null);
                PreKeyResponse response = JsonUtil.fromJson<PreKeyResponse>(responseText);
                List<PreKeyBundle> bundles = new List<PreKeyBundle>();

                foreach (PreKeyResponseItem device in response.getDevices())
                {
                    ECPublicKey preKey = null;
                    ECPublicKey signedPreKey = null;
                    byte[] signedPreKeySignature = null;
                    int preKeyId = -1;
                    int signedPreKeyId = -1;

                    if (device.getSignedPreKey() != null)
                    {
                        signedPreKey = device.getSignedPreKey().getPublicKey();
                        signedPreKeyId = (int)device.getSignedPreKey().getKeyId(); // TODO: whacky
                        signedPreKeySignature = device.getSignedPreKey().getSignature();
                    }

                    if (device.getPreKey() != null)
                    {
                        preKeyId = (int)device.getPreKey().getKeyId();// TODO: whacky
                        preKey = device.getPreKey().getPublicKey();
                    }

                    bundles.Add(new PreKeyBundle(device.getRegistrationId(), device.getDeviceId(), (uint)preKeyId,
                                                         preKey, (uint)signedPreKeyId, signedPreKey, signedPreKeySignature,
                                                         response.getIdentityKey()));// TODO: whacky
                }

                return bundles;
            }
            /*catch (JsonUtil.JsonParseException e)
            {
                throw new IOException(e);
            }*/
            catch (NotFoundException nfe)
            {
                throw new UnregisteredUserException(destination.getNumber(), nfe);
            }
        }
Exemplo n.º 16
0
        private void handleMessage(TextSecureEnvelope envelope, May<long> smsMessageId)
        {
            try
            {
                AxolotlStore axolotlStore = new TextSecureAxolotlStore();
                TextSecureAddress localAddress = new TextSecureAddress(TextSecurePreferences.getLocalNumber());
                TextSecureCipher cipher = new TextSecureCipher(localAddress, axolotlStore);

                TextSecureContent content = cipher.decrypt(envelope);

                if (content.getDataMessage().HasValue)
                {
                    TextSecureDataMessage message = content.getDataMessage().ForceGetValue();

                    if (message.isEndSession()) handleEndSessionMessage(envelope, message, smsMessageId);
                    else if (message.isGroupUpdate()) handleGroupMessage(envelope, message, smsMessageId);
                    else if (message.getAttachments().HasValue) handleMediaMessage(envelope, message, smsMessageId);
                    else handleTextMessage(envelope, message, smsMessageId);
                }
                /*else if (content.getSyncMessage().HasValue) TODO: SYNC enable
                {
                    TextSecureSyncMessage syncMessage = content.getSyncMessage().ForceGetValue();

                    if (syncMessage.getSent().HasValue) handleSynchronizeSentMessage(masterSecret, syncMessage.getSent().ForceGetValue(), smsMessageId);
                    else if (syncMessage.getRequest().HasValue) handleSynchronizeRequestMessage(masterSecret, syncMessage.getRequest().ForceGetValue());
                }*/

                if (envelope.isPreKeyWhisperMessage())
                {
                    App.Current.Worker.AddTaskActivities(new RefreshPreKeysTask());
                    //ApplicationContext.getInstance(context).getJobManager().add(new RefreshPreKeysJob(context));
                }
            }
            catch (InvalidVersionException e)
            {
                Log.Warn(e);
                handleInvalidVersionMessage(envelope, smsMessageId);
            }
            catch (InvalidMessageException e)
            {
                Log.Warn(e);
                handleCorruptMessage(envelope, smsMessageId);
            }
            catch (InvalidKeyIdException e)
            {
                Log.Warn(e);
                handleCorruptMessage(envelope, smsMessageId);
            }
            catch (InvalidKeyException e)
            {
                Log.Warn(e);
                handleCorruptMessage(envelope, smsMessageId);
            }
            catch (NoSessionException e)
            {
                Log.Warn(e);
                handleNoSessionMessage(envelope, smsMessageId);
            }
            catch (LegacyMessageException e)
            {
                Log.Warn(e);
                handleLegacyMessage(envelope, smsMessageId);
            }
            catch (DuplicateMessageException e)
            {
                Log.Warn(e);
                handleDuplicateMessage(envelope, smsMessageId);
            }
            catch (libaxolotl.exceptions.UntrustedIdentityException e)
            {
                Log.Warn(e);
                handleUntrustedIdentityMessage(envelope, smsMessageId);
            }
            catch (Exception e)
            {
                Log.Warn($"Unexpected Exception");
            }
        }