jasonacox / tinytuya

Python API for Tuya WiFi smart devices using a direct local area network (LAN) connection or the cloud (TuyaCloud API).
MIT License
868 stars 157 forks source link

Crypto lib changes and misc fixes #423

Closed uzlonewolf closed 7 months ago

uzlonewolf commented 7 months ago

This PR reworks AESCipher() to make it a bit easier to add additional crypto libraries. It also adds pyca/cryptography ( https://cryptography.io/en/latest/ ) which uses OpenSSL under the hood. pyca/cryptography is preferred at runtime and in setup.py, but PyCryptodome is still preferred in requirements.txt.

An issue with tinytuya.find_device() for v3.1 devices has also been fixed, as has the infinite loop in Contrib/IRRemoteControlDevice.py (Closes #403).

uzlonewolf commented 7 months ago

The crypto library it's using as also been added to the set_debug() message:

import tinytuya
tinytuya.set_debug()

result in:

DEBUG:TinyTuya [1.12.11]

DEBUG:Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
DEBUG:Using pyca/cryptography 38.0.4 for crypto, GCM is supported

or

DEBUG:TinyTuya [1.12.11]

DEBUG:Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
DEBUG:Using PyCryptodomex 3.11.0 for crypto, GCM is supported

or

DEBUG:TinyTuya [1.12.11]

DEBUG:Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
DEBUG:Using pyaes 1.3.0 for crypto
DEBUG:Warning: Crypto library does not support AES-GCM, v3.5 devices will not work!

or

DEBUG:TinyTuya [1.12.11]

DEBUG:Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
DEBUG:Using PyCrypto 2.x.y for crypto
DEBUG:Warning: Crypto library does not support AES-GCM, v3.5 devices will not work!
jasonacox commented 7 months ago

I'm going to test on a few more systems (Win11 and RPi). Any other updates you are thinking about before we merge?

uzlonewolf commented 7 months ago

I'm sure I'll think of one 5 seconds after it's merged... But right now I think I'm done :)

uzlonewolf commented 7 months ago

Ugh, I broke v3.5 devices, one moment...

uzlonewolf commented 7 months ago

And that should fix it. Should be good to merge!

uzlonewolf commented 7 months ago

One of these days I'll polish up my "fake v3.5 device" script and add it to tools/. Not going to be for this PR though.

jasonacox commented 7 months ago

✅ MacOS ✅ Linux ✅ RPi ✅ Win11 - One traceback run but not fatal

During one snapshot scan test, Win11 is producing some errors but still worked and occasionally occurs in v1.12.11 as well.

DEBUG:TinyTuya [1.13.0]

DEBUG:Python 3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)] on win32
DEBUG:Using PyCryptodome 3.12.0 for crypto, GCM is supported
TinyTuya [1.13.0]

...
Traceback (most recent call last):
  File "C:\Users\jason\tinytuya\tinytuya\scanner.py", line 802, in write_data
    self.sock.sendall( self.device._encode_message( self.device.generate_payload(tinytuya.DP_QUERY) ) )
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host

I also tested pyca/cryptography on Win11 - successfully:

DEBUG:TinyTuya [1.13.0]

DEBUG:Python 3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)] on win32
DEBUG:Using pyca/cryptography 41.0.5 for crypto, GCM is supported
TinyTuya [1.13.0]
jasonacox commented 7 months ago

Python version warning for cryptography (Python 3.6 support):

CryptographyDeprecationWarning: Python 3.6 is no longer supported by the Python core team. Therefore, support for it is deprecated in cryptography. The next release of cryptography will remove support for Python 3.6.
  from cryptography.hazmat.primitives.ciphers import Cipher as Crypto
jasonacox commented 7 months ago

Issue I just discovered... on an Linux box using Python 3.7, the pyca/cryptography library of v3.0 or less will NOT work, so you will see something like this with scans:

Upgrading to cryptography>=3.1 fixes this (anything below that is broken).

We should push a patch to include that in the requirements.

uzlonewolf commented 7 months ago

Looking at the backtrace it looks like <=3.0 require a backend= argument that was removed for 3.1 https://cryptography.io/en/latest/faq/#what-happened-to-the-backend-argument . In addition to the requirements.txt update I also added some logic to the import routine to fallback to PyCryptodome if cryptography is <=3.0. https://github.com/jasonacox/tinytuya/commit/7d94c8001901a0c8f16d835fa8bb32e6b8ac74d5 . I'll submit a PR once I finish adding my fake v3.5 device script.

jasonacox commented 7 months ago

I like it! Thanks @uzlonewolf