Example #1
0
        public static SignalMessage IncreaseReceiptCountLocked(SignalServiceEnvelope envelope)
        {
            SignalMessage m;
            bool          set_mark = false;

            lock (DBLock)
            {
                using (var ctx = new SignalDBContext())
                {
                    m = ctx.Messages.SingleOrDefault(t => t.ComposedTimestamp == envelope.GetTimestamp());
                    if (m != null)
                    {
                        m.Receipts++;
                        if (m.Status == SignalMessageStatus.Confirmed)
                        {
                            m.Status = SignalMessageStatus.Received;
                            set_mark = true;
                        }
                    }
                    else
                    {
                        ctx.EarlyReceipts.Add(new SignalEarlyReceipt()
                        {
                            DeviceId  = (uint)envelope.GetSourceDevice(),
                            Timestamp = envelope.GetTimestamp(),
                            Username  = envelope.GetSourceE164()
                        });
                    }
                    ctx.SaveChanges();
                }
            }
            return(set_mark ? m : null);
        }
        private async Task HandleSessionResetMessage(SignalServiceEnvelope envelope, SignalServiceContent content, SignalServiceDataMessage dataMessage, bool isSync, long timestamp)
        {
            SignalMessageDirection type;
            SignalContact          author;
            SignalMessageStatus    status;
            SignalConversation     conversation;
            string prefix;
            string conversationId;
            Guid?  conversationGuid;
            long   composedTimestamp;

            if (isSync)
            {
                var sent = content.SynchronizeMessage.Sent;
                type              = SignalMessageDirection.Synced;
                status            = SignalMessageStatus.Confirmed;
                composedTimestamp = sent.Timestamp;
                author            = null;
                prefix            = "You have";
                conversationId    = sent.Destination.E164;
                conversationGuid  = sent.Destination.Uuid;
            }
            else
            {
                status = 0;
                type   = SignalMessageDirection.Incoming;
                author = await SignalDBContext.GetOrCreateContactLocked(content.Sender.E164, content.Sender.Uuid);

                prefix            = $"{author.ThreadDisplayName} has";
                composedTimestamp = envelope.GetTimestamp();
                conversationId    = content.Sender.E164;
                conversationGuid  = content.Sender.Uuid;
            }
            LibsignalDBContext.DeleteAllSessions(conversationId);
            conversation = await SignalDBContext.GetOrCreateContactLocked(conversationId, conversationGuid);

            SignalMessage sm = new SignalMessage()
            {
                Direction = type,
                Type      = SignalMessageType.SessionReset,
                Status    = status,
                Author    = author,
                Content   = new SignalMessageContent()
                {
                    Content = $"{prefix} reset the session."
                },
                ThreadId          = conversationId,
                ThreadGuid        = conversationGuid,
                DeviceId          = (uint)envelope.GetSourceDevice(),
                Receipts          = 0,
                ComposedTimestamp = composedTimestamp,
                ReceivedTimestamp = timestamp,
            };
            await SignalLibHandle.Instance.SaveAndDispatchSignalMessage(sm, null, conversation);
        }
