tgalal / yowsup

The WhatsApp lib
GNU General Public License v3.0
7.09k stars 2.23k forks source link

Can't receive Encrypt image #1400

Closed Dimelay closed 5 years ago

Dimelay commented 8 years ago

File "/home/steck/whatsappMy/yowsup/yowsup/layers/protocol_media/layer.py", line 41, in recvMessageStanza if mediaNode.getAttributeValue("type") == "image": AttributeError: 'NoneType' object has no attribute 'getAttributeValue'

DATA Decrypt body: yowsup/layers/axolotl/layer.py: def handleWhisperMessage(self, node): encMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node) ``` whisperMessage = WhisperMessage(serialized=encMessageProtocolEntity.getEncData()) sessionCipher = self.getSessionCipher(encMessageProtocolEntity.getFrom(False)) plaintext = sessionCipher.decryptMsg(whisperMessage) if encMessageProtocolEntity.getVersion() == 2: plaintext = self.unpadV2Plaintext(plaintext) //PRINT DECRYPT BODY print plaintext // bodyNode = ProtocolTreeNode("body", data = plaintext) node.addChild(bodyNode) self.toUpper(node) ``` Link to my file https://mmi488.whatsapp.net/d/0QVa5QLVNRiH0HZ_gU-W5FbzX-4/AhbVJi2WS1Yia7EklnoFua1fwMezYiqzH4BQsv53_63Z.enc ┴�K\←c��� *�/R���Zc�T㡪Z│ܒM���O·�┘┌��±b�c�H�─�π─U��┌\└ǎ�K91b��←?:◆�;±�⎺��cM&RF���_�M��1���┤4?���d��K'E��̏�
yniv commented 8 years ago

no clue. have you looked at the wa16 branch I think @tgalal has already started working on this. maybe its working there. also, @mgp25 's the chat-api already implemented this. you can check there. please post here any progress you have cause currently yowsup is useless

yniv commented 8 years ago

@Dimelay can you please post the code to simple ignore image messages for now, so it won't break the code? (until someone will solve the problem)

Dimelay commented 8 years ago

@yniv Edit file yowsup/layers/protocol_media/layer.py

Find and modify function def recvMessageStanza(self, node): pass

There is little time for this. Simple ignore

Sorry/ google translate =)

yniv commented 8 years ago

@Dimelay but maybe we need to send ack anyway?

Dimelay commented 8 years ago

@yniv Done! Receive notification about the image and sent 'ack' package It does not fall. How can you put the files? =)

Dimelay commented 8 years ago

yowsup/layers/protocol_media/layer.py

def recvMessageStanza(self, node): if node.getAttributeValue("type") == "media": mediaNode = node.getChild("enc") if mediaNode.getAttributeValue("mediatype") == "image": entity = ImageDownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node) self.toUpper(entity) print 'protocol_media/layer.py recv image from %s' % node.getAttributeValue("from") elif mediaNode.getAttributeValue("type") == "audio": entity = AudioDownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node) self.toUpper(entity) elif mediaNode.getAttributeValue("type") == "video": entity = VideoDownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node) self.toUpper(entity) elif mediaNode.getAttributeValue("type") == "location": entity = LocationMediaMessageProtocolEntity.fromProtocolTreeNode(node) self.toUpper(entity) elif mediaNode.getAttributeValue("type") == "vcard": entity = VCardMediaMessageProtocolEntity.fromProtocolTreeNode(node) self.toUpper(entity)

yowsup/layers/protocol_media/protocolentities/message_media_downloadable.py

@staticmethod def fromProtocolTreeNode(node): entity = MediaMessageProtocolEntity.fromProtocolTreeNode(node) entity.class = DownloadableMediaMessageProtocolEntity """ mediaNode = node.getChild("media") entity.setDownloadableMediaProps( mediaNode.getAttributeValue("mimetype"), mediaNode.getAttributeValue("filehash"), mediaNode.getAttributeValue("url"), mediaNode.getAttributeValue("ip"), mediaNode.getAttributeValue("size"), mediaNode.getAttributeValue("file") ) """ return entity

yowsup/layers/protocol_media/protocolentities/message_media_downloadable_image.py

@staticmethod def fromProtocolTreeNode(node): entity = DownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node) entity.class = ImageDownloadableMediaMessageProtocolEntity """ mediaNode = node.getChild("media") entity.setImageProps( mediaNode.getAttributeValue("encoding"), mediaNode.getAttributeValue("width"), mediaNode.getAttributeValue("height"), mediaNode.getAttributeValue("caption"), ) """ return entity

yowsup/layers/protocol_media/protocolentities/message_media.py

@staticmethod def fromProtocolTreeNode(node): entity = MessageProtocolEntity.fromProtocolTreeNode(node) entity.class = MediaMessageProtocolEntity """ entity.setMediaType(node.getChild("media").getAttributeValue("type")) preview = node.getChild("media").getData() entity.setPreview(preview) """ return entity

bdbais commented 8 years ago

I have this problem, is it the same?

... File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/init.py", line 59, in toUpper self.upper.receive(data) File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/__init.py", line 169, in receive s.receive(data) File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/init.py", line 105, in receive recv(node) File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/protocol_media/layer.py", line 40, in recvMessageStanza if mediaNode.getAttributeValue("type") == "image": AttributeError: 'NoneType' object has no attribute 'getAttributeValue'

