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!"); }
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); } }
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 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); } }
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"); } }