Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Message decrypt error #683

Closed
bmutinda opened this issue Mar 14, 2015 · 11 comments
Closed

Message decrypt error #683

bmutinda opened this issue Mar 14, 2015 · 11 comments
Labels

Comments

@bmutinda
Copy link

I seem to be getting this exception for some messages. I have enabled axolotl for encryption.

What might be the issue??

This is the error stack trace.

Traceback (most recent call last):
  File "myproject_run.py", line 46, in <module>
    run()
  File "myproject_run.py", line 43, in run
    stack.loop() #this is the program mainloop
  File "/var/www/html/myproject/yowsup/stacks/yowstack.py", line 170, in loop
    asyncore.loop(*args, **kwargs)
  File "/usr/lib/python2.7/asyncore.py", line 216, in loop
    poll_fun(timeout, map)
  File "/usr/lib/python2.7/asyncore.py", line 156, in poll
    read(obj)
  File "/usr/lib/python2.7/asyncore.py", line 87, in read
    obj.handle_error()
  File "/usr/lib/python2.7/asyncore.py", line 83, in read
    obj.handle_read_event()
  File "/usr/lib/python2.7/asyncore.py", line 449, in handle_read_event
    self.handle_read()
  File "/var/www/html/myproject/yowsup/layers/network/layer.py", line 48, in handle_read
    self.receive(data)
  File "/var/www/html/myproject/yowsup/layers/network/layer.py", line 55, in receive
    self.toUpper(data)
  File "/var/www/html/myproject/yowsup/layers/__init__.py", line 55, in toUpper
    self.__upper.receive(data)
  File "/var/www/html/myproject/yowsup/layers/stanzaregulator/layer.py", line 28, in receive
    self.processReceived()
  File "/var/www/html/myproject/yowsup/layers/stanzaregulator/layer.py", line 51, in processReceived
    self.processReceived()
  File "/var/www/html/myproject/yowsup/layers/stanzaregulator/layer.py", line 51, in processReceived
    self.processReceived()
  File "/var/www/html/myproject/yowsup/layers/stanzaregulator/layer.py", line 48, in processReceived
    self.toUpper(oneMessageData)
  File "/var/www/html/myproject/yowsup/layers/__init__.py", line 55, in toUpper
    self.__upper.receive(data)
  File "/var/www/html/myproject/yowsup/layers/auth/layer_crypt.py", line 63, in receive
    self.toUpper(payload)
  File "/var/www/html/myproject/yowsup/layers/__init__.py", line 55, in toUpper
    self.__upper.receive(data)
  File "/var/www/html/myproject/yowsup/layers/coder/layer.py", line 35, in receive
    self.toUpper(node)
  File "/var/www/html/myproject/yowsup/layers/__init__.py", line 55, in toUpper
    self.__upper.receive(data)
  File "/var/www/html/myproject/yowsup/layers/logger/layer.py", line 14, in receive
    self.toUpper(data)
  File "/var/www/html/myproject/yowsup/layers/__init__.py", line 55, in toUpper
    self.__upper.receive(data)
  File "/var/www/html/myproject/yowsup/layers/axolotl/layer.py", line 99, in receive
    self.onMessage(protocolTreeNode)
  File "/var/www/html/myproject/yowsup/layers/axolotl/layer.py", line 117, in onMessage
    self.handleEncMessage(protocolTreeNode)
  File "/var/www/html/myproject/yowsup/layers/axolotl/layer.py", line 175, in handleEncMessage
    self.handleWhisperMessage(node)
  File "/var/www/html/myproject/yowsup/layers/axolotl/layer.py", line 195, in handleWhisperMessage

 plaintext = sessionCipher.decryptMsg(whisperMessage)
  File "/usr/local/lib/python2.7/dist-packages/axolotl/sessioncipher.py", line 71, in decryptMsg
    raise NoSessionException("No session for: %s, %s" % (self.recipientId, self.deviceId))
axolotl.nosessionexception.NoSessionException: No session for: 255xxxxxxxx, 1
@bmutinda
Copy link
Author

Just followed this issue response #593 [Try to connect several times] but it only works for some time then the error resumes.

@bmutinda
Copy link
Author

For those who have experienced the same problem, here is what I did.

Rather than letting the exception to terminate my program, I had to try catch the sections that raised exceptions both in the axolotl layer.py(NoSession exception) - issue #593 and protocol messages/message_text.py(AttributeError: 'NoneType' object has no attribute 'getData' ) - issue #690

Here is my fix.

yowsup/layers/axolotl/layer.py - from line 179