yniv commented 8 years ago

yes

pag16 commented 8 years ago

https://github.com/tgalal/yowsup/issues/1389 you can try solution which i propose here to ignore these scenarios in meanwhile

jodersus commented 8 years ago

@Dimelay could you pls post your code with indentation? use three of this character: ` (<- copy paste ;) before and after the code.

Thanks! A

bdbais commented 8 years ago
    def recvMessageStanza(self, node):
        if node.getAttributeValue("type") == "media":
            mediaNode = node.getChild("enc")
            if mediaNode.getAttributeValue("mediatype") == "image":
                entity = ImageDownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node)
                self.toUpper(entity)
                print 'protocol_media/layer.py recv image from %s' % node.getAttributeValue("from")
            elif mediaNode.getAttributeValue("type") == "audio":
                entity = AudioDownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node)
                self.toUpper(entity)
            elif mediaNode.getAttributeValue("type") == "video":
                entity = VideoDownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node)
                self.toUpper(entity)
            elif mediaNode.getAttributeValue("type") == "location":
                entity = LocationMediaMessageProtocolEntity.fromProtocolTreeNode(node)
                self.toUpper(entity)
            elif mediaNode.getAttributeValue("type") == "vcard":
                entity = VCardMediaMessageProtocolEntity.fromProtocolTreeNode(node)
            self.toUpper(entity)

I'm trying to do it

bdbais commented 8 years ago
    @staticmethod
    def fromProtocolTreeNode(node):
        entity = MediaMessageProtocolEntity.fromProtocolTreeNode(node)
        entity.__class__ = DownloadableMediaMessageProtocolEntity
        """
            mediaNode = node.getChild("media")
            entity.setDownloadableMediaProps(
            mediaNode.getAttributeValue("mimetype"),
            mediaNode.getAttributeValue("filehash"),
            mediaNode.getAttributeValue("url"),
            mediaNode.getAttributeValue("ip"),
            mediaNode.getAttributeValue("size"),
            mediaNode.getAttributeValue("file")
            )
        """
        return entity
bdbais commented 8 years ago
    @staticmethod
    def fromProtocolTreeNode(node):
        entity = DownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node)
        entity.__class__ = ImageDownloadableMediaMessageProtocolEntity
        """
            mediaNode = node.getChild("media")
            entity.setImageProps(
            mediaNode.getAttributeValue("encoding"),
            mediaNode.getAttributeValue("width"),
            mediaNode.getAttributeValue("height"),
            mediaNode.getAttributeValue("caption"),
            )
        """
    return entity

okay fixed

bdbais commented 8 years ago
    @staticmethod
    def fromProtocolTreeNode(node):
        entity = MessageProtocolEntity.fromProtocolTreeNode(node)
        entity.__class__ = MediaMessageProtocolEntity
        """
        entity.setMediaType(node.getChild("media").getAttributeValue("type"))
        preview = node.getChild("media").getData()
        entity.setPreview(preview)
        """
        return entity
bdbais commented 8 years ago

not resolve for me:

  File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/protocol_media/protocolentities/message_media_downloadable.py", line 30, in __str__
    out  = super(DownloadableMediaMessageProtocolEntity, self).__str__()
  File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/protocol_media/protocolentities/message_media.py", line 108, in __str__
    out += "Media Type: %s\n" % self.mediaType
AttributeError: 'DownloadableMediaMessageProtocolEntity' object has no attribute 'mediaType'
payamazadi commented 8 years ago

@bdbais @jlguardi the above is a step in the right direction - following changes:

  1. in protocol_media/layer.py recvStanzaMessage
if node.getAttributeValue("type") == "media":
            mediaNode = node.getChild("enc") #change media to enc
  1. in protocol_media/protocolentities/message_media.py fromProtocolTreeNode
entity.setMediaType(node.getAttributeValue("mediatype")) #instead of .getChild etc)
preview = node.getData() # instead of .getChild etc)

This makes things conform to the new encrypted XML body, which @Dimelay alluded to, which is something like:

<enc type="msg" mediatype="image" v="2">
3
!�ƕ�u����[
          -�J�,��q���z�/�6wE"�L�sm�u!D���d��X����{�T%@,_�k���/���P dh�XG.�{-�ۇֆ��H[Pl�"�rA"t�&�^r�V�{�i=��(�$j�߾.���a�T�ç�#��;�{��7��}�Խ{�-#B����'(���-�
��|w�&�@C���IJ���٦A� �w�8̶�;\d\�y����#F�ăc�€\��`����L�ݮ��5q�/�e�)<`��4'����X�r�F���<ow�[.���k6p�*75~,`^���X��� ���{��hf��7����~w�g��1Q��z�l����ӆ#�0�Kk���e���f��t���jὭ0M��L�
            ;t ;t/��r�s���C�B��QUhy�aC�
                                       6��Wcz�Q�Z ��J\��c9dAޚ*����h�S��d�5��)��{?�t�*��uȿ�O-��u�� ��]�Scp��0
�Kێ3�m_ut`5
           ��ˍvk^���޼�-4�/
                          �g�~ �&L��2�_��Ѐݻ�!ԭ�_뙅�\�w��%�?�C����%}7��f7��R�=�9�5}^�;��t�kt�d'�\��"�Ve�n}��0q(�*3�p�n�º���^߾����������c/���aDÕ�y�*��9s�8���T�   ����%X|s�zX�ROr*�$�z��c(�S��$    >��c>�M���o+���>�z��
;"H�y6e��#�/�����a����|��ΊѤߣ��;y�s�
h8c�<F    (+��=�?��[*C/@��'\he �>���X�i*���xY�wB���3C^6�i�Jt�����$��q�ĝ�i�躼0
                                                                            L}�����(t���*`y,p��ok0��;C݄x��Q.?���gٔLJ1E��e��-�s�"��9��}�WR�+5�I�O�Q�:�Τx���f�D�I]b�[C�k��@���9�V��$�]����#x�S0��s���΢S�L9�i!���ha��-bO�S��a6]Mq�(��N�s&��Nv�Ð��Ň�#uqd�>�IT����=vJK?"x���XXy��1��O4�{����UCj�
                                         ����Uj���@���]uQ� �ȍ�E���׬`{,�1�B
                                                                          t�jzg8?k_��xj���/���X^���]F@d�-��z�Z
                              �Ǝ�����m���H�tm�.�c��%���/�7VP�    ��pϟ�W��?�{������)�xJ~��Q^�?�A���GP���3|am豸���}Yne�=����`�ǎ
��H���w������r�$�m�(�աm@Y|��[f��%�JC�Ic=~3
���c�j
      =�����M�_郖�ZP ���V�l��g7��X}7g���XTL��f�Z\
+�1y�0�u��M{�R���rZ{�\�C��k�?�8>��l7���� ��$���5�_"I�]�BΊ�>�I�J�YƋ���)���B?���Q�
p�>�3M4���bʪt�5���7��)�0�oXg2���G�3X󆁉����5_
                                      �t��H�lZ,��t)��&��Ņ\޽�$�`�2�*��ceށ�Ed_�꽇N*E����7<�o#�/�G��ʂ�#YV'nol�
2���$aa�_%�Dî�#��'�7&�6N�g��hsM%ڷ�?�c�_�mjz������m^����@�R)��RfN�C��J����2xuGd�U��Rz�e3�H�]��4����ǀ�G?h��\1�/��M
                                JaL}���]���D��*0]��(.�nt}@:�À}�@oO&T��A����c�p T�P�IhjW�P��oϐ���-�ӱ�.M���dv,i`KNS��%���E�9��jOM��V�\w��
                                                       Oƈz_ۄ�s�{��A���<��&�p�o�7�O�a��(_&_�v~�I�}�<����w��?]%�uf��nDZ-��y�L�w����Q(eD�z����6�����65�JԆ)�(��M�ɢ�j���w>�/4{_�v���/��=�P�O���<���i�1����z9�)�袢9�C�� �ط�
                                                     y^�SX��Ϯ楉>����:e
���j�a]�z�g�V>y�+d ���I�0��P'�=ߞ�
HEX:330a210598c6958075a8cablahblahblah more of this
</enc>

The question is, now we have the encrypted data in value node, we just need to decrypt it. What should be the process to do this? What is the key, where do we get it from, and how do we use it to decrypt the message body? It looks like the image data itself is encoded into the message, which means when we decrypt it we'll have the binary that makes up the image (including exif data etc). So no need to go and download an image from a URL, which makes mediadownloader.py unnecessary..

payamazadi commented 8 years ago

This is the full printout from below, with some relevant areas bolded

            print(node)
3 !�ƕ�u����[ -�J�,��q���z�/�6wE"�� �MQ�H�x�Y�6���R �N�T��1�9j�D���9�M ?�9XM- d�+bB�V2� �ZY���eZ�Z�1� 0.3;2��[(��lۧ�2x�(�Y��w:�ˡq�Dݕ�y1f2�4oѧ���..��(�~��Xn����.6z)�kctbA9�B�d6Ih����d��1G+C��v�?S_5�\Z���=n.Qn���b.�2}HC�#P��\��Ja��O��ح��Dy~(H�7}Öy99����9���rֱ�'?�J��lM�R�L�>�M`��#,�LS�W�"��� �����X��Q�Ԓ���BP��������k&� K&v�t�<Ϥ��x���������$T����j�qVό��53�,t����ں��;�����=�^��0̎)�£��������Ը��Yk�~��*�{����u=��q��S�*k���;W8��Ah��!Ż��L����� �9��ju�*<�(�o������Tc����H�����ӜO�;k�H��Ľ�G_��<��4 �?oB�S�X��1��V1A�3�o&�^%�,籬G Y �Ǟ�.��qX�0k� �����^run�i;Gx���zR�c�o�&C�u\KE&�[�0���$!S(�8t�?o㺟h�=M=�zxA�`�C/�hQ� �I���a�o��x$�6�R V'@ pJw$�_�n,=�,�pk��:�W�Mf�/��w�����j[ʎ�V��o������h��Eb#��-$�A��p#������[��˛X���# u��J��o��,~S ɽ�Mّ̆P!5y@81��X#��v.���KV�@��.�R�3G�'I�A�j�$ϴ�P� �V�F���b)�#���� ���2ʃ�r�ꏖ�Sѓ����"�G��Q��n��3�IH�f���S��7B}�_ʒ-EW��d�纝��E��f�I ��Z��Kc�����B-�i�Z�s�\�� �3r:y@�1+. p��i��g1��bV!�1*�7M�z 6���S۵���ҡ��恂�k��?��H@�kO�w��U���L��C�6]d �X�j�`����u{�Yi��^"8���E�k6-{��B��m����U��i��!� �/N���C6�s�$�=Y�n�@�3 r�#Ř�;`/�H�]x"MVͿl^z}�/�v� ~�X�(�E�1ռYFΈ�{�)�y�y�Œҫm��!8:55�]� Tp��0���vZ�$��;L p��~4�G����fy�mLH�<�6�wbn��`�jڿ�P����f~YHf���ɤ櫇 ���~'��� �U��{��������k�]���~�5�jn�H�H9�_�+�1�N/`>! S��80e�����h��p�&���lhwzg���􉮌d,���f��,=(�7��}�Yq�:�\G����-��R( R��e��?���t�3�@�$���4�K��pv� W�X>6\$:��Kj˦��Y�v�Gn?We��_�p�"�D\��lO�h��(��,�4�j��� �K�W�g/�]���9�,�;B 5��2���ʣdX A�+� sk|�g^� �E�}�0�0eZ���@� os�Y��i��j,��z��D T�B����� �<5Pˬ� ��^��"�5Ӄtg��њ�A�X�� �)���X��O�\�6�����~6�2%��+����R-�]��V��dG��s1��t�t� HEX:330a210598c6958075a8cadbc75b0b2d874ab52c1cc3ed7104bbecf97a06af2fab3677451007180322c01201eab020c54d511b57ec48d578d859be361685c7f5520cc1914ee05400a5d031be39106af444afe8e1a439c64d0b123fe1aa39588f1f081e4d2d0b1bdc64952b62427fee5632e20a8f125a59e4f08decbf65015ab25a03d631eb200c302e33073b32dd7fd05b28e4f96cdba7bb3278a628fb94598dd6773a80cba171e744dd9591791a316632f9346fd1a7efdefe2e2ea4f528fc9e10047ee806e314586ef5d3e2b4eb83052e367a29ac6b6374624139eea7428b1d6436014968e7c817bea16494f231472b43a8af76cd3f535f35bf5c5aa3a8c43d6e2e1951036e0186d1e4622ec0327d481243ad2350b7c85cfcd74a611ac0da4fcaf0d8adf3d044797e1f2848f2377dc3961879393910bc8291f090399cefc972d6b113c9273fea4a04dcfb6c4d1fab52984cbf173ef24d7fc50860ada023002c8f4c53b157f5229fbf11eca320fab0de14f31b8dd9d55813898951b5d492bee3deadff1bd34250b2eceeebcda793d1d4cc6b26b90b4b2676c374f6bc3ccfa4e7c078c1af5e1fd08f765845fb50cb6e5ad4a1404082604c3244b3eb59aaec19115affeaf1925961e944c8c06de6dd30d84ef53c7f0f2e8cb1e0b9928032af953cde7deb0d89dee4ebebe51e84bdf524548dba021249dbad08e2f96a997156cf8c97a6350f151133eb2c7412f9a5ce157ff21604e0dabaa904953b98b5bb86d41a3dd05e8ef0b530cc8e2994c2a3f901ca15a4158795178ebac8d4b89bde596bbf7eece92ac97b84c3de13ef753daae0b271d3e8531fde2a126bb07fe4ade6bc3b5738f6e69e416802a4e0a121c5bb81e2884c9ceac9ef00bd20d139d6e26a75fcad2a3ca12818846f1dccf6b18186b9831480fca75463a8b9ffed481d8e8396b695d39c4fbf3b6b9a1b0848fa1812f7c4bd05cc475fce18c13cb4b8342001fa3f6f42ec9953ca58898131ebc6563141a21433c16f26e15e1702259a2ce7b1ac47c2a059071d0cadc79e8c2ec7cb715884306b9f0bffb7e1cbc25e72756e00a10f693b47788ea8fb1f7a52d163f46f822643ed755c4b184526d35b03843080f4c4d16c7f055b10d8b5823eea49396a0d841e9e8a7f29d6829f42f97d86ff1529b959fa40912d8bc1a6a88efad1dbe69caa61e75115fc83890d1c8ea724211d5328d33874893f6fe3ba9f6818df3d4d3dd77a1c7841ea60e1b643192ff3680bb849b3f5e461f6126ff5ea78249236d552095627400b704a147724ec5f8e6e2c3d18a92c8b706bece73a3c6da19492c6dbb3dd96071d85ea51e159249d4b3c06532d36211837da3165807a537019fec3cc052f50207223549b04aa29d7fd63a307d0acd9a4b00c6c1c2437b248e61b89f689ef562fe744f60df2ef9b521940a1be082f335e99adad40a8f5c5e9074f791e622fcecba5ff85426d1935b785499ed2364b50563c3d4c2a1b77f58931d327d1de98c35f00bd1238b7af15069888d0b452a56e1efb7944c6fa7b4d746c361e9da6e98873743b29b0f0b2eb98af961b536a60456f0048c1502c83eaa5824ddc5fcbd81b1f75a9c356b6c734d80b58448bed7c34e7ff06f65fa7bcda11dfd97a3eb01857f34d66fc2f83ec9f77a2f5e81f80d66a5bca8e8d56edaa99c06fca05fb159d178590ff68dc0eab456223f5f92d24f241cbf47023efc51fc9c104e98f7f9f5ba094cb9b58a6a9e223040b7594068c4abdf16f96882c7e530cc9bd834dcc861fd9915021103579403831f81ebc5823e5f4a8762e13b8fea34b56e240b612e02ec15299331547d32749cc4104c86ae8bc241ecfb4d7509c0a8e691a0856cd7f468ca18162298a1123b685fcef840aa0181aefcc32ca83a2721bd2efea8f96ba53d1938eadb5b922fa473c21d180b4e41a480abcff56e17115d8a5e106216362e0e285704bf291ed8c96b8762f19d515a34c68d620a771c6a8a05f0a8b88d4fa4979ea5fb2787387044d0b30df3ed27fde51f003e76ef091ce33c911490348a11a071966fad8dd5382f537427d865fca922d4557a3a164eca0e7ba9dccf7451afafc669f490ceb33723a7940fe31182b2e0d04f4d7005a1df112c04b6312b8ebd9ff80422df269db5a8973cb5ca0ea0c70d0f769adf207673187b0621a02562185312afe03374d19f97a0c36e1fd8ca091dd53dbb5e500e9c9d2a19d1090e68182c76b80d63f97e28248408a6b4fbb77fc03f355ef191c96b04cf18703bf43d6365d1f640b2f50a6c94318628e936e8d18c3c7469118224381fb29e8602f724ed5c9984d131330c31ed534820df658cd6ac060d8ffdb1590757bad596982ac5e22381e90eec5454e0801b46b362d7bc2d94295956df9ffd8fa55e7fd69bdc621e38b20d82f4e9ba7bb433614fc917316b724e93d59d8066e9305400ec514330a7219dc23c5981512bb3b07602fb8481ef85d78224d56cdbf6c5e7a7dbc2ffa76e61c0c7eb8588328fa459c31d5bc591046ce889c7be129ba79c179a5c28cd2ab6d1495f0b22103383a3535e65d8e095470b6d33086b0139717765a9fdb971224f2d63b4c0b70e11bc6f37e34ba47a8ddc0e26679886d4c48df3c13c6360fec77626e89fd9f9760c96adabf011f9050ad858ad605667f7e591d4866a4c201e4c9a4e6ab870b10cbe2cf127e279b85d50acc55bdfc137b919ca69eb09cdbdc6b865dfbc8fa7eae35c06a6ee048ca4839a85f9c2b8031b80f4e042f60153e210c53aae438306596bd86baf3689daf70c026ad8aec6c6816777a7f67bec2c7f489ae8c642cb1efeb6687ba2c3d28b337d5fe7dc4590271dd3ade5c47a5d9fba1fcaf2d858d52280a52afbb65c1a7a13f04aab41402df74a907338c40e52404869eeb3402814bd6cf7076f60a57197f8e583e365c243a92e9b54b036acba6b4a659b5769c476e3f576582fd5fcc70d82200e6445cb6f7ab6c4fc3688aa91e28dafa2ce034d86aa181c30b35a8e93290a4b1caa3641e580941fe2b900d19e34bf857a7672fe15db9c817e9b73917b42cd83b420b736b7cecd288675ef40cad1645bf7d7fb530e0999730651d5a9884df40d80b6f73c959cf16d0690685af6a2cf4e27affda442054e842c5f31cd6ffe20bf1ad3c3550cbaced0b831af51e5ee48c1b7fec22b51235d38374679fb0d19afa131841f27f5814a4b801030b48b9dbc618e7aeeafd298263c9718f91b8a075d42bc3d877800969c300516f905aba321f8974c80d240df9fe8d55f3ec93e27e88a23b64b516443e60b15f031851714834c625b2898a88b0cab642aa6a850deeab29a28fcd1217581dd002fb4ffc5c8b368986f7e9c67e369e3225e3ed2bbaf9f2b6d3522d8e5dae9556bfff6447b797733111f4d874 j**https://mmi263.whatsapp.net/d/X5lGvQhVridh8JNjJ1cRTlb0UBk/AomynskcHiGNoLNiIC9qfyPYsnDBZGK_CxMYe1aDbZVG.enc** image/jpeg" �Yǧ�g���M�聹ty�p�H�VU��ߨ�(��0� 8�B EV���eT�O4d�}���n��8�����������JFIFHH��**LExifMM�i&�8�d��8Photoshop 3.08BIM8BIM%**���� ���B~�d8"�� ���}!1AQa"q2��#B��R��$3br� %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz��������������������������������������������������������������������������� ���w!1AQaq"2B���� #3R�br� $4�%�&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz��������������������������������������������������������������������������C """"""''''',,,,,,,,,,��C ...................................................���� ?�Z����^;��RH`}�9IA�*��*`�G�Oޭ;��N��+���O��}�<�?֭4|!��m=?֭�^�=�2��7�����/���H�l�-m'�j���s��`���AH�@�<�g�j��3�~fUIaIb6������{���ذ��8�p��Z���}�H��5��"%-�9'���^t�|/�S��:�� Yx��[��3٩���.B�pq� RcH�i�r\��� �9 2��� �v���$0!�$g�_2�7�:ޮ�/� �7��� l/�vc_Q�T�)��ք z��€>��QLG���(�k��]��n��K�J�\j g��R���~�v�~#1���C�A��Xw�C�}�-J{�C��[H�l�r�s��A����O���A��H�$$�ە�q���¡���i0Zi:�\ۨI6c�x �� ���EQ����|ۙ>V=�=j�Y'���}g��Z~�yi2��R���x�R�✐���'-(�ۄ�Gğj���8â�M��U ���ʖ��&愨�#p#�j�T�e��LTg$�d���P�ޟ�\Eu.�Rh[pt� r0A�:��s�=���-��\�,n�n�e�cO5�H&� ��=��Z��rbA����������EN�jQ*f%��G�>����a�����_�zo��No57�� *� _;v{`u��^�^�9d��qy����1����d}U��Z��WwC���]_�> ��.�-n H���Ub����>���Ὴ$M�unGջc�a^�El�IT�l<����g���^*h���1պz}Ξ�5�3��ulv.��PWo����a���p�N�9#��:�_2<��d��o ������xW�֍������#d�Y�sӪ��*@��t���''vw�СJ{������9�`���&?w6����O|9�uu�2m��$ۀ��������������v���Q� ;����?���z(��w�7ff״��䍪y�A��>:� ��Ӏ�q�pZ������{|�u{cԫ��� ;����?���z(���Z�(��(��(��(��� HEX:0a6a68747470733a2f2fmore hex blahblah
payamazadi commented 8 years ago

trying to figure out how to just make this work in the axolotl layer. so far i've changed handleEncMessage to something like this:

def handleEncMessage(self, node):
        try:
            if node.getChild("enc")["v"] == "2" and node["from"] not in self.v2Jids:
                self.v2Jids.append(node["from"])

            if node.getChild("enc")["type"] == "pkmsg":
                self.handlePreKeyWhisperMessage(node)
            elif node.getChild("enc")["type"] == "msg" and node.getChild("enc")["mediatype"] == "image":
                self.handleWhisperMessage(node) #what should this be!?
Dimelay commented 8 years ago

@bdbais not resolve for me:

You use yowsup-cli.py or written by you script ? For yowsup-cli.py edit /yowsup/demos/cli/layer.py @ProtocolEntityCallback("message") Line 513

elif message.getType() == "media":
    pass    
    #messageOut = self.getMediaMessageBody(message)

Now, if I get the picture, my script does not crash and gives the message

[Online ](-->)
protocol_media/layer.py recv image from  7XXXXXXXXX@s.whatsapp.net
[Online ](-->)
payamazadi commented 8 years ago

i'm not trying to just ignore the case when a message is received, i'm actually trying to fix the problem. my use case for this requires the ability to receive images. that's why this issue is a bug..

bdbais commented 8 years ago
    @staticmethod
    def fromProtocolTreeNode(node):
        entity = MessageProtocolEntity.fromProtocolTreeNode(node)
        entity.__class__ = MediaMessageProtocolEntity
        """
        entity.setMediaType(node.getAttributeValue("mediatype"))
        preview = node.getData()
        entity.setPreview(preview)
        """
        return entity
bdbais commented 8 years ago

I'm using a script based on echoclient for receiving media from users, but now I can't use it. Error is already present.

payamazadi commented 8 years ago

yes, you are right, that is what we are trying to fix. don't know how to properly decrypt the media message

Dimelay commented 8 years ago

OK, I got to see a preview of the image. After the function def handleWhisperMessage (self, node) We get the binary data. They can parse. We are looking for the title FF D8 (JPEG Header and get a preview of the image! In the same binary data link to the full image, you just get it and decipher!

payamazadi commented 8 years ago

@Dimelay that sounds like it'd work - can you post the code here?

payamazadi commented 8 years ago

ok, i see what yuo're saying. i'm doing something like this:

def handleWhisperMessage(self, node):
        encMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node)

        whisperMessage = WhisperMessage(serialized=encMessageProtocolEntity.getEncData())
        sessionCipher = self.getSessionCipher(encMessageProtocolEntity.getFrom(False))
        plaintext = sessionCipher.decryptMsg(whisperMessage)

        newFile = open ("kaka.txt", "wb")
        newByteArray = bytearray(plaintext)
        encLocation = str(newByteArray[5:111])

        #download file from encLocation
        #get its binary value, decrypt it, print it
        #
        downloader = MediaDownloader(self.handleEncLocation)
        downloader.download(encLocation)

        #if encMessageProtocolEntity.getVersion() == 2:
        #    plaintext = self.unpadV2Plaintext(plaintext)

        bodyNode = ProtocolTreeNode("body", data = plaintext)

        node.addChild(bodyNode)
        self.toUpper(node)

    def handleEncLocation(self, path):
        outPath = "/tmp/yowfiles/%s.txt" % os.path.basename(path)
        shutil.copyfile(path, outPath)

        theFile = open(outPath, 'rb')
        theBytes = theFile.read()
        #now decrypt theBytes. having trouble getting the recipient ID here
jlguardi commented 8 years ago

@payamazadi @Dimelay I've gotten preview of the image and I've partially ported chatAPI in my branch (https://github.com/jlguardi/yowsup/tree/encrypted_media)

As you can see, it produces still an exception but preview node is correct. I have printed to a file and works.

Now, I'm trying to use protobuf to read all other fields (url is possible without protobuf but we need all other fields to decrypt remote file).

payamazadi commented 8 years ago

@jlguardi are you saying without protobuf the contents of the .enc file that gets downloaded can't be fully decrypted? do you have any idea what the file structure is?..

jlguardi commented 8 years ago

@payamazadi Step by step... I've fully read encrypted message content: url, caption... So I'll decrypt file but I need time/help for that. Use my branch!

payamazadi commented 8 years ago

@jlguardi let me know what i can do to help. if you can point me to where in chat-api i need to look to port, i can help w that

Dimelay commented 8 years ago
      switch ($node->getChild('enc')->getAttribute('mediatype')) {
        case 'image':
          $image = new ImageMessage();
          $image->parseFromString($plaintext);
          $keys = (new HKDFv3())->deriveSecrets($image->getRefKey(), hex2bin('576861747341707020496d616765204b657973'), 112);
          $iv = substr($keys, 0, 16);
          $keys = substr($keys, 16);
          $parts = str_split($keys, 32);
          $key = $parts[0];
          $macKey = $parts[1];
          $refKey = $parts[2];

          //should be changed to nice curl, no extra headers :D
          $file_enc = file_get_contents($image->getUrl());
          //requires mac check , last 10 chars
          $mac = substr($file_enc, -10);
          $cipherImage = substr($file_enc, 0, strlen($file_enc) - 10);
          $decrypted_image = pkcs5_unpad(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $cipherImage, MCRYPT_MODE_CBC, $iv));
          //$save_file = tempnam(sys_get_temp_dir(),"WAIMG_");
          //file_put_contents($save_file,$decrypted_image);
          $child = new ProtocolNode('media',
            [
                'size'     => $image->getLength(),
                'caption'  => $image->getCaption(),
                'url'      => $image->getUrl(),
                'mimetype' => $image->getMimeType(),
                'filehash' => bin2hex($image->getSha256()),
                'width'    => 0,
                'height'   => 0,
                'file'     => $decrypted_image ?: $file_enc,
                'type'     => 'image',
              ], null, $image->getThumbnail());
          $node->addChild($child);```

Chat-API

We need a key:

$keys = (new HKDFv3())->deriveSecrets($image->getRefKey(), hex2bin('576861747341707020496d616765204b657973'), 112); $keys = substr($keys, 16); $parts = str_split($keys, 32); $key = $parts[0]; //KEY!


And decrypt

pkcs5_unpad(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $cipherImage, MCRYPT_MODE_CBC, $iv));



pkcs5_unpad == unpadV2plaintex
jlguardi commented 8 years ago

I'm in file chatAPI "handlers/MessageHandler.php +443" I have up to here.

But last half hour I was working with utf-8/latin-1? exception with captions.

Dimelay commented 8 years ago

$image->getRefKey() <-- where ??? I use the hex editor to find it. To decrypt at least a test file. But this is the wrong decision to search using hexeditor

payamazadi commented 8 years ago

const REFKEY = 8;

pb_wa_messages.php

or did you mean where to put it in the port..

jlguardi commented 8 years ago

I've 'almost' implemented gerRefKey. So I need to continue decrypting but now I'm getting an error while reading with protobuff.

I've pushed my last code.

jlguardi commented 8 years ago

@payamazadi This is the position in the buffer

jlguardi commented 8 years ago

4:35 am! time to sleep! Finally I've some kind of error converting from decrypted but buffered message to an object using protobuf. I get url, mime and caption but seems to fail with sha256. You can try it, it is updated in my fork/encrypted_media. I hope somebody fixes that before wake up time ;)

payamazadi commented 8 years ago

why is the .proto file for sha256 using string? shouldn't it be bytes? https://developers.google.com/protocol-buffers/docs/proto#scalar

payamazadi commented 8 years ago

i switched it to bytes, installed protobuff, and compiled, and now the error is past sha256 and onto refkey.

payamazadi commented 8 years ago

changed refkey to use bytes and now it looks like its working. changed heigh to height and lengt to length, to match with what's being debugged changed IV to iv in .proto to match with what's being debugged

now i get something like this with your existing debug statements: URL: https://mmi447.whatsapp.net/d/cVtP9_0aOCLhA_-zJOYru1b0wes/Ap6sE4raJ1oJp1t1Lq8GVhgcZr2HRaTToA7PHaB-_UOU.enc MIME: image/jpeg CAPTION: SHA: �Yǧ�g���M�聹ty�p�H�VU��ߨ� LENGTH: 123313 HEIGHT: 1600 WIDTH: 900 REFKEY: ��(�������ķ��W��$�[�3LJ�� KEY: THUMB: ----node--

Dimelay commented 8 years ago

Show you code REFKEY its good/

Dimelay commented 8 years ago

type=7 and cpp_type=7 ?

payamazadi commented 8 years ago

i'm not sure yet, i'm about to start decrypting

i am using @jlguardi's encrypted-media branch, so make sure you update to that. from there, the code is almost exactly the same, here's what you need to do to get where i am:

  1. change layers/axolotl/encrypted_media.proto to this:
message Media {
    optional string url       =  1;
    optional string mimetype  =  2;
    optional string caption   =  3;
    optional bytes sha256     =  4;
    optional int32 length      =  5;
    optional int32 height      =  6;
    optional int32 width      =  7;
    optional bytes refkey    =  8;
    optional string key       =  9;
    optional string iv        = 10;
    optional string thumbnail = 11;
}
  1. if you don't already, download and install Protobuf: https://developers.google.com/protocol-buffers/docs/downloads#release-packages . unzip, ./configure, make && make install. then in a terminal, cd into layers/axolotl and run the following command: protoc --python_out=. encrypted_media.proto
payamazadi commented 8 years ago

if it makes it easier, here's the updated encrypted_media_pb2.py file (but still make sure to update the .proto file as above):

# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: encrypted_media.proto

import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
from google.protobuf import descriptor_pb2
# @@protoc_insertion_point(imports)

_sym_db = _symbol_database.Default()

DESCRIPTOR = _descriptor.FileDescriptor(
  name='encrypted_media.proto',
  package='',
  serialized_pb=_b('\n\x15\x65ncrypted_media.proto\"\xb2\x01\n\x05Media\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x10\n\x08mimetype\x18\x02 \x01(\t\x12\x0f\n\x07\x63\x61ption\x18\x03 \x01(\t\x12\x0e\n\x06sha256\x18\x04 \x01(\x0c\x12\x0e\n\x06length\x18\x05 \x01(\x05\x12\x0e\n\x06height\x18\x06 \x01(\x05\x12\r\n\x05width\x18\x07 \x01(\x05\x12\x0e\n\x06refkey\x18\x08 \x01(\x0c\x12\x0b\n\x03key\x18\t \x01(\t\x12\n\n\x02iv\x18\n \x01(\t\x12\x11\n\tthumbnail\x18\x0b \x01(\t')
)
_sym_db.RegisterFileDescriptor(DESCRIPTOR)

_MEDIA = _descriptor.Descriptor(
  name='Media',
  full_name='Media',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='url', full_name='Media.url', index=0,
      number=1, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=_b("").decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='mimetype', full_name='Media.mimetype', index=1,
      number=2, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=_b("").decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='caption', full_name='Media.caption', index=2,
      number=3, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=_b("").decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='sha256', full_name='Media.sha256', index=3,
      number=4, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='length', full_name='Media.length', index=4,
      number=5, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='height', full_name='Media.height', index=5,
      number=6, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='width', full_name='Media.width', index=6,
      number=7, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='refkey', full_name='Media.refkey', index=7,
      number=8, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='key', full_name='Media.key', index=8,
      number=9, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=_b("").decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='iv', full_name='Media.iv', index=9,
      number=10, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=_b("").decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='thumbnail', full_name='Media.thumbnail', index=10,
      number=11, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=_b("").decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=26,
  serialized_end=204,
)

DESCRIPTOR.message_types_by_name['Media'] = _MEDIA

Media = _reflection.GeneratedProtocolMessageType('Media', (_message.Message,), dict(
  DESCRIPTOR = _MEDIA,
  __module__ = 'encrypted_media_pb2'
  # @@protoc_insertion_point(class_scope:Media)
  ))
_sym_db.RegisterMessage(Media)

# @@protoc_insertion_point(module_scope)
payamazadi commented 8 years ago

issued pull request on @jlguardi 's encrypted-media branch https://github.com/jlguardi/yowsup/pull/2

Dimelay commented 8 years ago

I did it!

payamazadi commented 8 years ago

you did!? share the code!!!

Dimelay commented 8 years ago
 def handleWhisperMessage(self, node):
        encMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node)

        whisperMessage = WhisperMessage(serialized=encMessageProtocolEntity.getEncData())
        sessionCipher = self.getSessionCipher(encMessageProtocolEntity.getFrom(False))
        plaintext = sessionCipher.decryptMsg(whisperMessage)

        if encMessageProtocolEntity.getVersion() == 2:
            plaintext = self.unpadV2Plaintext(plaintext)

        media = encrypted_media_pb2.Media()
        media.ParseFromString(plaintext)
        logger.debug("protobuf")
        media = encrypted_media_pb2.Media()
        media.ParseFromString(plaintext)
        print 'read url %s' % media.url
        print("URL: " + media.url)
        print("MIME: " + media.mimetype)
        print("CAPTION: " + media.caption)
        print("SHA: " + media.sha256)
        print("LENGTH: " + str(media.length))
        print("HEIGHT: " + str(media.height))
        print("WIDTH: " + str(media.width))
        print("REFKEY: " + media.refkey)
        print("KEY: " + media.key)
        print("IV: " + media.iv)
        #logger.debug("THUMB: " + media.thumbnail)
        encimg = urllib2.urlopen(media.url).read()
        derivative = HKDFv3().deriveSecrets(media.refkey, binascii.unhexlify('576861747341707020496d616765204b657973'), 112)
        parts = ByteUtil.split(derivative, 16, 32)
        iv = parts[0]
        cipherKey = parts[1]
        e_img = encimg[:-10]
        AES.key_size=128
        cr_obj = AES.new(key=cipherKey,mode=AES.MODE_CBC,IV=iv)
        myimg = cr_obj.decrypt(e_img)
        f=open('/tmp/MY','wb')
        f.write(bytearray(myimg))
        f.close()
        bodyNode = ProtocolTreeNode("body", data = plaintext)
        node.addChild(bodyNode)
        self.toUpper(node)

Image save in /tmp/MY

Dimelay commented 8 years ago

axolotl/layer.py from Crypto.Cipher import AES import urllib2 from axolotl.kdf.hkdfv3 import HKDFv3 from axolotl.util.byteutil import ByteUtil

Dimelay commented 8 years ago

Now we have to generate Protocol TreeNode is simply