def sendToGroupWithSessions(self, node, jidsNeedSenderKey = None, retryCount=0): jidsNeedSenderKey = jidsNeedSenderKey or [] groupJid = node["to"] ownNumber = self.getLayerInterface(YowAuthenticationProtocolLayer).getUsername(False) senderKeyName = SenderKeyName(groupJid, AxolotlAddress(ownNumber, 0)) cipher = self.getGroupCipher(groupJid, ownNumber) encEntities = [] if len(jidsNeedSenderKey): senderKeyDistributionMessage = self.groupSessionBuilder.create(senderKeyName) for jid in jidsNeedSenderKey: sessionCipher = self.getSessionCipher(jid.split('@')[0]) message = self.serializeSenderKeyDistributionMessageToProtobuf(node["to"], senderKeyDistributionMessage) if retryCount > 0: message = self.serializeToProtobuf(node, message) ciphertext = sessionCipher.encrypt(message.SerializeToString() + self.getPadding()) encEntities.append( EncProtocolEntity( EncProtocolEntity.TYPE_MSG if ciphertext.__class__ == WhisperMessage else EncProtocolEntity.TYPE_PKMSG , 2, ciphertext.serialize(), jid=jid ) ) if not retryCount: messageData = self.serializeToProtobuf(node).SerializeToString() ciphertext = cipher.encrypt(messageData + self.getPadding()) mediaType = node.getChild("media")["type"] if node.getChild("media") else None encEntities.append(EncProtocolEntity(EncProtocolEntity.TYPE_SKMSG, 2, ciphertext, mediaType)) self.sendEncEntities(node, encEntities)
def sendToGroup(self, node, retryReceiptEntity=None): groupJid = node["to"] ownNumber = self.getLayerInterface( YowAuthenticationProtocolLayer).getUsername(False) ownJid = self.getLayerInterface( YowAuthenticationProtocolLayer).getUsername(True) senderKeyName = SenderKeyName(node["to"], AxolotlAddress(ownNumber, 0)) senderKeyRecord = self.store.loadSenderKey(senderKeyName) def sendToGroup(resultNode, requestEntity): groupInfo = InfoGroupsResultIqProtocolEntity.fromProtocolTreeNode( resultNode) jids = list(groupInfo.getParticipants().keys() ) #keys in py3 returns dict_keys if ownJid in jids: jids.remove(ownJid) return self.ensureSessionsAndSendToGroup(node, jids) if senderKeyRecord.isEmpty(): groupInfoIq = InfoGroupsIqProtocolEntity(groupJid) self._sendIq(groupInfoIq, sendToGroup) else: retryCount = 0 jidsNeedSenderKey = [] if retryReceiptEntity is not None: retryCount = retryReceiptEntity.getRetryCount() jidsNeedSenderKey.append(retryReceiptEntity.getRetryJid()) self.sendToGroupWithSessions(node, jidsNeedSenderKey, retryCount)
def handleSenderKeyMessage(self, node): encMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode( node) enc = encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_SKMSG) senderKeyName = SenderKeyName( encMessageProtocolEntity.getFrom(True), AxolotlAddress(encMessageProtocolEntity.getParticipant(False), 0)) groupCipher = GroupCipher(self.store, senderKeyName) try: plaintext = groupCipher.decrypt(enc.getData()) #print("Plain before:", plaintext) padding = ord(plaintext[-1]) & 0xFF plaintext = plaintext[:-padding] plaintext = plaintext.encode() if sys.version_info >= ( 3, 0) else plaintext #print("Plain:", plaintext) self.parseAndHandleMessageProto(encMessageProtocolEntity, plaintext) except NoSessionException as e: logger.warning("No session for %s, going to send a retry", encMessageProtocolEntity.getAuthor(False)) retry = RetryOutgoingReceiptProtocolEntity.fromMessageNode( node, self.store.getLocalRegistrationId()) self.toLower(retry.toProtocolTreeNode())
def handleSenderKeyMessage(self, node): encMessageProtocolEntity = EncryptedMessageProtocolEntity(node) enc_ = encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_SKMSG) senderKeyName = SenderKeyName( encMessageProtocolEntity.sender, AxolotlAddress( Jid.denormalize(encMessageProtocolEntity.participant), 0)) groupCipher = GroupCipher(self.store, senderKeyName) try: plaintext = groupCipher.decrypt(enc_.getData()) paddingByte = plaintext[-1] if type(plaintext[-1]) is int else ord( plaintext[-1]) padding = paddingByte & 0xFF self.parseAndHandleMessageProto(encMessageProtocolEntity, plaintext[:-padding]) except NoSessionException: logger.warning( "No session for %s, going to send a retry", Jid.denormalize(encMessageProtocolEntity.getAuthor())) retry = RetryOutgoingReceiptProtocolEntity.fromMessageNode( node, self.store.getLocalRegistrationId()) self.toLower(retry.toProtocolTreeNode()) except Exception as ex: # (AttributeError, TypeError) logger.error('Exception in handleSenderKeyMessage: %s' % ex) raise
def getGroupCipher(self, groupId, senderId): senderKeyName = SenderKeyName(groupId, AxolotlAddress(senderId, 0)) if senderKeyName in self.groupCiphers: groupCipher = self.groupCiphers[senderKeyName] else: groupCipher = GroupCipher(self.store, senderKeyName) self.groupCiphers[senderKeyName] = groupCipher return groupCipher
def _get_group_cipher(self, groupid, username): logger.debug("get_group_cipher(groupid=%s, username=%s)" % (groupid, username)) senderkeyname = SenderKeyName(groupid, AxolotlAddress(username, 0)) if senderkeyname in self._group_ciphers: group_cipher = self._group_ciphers[senderkeyname] else: group_cipher = GroupCipher(self._store.senderKeyStore, senderkeyname) self._group_ciphers[senderkeyname] = group_cipher return group_cipher
def handleSenderKeyDistributionMessage(self, senderKeyDistributionMessage, axolotlAddress): groupId = senderKeyDistributionMessage.groupId axolotlSenderKeyDistributionMessage = SenderKeyDistributionMessage( serialized=senderKeyDistributionMessage. axolotl_sender_key_distribution_message) groupSessionBuilder = GroupSessionBuilder(self.store) senderKeyName = SenderKeyName(groupId, axolotlAddress) groupSessionBuilder.process(senderKeyName, axolotlSenderKeyDistributionMessage)
def handleSenderKeyMessage(self, node): encMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node) enc = encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_SKMSG) senderKeyName = SenderKeyName(encMessageProtocolEntity.getFrom(True), AxolotlAddress(encMessageProtocolEntity.getParticipant(False), 0)) groupCipher = GroupCipher(self.store, senderKeyName) try: plaintext = groupCipher.decrypt(enc.getData()) padding = ord(plaintext[-1]) & 0xFF self.parseAndHandleMessageProto(encMessageProtocolEntity, plaintext[:-padding]) except NoSessionException as e: logger.error(e) retry = RetryOutgoingReceiptProtocolEntity.fromMessageNode(node) retry.setRegData(self.store.getLocalRegistrationId()) self.toLower(retry.toProtocolTreeNode())
def group_create_session(self, groupid, participantid, skmsgdata): """ :param groupid: :type groupid: str :param participantid: :type participantid: str :param skmsgdata: :type skmsgdata: bytearray :return: :rtype: """ logger.debug("group_create_session(groupid=%s, participantid=%s, skmsgdata=[omitted])" % (groupid, participantid)) senderKeyName = SenderKeyName(groupid, AxolotlAddress(participantid, 0)) senderkeydistributionmessage = SenderKeyDistributionMessage(serialized=skmsgdata) self._group_session_builder.process(senderKeyName, senderkeydistributionmessage)
def handleSenderKeyMessage(self, node): encMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode( node) enc = encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_SKMSG) senderKeyName = SenderKeyName( encMessageProtocolEntity.getFrom(True), AxolotlAddress(encMessageProtocolEntity.getParticipant(False), 0)) groupCipher = GroupCipher(self.store, senderKeyName) try: plaintext = groupCipher.decrypt(enc.getData()) if type(plaintext) == bytes: # DEBUG SET RECEIPT # self.toLower(OutgoingReceiptProtocolEntity(node["id"], node["from"], 'read', participant=node["participant"]).toProtocolTreeNode()) if plaintext[0:1] == b'\n': msg = plaintext[3:3 + plaintext[1:2][-1]] elif plaintext[2:3] == b'\x01': msg = plaintext[5:5 + plaintext[4:5][-1]] if msg[0:1] == b'\x01': msg = plaintext[6:6 + plaintext[4:5][-1]] else: msg = plaintext[4:4 + plaintext[3:4][-1]] # self.parseAndHandleMessageProto(encMessageProtocolEntity, plaintext) self.handleConversationMessage(node, msg.decode()) # self.parseAndHandleMessageProto(encMessageProtocolEntity, plaintext.split(b'\x8a')[0]) return try: padding = ord(plaintext[-1]) & 0xFF plaintext = plaintext[:-padding] plaintext = plaintext.encode() if sys.version_info >= ( 3, 0) else plaintext self.parseAndHandleMessageProto(encMessageProtocolEntity, plaintext) except Exception as ex: #(AttributeError, TypeError) logger.error('Exception') logger.error('Exception %s' % ex) except NoSessionException as e: logger.warning("No session for %s, going to send a retry", encMessageProtocolEntity.getAuthor(False)) retry = RetryOutgoingReceiptProtocolEntity.fromMessageNode( node, self.store.getLocalRegistrationId()) self.toLower(retry.toProtocolTreeNode())
def load_senderkey(self, groupid): logger.debug("load_senderkey(groupid=%s)" % groupid) senderkeyname = SenderKeyName(groupid, AxolotlAddress(self._username, 0)) return self._store.loadSenderKey(senderkeyname)
def group_create_skmsg(self, groupid): logger.debug("group_create_skmsg(groupid=%s)" % groupid) senderKeyName = SenderKeyName(groupid, AxolotlAddress(self._username, 0)) return self._group_session_builder.create(senderKeyName)