Example #3
0
        private async Task HandleSignalMessage(SignalServiceEnvelope envelope, SignalServiceContent content, SignalServiceDataMessage dataMessage, bool isSync, long timestamp)
        {
            SignalMessageDirection type;
            SignalContact          author;
            SignalMessageStatus    status;
            SignalConversation     conversation;
            long   composedTimestamp;
            string body = dataMessage.Body ?? "";

            if (dataMessage.Group != null)
            {
                var rawId    = dataMessage.Group.GroupId;
                var threadId = Base64.EncodeBytes(rawId);
                conversation = await SignalDBContext.GetOrCreateGroupLocked(threadId, timestamp);

                if (!conversation.CanReceive)
                {
                    SignalServiceGroup group = new SignalServiceGroup()
                    {
                        Type    = SignalServiceGroup.GroupType.REQUEST_INFO,
                        GroupId = rawId
                    };
                    SignalServiceDataMessage requestInfoMessage = new SignalServiceDataMessage()
                    {
                        Group     = group,
                        Timestamp = Util.CurrentTimeMillis()
                    };
                    SignalLibHandle.Instance.OutgoingQueue.Add(new SignalServiceDataMessageSendable(requestInfoMessage, envelope.GetSourceAddress()));
                }
                composedTimestamp = envelope.GetTimestamp();
            }
            else
            {
                if (isSync)
                {
                    var sent = content.SynchronizeMessage.Sent;
                    conversation = await SignalDBContext.GetOrCreateContactLocked(sent.Destination.ForceGetValue(), timestamp);

                    composedTimestamp = sent.Timestamp;
                }
                else
                {
                    conversation = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), timestamp);

                    composedTimestamp = envelope.GetTimestamp();
                }
            }

            if (isSync)
            {
                type   = SignalMessageDirection.Synced;
                status = SignalMessageStatus.Confirmed;
                author = null;
            }
            else
            {
                status = 0;
                type   = SignalMessageDirection.Incoming;
                author = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), timestamp);
            }

            if (author != null && author.Blocked)
            {
                // Don't save blocked messages
                return;
            }

            List <SignalAttachment> attachments = new List <SignalAttachment>();
            SignalMessage           message     = new SignalMessage()
            {
                Direction = type,
                Status    = status,
                Author    = author,
                Content   = new SignalMessageContent()
                {
                    Content = body.Truncate(2000)
                },
                ThreadId          = conversation.ThreadId,
                DeviceId          = (uint)envelope.GetSourceDevice(),
                Receipts          = 0,
                ComposedTimestamp = composedTimestamp,
                ReceivedTimestamp = timestamp,
                AttachmentsCount  = (uint)attachments.Count,
                Attachments       = attachments
            };

            if (dataMessage.Attachments != null)
            {
                var receivedAttachments = dataMessage.Attachments;
                foreach (var receivedAttachment in receivedAttachments)
                {
                    var pointer         = receivedAttachment.AsPointer();
                    SignalAttachment sa = new SignalAttachment()
                    {
                        Message      = message,
                        Status       = (uint)SignalAttachmentStatus.Default,
                        SentFileName = pointer.FileName,
                        ContentType  = receivedAttachment.ContentType,
                        Key          = pointer.Key,
                        Relay        = pointer.Relay,
                        StorageId    = pointer.Id,
                        Size         = (long)pointer.Size,
                        Digest       = pointer.Digest
                    };
                    attachments.Add(sa);
                }

                // Make sure to update attachments count
                message.AttachmentsCount = (uint)attachments.Count;
            }
            await SignalLibHandle.Instance.SaveAndDispatchSignalMessage(message, null, conversation);
        }
Example #4
0
        private async Task HandleGroupUpdateMessage(SignalServiceEnvelope envelope, SignalServiceContent content, SignalServiceDataMessage dataMessage, bool isSync, long timestamp)
        {
            if (dataMessage.Group != null) //TODO check signal droid: group messages have different types!
            {
                SignalServiceGroup group       = dataMessage.Group;
                string             groupid     = Base64.EncodeBytes(group.GroupId);
                SignalGroup        g           = new SignalGroup();
                string             displayname = "Unknown group";
                string             avatarfile  = null;
                if (group.Name != null)
                {
                    displayname = group.Name;
                }
                var dbgroup = SignalDBContext.InsertOrUpdateGroupLocked(groupid, displayname, avatarfile, true, timestamp);
                if (group.Members != null)
                {
                    foreach (var member in group.Members)
                    {
                        SignalDBContext.InsertOrUpdateGroupMembershipLocked(dbgroup.Id, (await SignalDBContext.GetOrCreateContactLocked(member, 0)).Id);
                    }
                }

                /* insert message into conversation */
                SignalMessageDirection type;
                SignalContact          author;
                SignalMessageStatus    status;
                string prefix;
                long   composedTimestamp;

                if (isSync)
                {
                    var sent = content.SynchronizeMessage.Sent;
                    type              = SignalMessageDirection.Synced;
                    status            = SignalMessageStatus.Confirmed;
                    composedTimestamp = sent.Timestamp;
                    author            = null;
                    prefix            = "You have";
                }
                else
                {
                    status = 0;
                    type   = SignalMessageDirection.Incoming;
                    author = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), timestamp);

                    prefix            = $"{author.ThreadDisplayName} has";
                    composedTimestamp = envelope.GetTimestamp();
                }

                SignalMessage sm = new SignalMessage()
                {
                    Direction = type,
                    Type      = SignalMessageType.GroupUpdate,
                    Status    = status,
                    Author    = author,
                    Content   = new SignalMessageContent()
                    {
                        Content = $"{prefix} updated the group."
                    },
                    ThreadId          = groupid,
                    DeviceId          = (uint)envelope.GetSourceDevice(),
                    Receipts          = 0,
                    ComposedTimestamp = composedTimestamp,
                    ReceivedTimestamp = timestamp,
                };
                SignalDBContext.SaveMessageLocked(sm);
                dbgroup.MessagesCount += 1;
                if (sm.Direction == SignalMessageDirection.Incoming)
                {
                    dbgroup.UnreadCount += 1;
                }
                else
                {
                    dbgroup.UnreadCount          = 0;
                    dbgroup.LastSeenMessageIndex = dbgroup.MessagesCount;
                }
                dbgroup.LastMessage = sm;
                await SignalLibHandle.Instance.DispatchAddOrUpdateConversation(dbgroup, sm);
            }
            else
            {
                Logger.LogError("HandleGroupUpdateMessage() received group update without group info");
            }
        }
Example #5
0
        private async Task HandleGroupLeaveMessage(SignalServiceEnvelope envelope, SignalServiceContent content, SignalServiceDataMessage dataMessage, bool isSync, long timestamp)
        {
            SignalServiceGroup sentGroup = dataMessage.Group;

            if (sentGroup != null)
            {
                string      groupid = Base64.EncodeBytes(sentGroup.GroupId);
                SignalGroup group   = await SignalDBContext.GetOrCreateGroupLocked(groupid, 0);

                if (isSync)
                {
                    SignalContact author = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), 0);

                    SignalMessage sm = new SignalMessage()
                    {
                        Direction = SignalMessageDirection.Incoming,
                        Type      = SignalMessageType.GroupLeave,
                        Status    = SignalMessageStatus.Received,
                        Author    = author,
                        Content   = new SignalMessageContent()
                        {
                            Content = $"You have left the group."
                        },
                        ThreadId          = groupid,
                        DeviceId          = (uint)envelope.GetSourceDevice(),
                        Receipts          = 0,
                        ComposedTimestamp = envelope.GetTimestamp(),
                        ReceivedTimestamp = timestamp,
                    };
                    SignalConversation updatedConversation = SignalDBContext.RemoveMemberFromGroup(groupid, author, sm);
                    await SignalLibHandle.Instance.DispatchAddOrUpdateConversation(updatedConversation, sm);
                }
                else
                {
                    SignalContact author = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), 0);

                    SignalMessage sm = new SignalMessage()
                    {
                        Direction = SignalMessageDirection.Incoming,
                        Type      = SignalMessageType.GroupLeave,
                        Status    = SignalMessageStatus.Received,
                        Author    = author,
                        Content   = new SignalMessageContent()
                        {
                            Content = $"{author.ThreadDisplayName} has left the group."
                        },
                        ThreadId          = groupid,
                        DeviceId          = (uint)envelope.GetSourceDevice(),
                        Receipts          = 0,
                        ComposedTimestamp = envelope.GetTimestamp(),
                        ReceivedTimestamp = timestamp,
                    };
                    SignalConversation updatedConversation = SignalDBContext.RemoveMemberFromGroup(groupid, author, sm);
                    await SignalLibHandle.Instance.DispatchAddOrUpdateConversation(updatedConversation, sm);
                }
            }
            else
            {
                Logger.LogError("HandleGroupLeaveMessage() received group update without group info");
            }
        }