def handlePreKeyWhisperMessage(self, node):
        plaintext = None
        try:
            pkMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node)
            preKeyWhisperMessage = PreKeyWhisperMessage(serialized=pkMessageProtocolEntity.getEncData())
            sessionCipher = self.getSessionCipher(pkMessageProtocolEntity.getFrom(False))
            plaintext = sessionCipher.decryptPkmsg(preKeyWhisperMessage)
        except Exception as e:
            print 'Message decript error -> %s' %(str(e))

        bodyNode = ProtocolTreeNode("body", data = plaintext)
        node.addChild(bodyNode)
        self.toUpper(node)

    def handleWhisperMessage(self, node):
        plaintext = None
        try:
            encMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node)
            whisperMessage = WhisperMessage(serialized=encMessageProtocolEntity.getEncData())
            sessionCipher = self.getSessionCipher(encMessageProtocolEntity.getFrom(False))
            plaintext = sessionCipher.decryptMsg(whisperMessage)
        except Exception as e:
            print 'Message decript error -> %s' %(str(e))

        bodyNode = ProtocolTreeNode("body", data = plaintext)
        node.addChild(bodyNode)
        self.toUpper(node)
    ####

yowsup/layers/protocol_messages/protocolentities/message_text.py - from line 35

@staticmethod
    def fromProtocolTreeNode(node):
        entity = MessageProtocolEntity.fromProtocolTreeNode(node)
        entity.__class__ = TextMessageProtocolEntity
        #entity.setBody(node.getChild("body").getData())
        #return entity
        try:
            entity.setBody(node.getChild("body").getData())
            return entity
        except Exception, e:
            pass 
        entity.setBody( None )
        return entity

After doing this, In my layer onMessage method, I check if the message is empty then return an error message to my customer.

NB: I realized that the next time a message comes the same number which was initialized raising exceptions, It doesn't raise it again - a new session created -

This quick fix helped me out.

Similar issue was created here #593
Thanks.

@danielapsmaior
Copy link

@tgalal I'm trying to do something similar as in handlePlaintextNode, where it does a _sendIq with GetKeysIqProtocolEntity and then processes a pendingMessages on the onGetKeysResult callback.
My problem is after I get the session, I don't know how to use the keys to decrypt my pending message. It's giving me a "Bad Mac" error in the WhisperMessage.verifyMac().

Is there a way to do this? Thank you in advance for any help.

def handleEncMessage(self, node):
        encEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node)
        mFrom = encEntity.getFrom()
        if not self.store.containsSession(encEntity.getFrom(False), 1):
            if mFrom not in self.pendingMessagesFrom:
                self.pendingMessagesFrom[mFrom] = []
            self.pendingMessagesFrom[mFrom].append(node)
            entity = GetKeysIqProtocolEntity([mFrom])
            self._sendIq(entity, self.onGetKeysResult, self.onGetKeysError)
        else:
            try:
                if node.getChild("enc")["type"] == "pkmsg":
                    plaintext = self.handlePreKeyWhisperMessage(encEntity)
                else:
                    plaintext = self.handleWhisperMessage(encEntity)
            except InvalidMessageException:
                logger.error("Invalid message from %s!! Your axololtl database data might be inconsistent with WhatsApp, or with what that contact has" % node["from"])
                sys.exit(1)
            bodyNode = ProtocolTreeNode("body", data = plaintext)
            node.addChild(bodyNode)
            self.toUpper(node)

def handlePreKeyWhisperMessage(self, pkMessageProtocolEntity):
        preKeyWhisperMessage = PreKeyWhisperMessage(serialized=pkMessageProtocolEntity.getEncData())
        sessionCipher = self.getSessionCipher(pkMessageProtocolEntity.getFrom(False))
        try:
            return sessionCipher.decryptPkmsg(preKeyWhisperMessage)
        except Exception,e:
            return None   

def handleWhisperMessage(self, encMessageProtocolEntity):
        whisperMessage = WhisperMessage(serialized=encMessageProtocolEntity.getEncData())
        sessionCipher = self.getSessionCipher(encMessageProtocolEntity.getFrom(False))
        try:
            return sessionCipher.decryptMsg(whisperMessage)
        except Exception,e:
            return None

def onGetKeysResult(self, resultNode, getKeysEntity):
        entity = ResultGetKeysIqProtocolEntity.fromProtocolTreeNode(resultNode)

        resultJids = entity.getJids()
        for jid in getKeysEntity.getJids():
            if jid not in resultJids:
                self.skipEncJids.append(jid)
                self.processPendingMessages(jid)
                self.processPendingMessagesFrom(jid)
                continue

            recipient_id = jid.split('@')[0]
            preKeyBundle = entity.getPreKeyBundleFor(jid)

            sessionBuilder = SessionBuilder(self.store, self.store, self.store,
                                               self.store, recipient_id, 1)
            sessionBuilder.processPreKeyBundle(preKeyBundle)

            self.processPendingMessages(jid)
            self.processPendingMessagesFrom(jid)