Example #6
0
        private async Task HandleExpirationUpdateMessage(SignalServiceEnvelope envelope, SignalServiceContent content, SignalServiceDataMessage message, bool isSync, long timestamp)
        {
            SignalMessageDirection type;
            SignalContact          author;
            SignalMessageStatus    status;
            string             prefix;
            SignalConversation conversation;
            long composedTimestamp;

            if (isSync)
            {
                var sent = content.SynchronizeMessage.Sent;
                type              = SignalMessageDirection.Synced;
                status            = SignalMessageStatus.Confirmed;
                composedTimestamp = sent.Timestamp;
                author            = null;
                prefix            = "You have";
                if (message.Group != null)
                {
                    conversation = await SignalDBContext.GetOrCreateGroupLocked(Base64.EncodeBytes(message.Group.GroupId), 0);
                }
                else
                {
                    conversation = await SignalDBContext.GetOrCreateContactLocked(sent.Destination.ForceGetValue(), 0);
                }
            }
            else
            {
                status = 0;
                type   = SignalMessageDirection.Incoming;
                author = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), timestamp);

                prefix            = $"{author.ThreadDisplayName} has";
                composedTimestamp = envelope.GetTimestamp();
                if (message.Group != null)
                {
                    conversation = await SignalDBContext.GetOrCreateGroupLocked(Base64.EncodeBytes(message.Group.GroupId), 0);
                }
                else
                {
                    conversation = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), 0);
                }
            }
            conversation.ExpiresInSeconds = (uint)message.ExpiresInSeconds;
            SignalDBContext.UpdateExpiresInLocked(conversation);
            SignalMessage sm = new SignalMessage()
            {
                Direction = type,
                Type      = SignalMessageType.ExpireUpdate,
                Status    = status,
                Author    = author,
                Content   = new SignalMessageContent()
                {
                    Content = $"{prefix} set the expiration timer to {message.ExpiresInSeconds} seconds."
                },
                ThreadId          = conversation.ThreadId,
                DeviceId          = (uint)envelope.GetSourceDevice(),
                Receipts          = 0,
                ComposedTimestamp = composedTimestamp,
                ReceivedTimestamp = timestamp,
            };
            await SignalLibHandle.Instance.SaveAndDispatchSignalMessage(sm, null, conversation);
        }
Example #7
0
        private async Task HandleMessage(SignalServiceEnvelope envelope)
        {
            var  cipher    = new SignalServiceCipher(new SignalServiceAddress(SignalLibHandle.Instance.Store.Username), new Store());
            var  content   = cipher.Decrypt(envelope);
            long timestamp = Util.CurrentTimeMillis();

            if (content.Message != null)
            {
                SignalServiceDataMessage message = content.Message;
                if (message.EndSession)
                {
                    await HandleSessionResetMessage(envelope, content, message, false, timestamp);
                }
                else if (message.IsGroupUpdate())
                {
                    if (message.Group.Type == SignalServiceGroup.GroupType.UPDATE)
                    {
                        await HandleGroupUpdateMessage(envelope, content, message, false, timestamp);
                    }
                    else if (message.Group.Type == SignalServiceGroup.GroupType.QUIT)
                    {
                        await HandleGroupLeaveMessage(envelope, content, message, false, timestamp);
                    }
                    else if (message.Group.Type == SignalServiceGroup.GroupType.REQUEST_INFO)
                    {
                        Logger.LogWarning("Received REQUEST_INFO request");
                    }
                }
                else if (message.ExpirationUpdate)
                {
                    await HandleExpirationUpdateMessage(envelope, content, message, false, timestamp);
                }
                else
                {
                    await HandleSignalMessage(envelope, content, message, false, timestamp);
                }
            }
            else if (content.SynchronizeMessage != null)
            {
                if (content.SynchronizeMessage.Sent != null)
                {
                    var syncMessage = content.SynchronizeMessage.Sent;
                    var dataMessage = syncMessage.Message;

                    if (dataMessage.EndSession)
                    {
                        await HandleSessionResetMessage(envelope, content, dataMessage, true, timestamp);
                    }
                    else if (dataMessage.IsGroupUpdate())
                    {
                        if (dataMessage.Group.Type == SignalServiceGroup.GroupType.UPDATE)
                        {
                            await HandleGroupUpdateMessage(envelope, content, dataMessage, true, timestamp);
                        }
                        else if (dataMessage.Group.Type == SignalServiceGroup.GroupType.QUIT)
                        {
                            await HandleGroupLeaveMessage(envelope, content, dataMessage, true, timestamp);
                        }
                        else if (dataMessage.Group.Type == SignalServiceGroup.GroupType.REQUEST_INFO)
                        {
                            Logger.LogWarning("Received synced REQUEST_INFO request");
                        }
                    }
                    else if (dataMessage.ExpirationUpdate)
                    {
                        await HandleExpirationUpdateMessage(envelope, content, dataMessage, true, timestamp);
                    }
                    else
                    {
                        await HandleSignalMessage(envelope, content, dataMessage, true, timestamp);
                    }
                }
                else if (content.SynchronizeMessage.Reads != null)
                {
                    var readMessages = content.SynchronizeMessage.Reads;
                    foreach (var readMessage in readMessages)
                    {
                        try
                        {
                            await HandleSyncedReadMessage(readMessage);
                        }
                        catch (Exception e)
                        {
                            Logger.LogError("HandleReadMessage failed: {0}\n{1}", e.Message, e.StackTrace);
                        }
                    }
                }
                else if (content.SynchronizeMessage.BlockedList != null)
                {
                    List <string> blockedNumbers = content.SynchronizeMessage.BlockedList.Numbers;
                    await HandleBlockedNumbers(blockedNumbers);
                }
                else if (content.SynchronizeMessage.Groups != null)
                {
                    Logger.LogInformation("HandleMessage() handling groups sync message from device {0}", envelope.GetSourceDevice());
                    int read;
                    var avatarBuffer = new byte[4096];
                    var groups       = content.SynchronizeMessage.Groups;
                    using (var tmpFile = LibUtils.CreateTmpFile("groups_sync"))
                    {
                        var plaintextStream = await MessageReceiver.RetrieveAttachment(Token, groups.AsPointer(), tmpFile, 10000, null);

                        var         deviceGroupsStream = new DeviceGroupsInputStream(plaintextStream);
                        var         groupsList         = new List <(SignalGroup, IList <string>)>();
                        DeviceGroup g;
                        while ((g = deviceGroupsStream.Read()) != null)
                        {
                            if (g.Avatar != null)
                            {
                                SignalServiceAttachmentStream ssas = g.Avatar.AsStream();
                                while ((read = ssas.InputStream.Read(avatarBuffer, 0, avatarBuffer.Length)) > 0)
                                {
                                }
                            }
                            var group = new SignalGroup()
                            {
                                ThreadDisplayName = g.Name,
                                ThreadId          = Base64.EncodeBytes(g.Id),
                                GroupMemberships  = new List <GroupMembership>(),
                                CanReceive        = true,
                                ExpiresInSeconds  = g.ExpirationTimer != null ? g.ExpirationTimer.Value : 0
                            };
                            groupsList.Add((group, g.Members));
                        }
                        List <SignalConversation> dbGroups = await SignalDBContext.InsertOrUpdateGroups(groupsList);

                        await SignalLibHandle.Instance.DispatchAddOrUpdateConversations(dbGroups);
                    }
                }
                else if (content.SynchronizeMessage.Contacts != null && content.SynchronizeMessage.Contacts.Complete) //TODO incomplete updates
                {
                    Logger.LogInformation("HandleMessage() handling contacts sync message from device {0}", envelope.GetSourceDevice());
                    int             read;
                    var             avatarBuffer = new byte[4096];
                    ContactsMessage contacts     = content.SynchronizeMessage.Contacts;
                    using (var tmpFile = LibUtils.CreateTmpFile("contacts_sync"))
                    {
                        var plaintextStream = await MessageReceiver.RetrieveAttachment(Token, contacts.Contacts.AsPointer(), tmpFile, 10000, null);

                        var deviceContactsStream          = new DeviceContactsInputStream(plaintextStream);
                        List <SignalContact> contactsList = new List <SignalContact>();
                        DeviceContact        c;
                        while ((c = deviceContactsStream.Read()) != null)
                        {
                            if (c.Avatar != null)
                            {
                                SignalServiceAttachmentStream ssas = c.Avatar.AsStream();
                                while ((read = ssas.InputStream.Read(avatarBuffer, 0, avatarBuffer.Length)) > 0)
                                {
                                }
                            }
                            SignalContact contact = new SignalContact()
                            {
                                ThreadDisplayName = c.Name,
                                ThreadId          = c.Number,
                                Color             = c.Color,
                                CanReceive        = true,
                                ExpiresInSeconds  = c.ExpirationTimer != null ? c.ExpirationTimer.Value : 0
                            };
                            contactsList.Add(contact);
                        }
                        var dbContacts = SignalDBContext.InsertOrUpdateContacts(contactsList);
                        await SignalLibHandle.Instance.DispatchAddOrUpdateConversations(dbContacts);
                    }
                }
            }
            else if (content.ReadMessage != null)
            {
                SignalServiceReceiptMessage receiptMessage = content.ReadMessage;
                Logger.LogTrace("HandleMessage() received ReceiptMessage (type={0}, when={1})", receiptMessage.ReceiptType, receiptMessage.When);
            }
            else
            {
                //TODO callmessages
                Logger.LogWarning("HandleMessage() received unrecognized message");
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="envelope"></param>
        /// <param name="ciphertext"></param>
        /// <returns></returns>
        /// <exception cref="InvalidMetadataMessageException"></exception>
        /// <exception cref="InvalidMetadataVersionException"></exception>
        /// <exception cref="ProtocolDuplicateMessageException"></exception>
        /// <exception cref="ProtocolUntrustedIdentityException"></exception>
        /// <exception cref="ProtocolLegacyMessageException"></exception>
        /// <exception cref="ProtocolInvalidKeyException"></exception>
        /// <exception cref="ProtocolInvalidVersionException"></exception>
        /// <exception cref="ProtocolInvalidMessageException"></exception>
        /// <exception cref="ProtocolInvalidKeyIdException"></exception>
        /// <exception cref="ProtocolNoSessionException"></exception>
        /// <exception cref="SelfSendException"></exception>
        private Plaintext Decrypt(SignalServiceEnvelope envelope, byte[] ciphertext)
        {
            try
            {
                byte[] paddedMessage;
                SignalServiceMetadata metadata;
                uint sessionVersion;

                if (!envelope.HasSource() && !envelope.IsUnidentifiedSender())
                {
                    throw new ProtocolInvalidMessageException(new InvalidMessageException("Non-UD envelope is missing a source!"), null, 0);
                }

                if (envelope.IsPreKeySignalMessage())
                {
                    SignalProtocolAddress sourceAddress = GetPreferredProtocolAddress(signalProtocolStore, envelope.GetSourceAddress(), envelope.GetSourceDevice());
                    SessionCipher         sessionCipher = new SessionCipher(signalProtocolStore, sourceAddress);

                    paddedMessage  = sessionCipher.decrypt(new PreKeySignalMessage(ciphertext));
                    metadata       = new SignalServiceMetadata(envelope.GetSourceAddress(), envelope.GetSourceDevice(), envelope.GetTimestamp(), false);
                    sessionVersion = sessionCipher.getSessionVersion();
                }
                else if (envelope.IsSignalMessage())
                {
                    SignalProtocolAddress sourceAddress = GetPreferredProtocolAddress(signalProtocolStore, envelope.GetSourceAddress(), envelope.GetSourceDevice());
                    SessionCipher         sessionCipher = new SessionCipher(signalProtocolStore, sourceAddress);

                    paddedMessage  = sessionCipher.decrypt(new SignalMessage(ciphertext));
                    metadata       = new SignalServiceMetadata(envelope.GetSourceAddress(), envelope.GetSourceDevice(), envelope.GetTimestamp(), false);
                    sessionVersion = sessionCipher.getSessionVersion();
                }
                else if (envelope.IsUnidentifiedSender())
                {
                    SealedSessionCipher   sealedSessionCipher = new SealedSessionCipher(signalProtocolStore, localAddress.Uuid, localAddress.GetNumber(), 1);
                    DecryptionResult      result          = sealedSessionCipher.Decrypt(certificateValidator !, ciphertext, (long)envelope.Envelope.ServerTimestamp);
                    SignalServiceAddress  resultAddress   = new SignalServiceAddress(UuidUtil.Parse(result.SenderUuid), result.SenderE164);
                    SignalProtocolAddress protocolAddress = GetPreferredProtocolAddress(signalProtocolStore, resultAddress, result.DeviceId);

                    paddedMessage  = result.PaddedMessage;
                    metadata       = new SignalServiceMetadata(resultAddress, result.DeviceId, envelope.GetTimestamp(), true);
                    sessionVersion = (uint)sealedSessionCipher.GetSessionVersion(protocolAddress);
                }
                else
                {
                    throw new InvalidMessageException($"Unknown type: {envelope.GetType()}");
                }

                PushTransportDetails transportDetails = new PushTransportDetails(sessionVersion);
                byte[] data = transportDetails.GetStrippedPaddingMessageBody(paddedMessage);

                return(new Plaintext(metadata, data));
            }
            catch (DuplicateMessageException e)
            {
                throw new ProtocolDuplicateMessageException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice());
            }
            catch (LegacyMessageException e)
            {
                throw new ProtocolLegacyMessageException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice());
            }
            catch (InvalidMessageException e)
            {
                throw new ProtocolInvalidMessageException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice());
            }
            catch (InvalidKeyIdException e)
            {
                throw new ProtocolInvalidKeyIdException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice());
            }
            catch (InvalidKeyException e)
            {
                throw new ProtocolInvalidKeyException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice());
            }
            catch (libsignal.exceptions.UntrustedIdentityException e)
            {
                throw new ProtocolUntrustedIdentityException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice());
            }
            catch (InvalidVersionException e)
            {
                throw new ProtocolInvalidVersionException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice());
            }
            catch (NoSessionException e)
            {
                throw new ProtocolNoSessionException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice());
            }
        }
Example #9
0
        private Plaintext Decrypt(SignalServiceEnvelope envelope, byte[] ciphertext)
        {
            try
            {
                SignalProtocolAddress sourceAddress       = new SignalProtocolAddress(envelope.GetSource(), (uint)envelope.GetSourceDevice());
                SessionCipher         sessionCipher       = new SessionCipher(SignalProtocolStore, sourceAddress);
                SealedSessionCipher   sealedSessionCipher = new SealedSessionCipher(SignalProtocolStore, new SignalProtocolAddress(LocalAddress.E164number, 1));

                byte[]   paddedMessage;
                Metadata metadata;
                uint     sessionVersion;

                if (envelope.IsPreKeySignalMessage())
                {
                    paddedMessage  = sessionCipher.decrypt(new PreKeySignalMessage(ciphertext));
                    metadata       = new Metadata(envelope.GetSource(), envelope.GetSourceDevice(), envelope.GetTimestamp(), false);
                    sessionVersion = sessionCipher.getSessionVersion();
                }
                else if (envelope.IsSignalMessage())
                {
                    paddedMessage  = sessionCipher.decrypt(new SignalMessage(ciphertext));
                    metadata       = new Metadata(envelope.GetSource(), envelope.GetSourceDevice(), envelope.GetTimestamp(), false);
                    sessionVersion = sessionCipher.getSessionVersion();
                }
                else if (envelope.IsUnidentifiedSender())
                {
                    var results = sealedSessionCipher.Decrypt(CertificateValidator, ciphertext, (long)envelope.Envelope.ServerTimestamp);
                    paddedMessage  = results.Item2;
                    metadata       = new Metadata(results.Item1.Name, (int)results.Item1.DeviceId, (long)envelope.Envelope.Timestamp, true);
                    sessionVersion = (uint)sealedSessionCipher.GetSessionVersion(new SignalProtocolAddress(metadata.Sender, (uint)metadata.SenderDevice));
                }
                else
                {
                    throw new InvalidMessageException("Unknown type: " + envelope.GetEnvelopeType() + " from " + envelope.GetSource());
                }

                PushTransportDetails transportDetails = new PushTransportDetails(sessionVersion);
                byte[] data = transportDetails.GetStrippedPaddingMessageBody(paddedMessage);
                return(new Plaintext(metadata, data));
            }
            catch (DuplicateMessageException e)
            {
                throw new ProtocolDuplicateMessageException(e, envelope.GetSource(), envelope.GetSourceDevice());
            }
            catch (LegacyMessageException e)
            {
                throw new ProtocolLegacyMessageException(e, envelope.GetSource(), envelope.GetSourceDevice());
            }
            catch (InvalidMessageException e)
            {
                throw new ProtocolInvalidMessageException(e, envelope.GetSource(), envelope.GetSourceDevice());
            }
            catch (InvalidKeyIdException e)
            {
                throw new ProtocolInvalidKeyIdException(e, envelope.GetSource(), envelope.GetSourceDevice());
            }
            catch (InvalidKeyException e)
            {
                throw new ProtocolInvalidKeyException(e, envelope.GetSource(), envelope.GetSourceDevice());
            }
            catch (libsignal.exceptions.UntrustedIdentityException e)
            {
                throw new ProtocolUntrustedIdentityException(e, envelope.GetSource(), envelope.GetSourceDevice());
            }
            catch (InvalidVersionException e)
            {
                throw new ProtocolInvalidVersionException(e, envelope.GetSource(), envelope.GetSourceDevice());
            }
            catch (NoSessionException e)
            {
                throw new ProtocolNoSessionException(e, envelope.GetSource(), envelope.GetSourceDevice());
            }
        }
Example #10
0
        private byte[] Decrypt(SignalServiceEnvelope envelope, byte[] ciphertext)

        {
            SignalProtocolAddress sourceAddress = new SignalProtocolAddress(envelope.GetSource(), (uint)envelope.GetSourceDevice());
            SessionCipher         sessionCipher = new SessionCipher(SignalProtocolStore, sourceAddress);

            byte[] paddedMessage;

            if (envelope.IsPreKeySignalMessage())
            {
                paddedMessage = sessionCipher.decrypt(new PreKeySignalMessage(ciphertext));
            }
            else if (envelope.IsSignalMessage())
            {
                paddedMessage = sessionCipher.decrypt(new SignalMessage(ciphertext));
            }
            else
            {
                throw new InvalidMessageException("Unknown type: " + envelope.GetEnvelopeType() + " from " + envelope.GetSource());
            }

            PushTransportDetails transportDetails = new PushTransportDetails(sessionCipher.getSessionVersion());

            return(transportDetails.GetStrippedPaddingMessageBody(paddedMessage));
        }