def processPendingMessagesFrom(self, jid):
        if jid in self.pendingMessagesFrom:
            for node in self.pendingMessagesFrom[jid]:
                self.handleEncMessage(node)

            del self.pendingMessagesFrom[jid]

@danielapsmaior
Copy link

@tgalal I got it! I don't know if you're interested in the solution, worthing a pull request.. But I created a new protocol entity to ask Whatsapp to retry the message after my session was created, and then this new retry comes with ratcket keys I can decrypt :)

@CODeRUS
Copy link
Contributor

CODeRUS commented May 29, 2015

retry receipt node PR would be cool

@danielapsmaior
Copy link

yowsup.layers.protocol_receipts.protocolentities.retry_receipt_outgoing

from yowsup.structs import ProtocolEntity, ProtocolTreeNode
from .receipt_outgoing import OutgoingReceiptProtocolEntity
from yowsup.layers.axolotl.protocolentities.iq_keys_get_result import ResultGetKeysIqProtocolEntity
class RetryReceiptProtocolEntity(OutgoingReceiptProtocolEntity):

    '''
    <receipt type="retry" to="xxxxxxxxxxx@s.whatsapp.net" id="1415389947-12" t="1432833777">
        <retry count="1" t="1432833266" id="1415389947-12" v="1">
        </retry>
        <registration>
            HEX:xxxxxxxxx
        </registration>
    </receipt>

    '''

    def __init__(self, _id, to, t, v = "1", count = "1",regData = ""):
        super(RetryReceiptProtocolEntity, self).__init__(_id,to)
        self.setRetryData(t,v,count,regData)

    def setRetryData(self, t,v,count,regData):
        self.t = t
        self.v = v
        self.count = count
        self.regData = regData

    def setRegData(self,regData):
        '''
        In axolotl layer:
        regData = self.store.getLocalRegistrationId()
        '''
        self.regData = ResultGetKeysIqProtocolEntity._intToBytes(regData)

    def toProtocolTreeNode(self):
        node = super(RetryReceiptProtocolEntity, self).toProtocolTreeNode()
        node.setAttribute("type", "retry")
        retry = ProtocolTreeNode("retry", {"count": self.count,"t":self.t,"id":self.getId(),"v":self.v})
        node.addChild(retry)
        registration = ProtocolTreeNode("registration",data=self.regData)
        node.addChild(registration)
        return node

    def __str__(self):
        out = super(RetryReceiptProtocolEntity, self).__str__()
        return out

    @staticmethod
    def fromProtocolTreeNode(MessageNodeToBeRetried):
        return RetryReceiptProtocolEntity(
            MessageNodeToBeRetried.getAttributeValue("id"),
            MessageNodeToBeRetried.getAttributeValue("from"),
            MessageNodeToBeRetried.getAttributeValue("t"),
            MessageNodeToBeRetried.getChild("enc").getAttributeValue("v")
        )

@tgalal
Copy link
Owner

tgalal commented Jul 27, 2015

@danielapsmaior thanks for the code!

@tgalal
Copy link
Owner

tgalal commented Jul 27, 2015

Please try code from develop branch

@tgalal tgalal closed this as completed in 6ebbbe2 Aug 1, 2015
@bdbais
Copy link

bdbais commented Dec 29, 2015

I have same problem, with deployment and with official version.
There is a light at the end of this tunnel?
ERROR:yowsup.layers.axolotl.layer:No valid sessionsBad Mac!
some workaround is possible?

DEBUG:yowsup.layers.logger.layer:rx:


3
▒_R▒,▒▒61t.XYcM▒▒▒▒.▒▒y▒▒M▒▒▒"▒2▒
HEX:330a2105d9a1bdc5e2bd816588fab3bbb9e3e14db082f69dc8082e96a5799a934dbe8c1410ae0618002210d832de0de3f1e6e9ca0df55f52942cfdcc3631742e585963

ERROR:yowsup.layers.axolotl.layer:No valid sessionsBad Mac!
DEBUG:yowsup.layers.logger.layer:tx:




~▒▒
HEX:7eead808

DEBUG:yowsup.layers.logger.layer:rx:



@bdbais
Copy link

bdbais commented Dec 30, 2015

I removed axolotl.db from my .yowsup folder... last beach.

@bdbais
Copy link

bdbais commented Dec 30, 2015

yowsup.layers.axolotl.layer:No session for: 3393939337777
ERROR:yowsup.layers.axolotl.layer:No valid sessionsBad Mac!

but after 10 messages now is working again...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants