hiveeyes / terkin-datalogger

Datalogger for MicroPython and CPython.
https://terkin.org
GNU Affero General Public License v3.0
59 stars 28 forks source link

CPython/Dragino: LoRaWAN implementation croaks with PyCryptodome #108

Open amotl opened 2 years ago

amotl commented 2 years ago

Hi there,

@tonke reported that the Dragino LoRaWAN implementation [1] croaks when using PyCryptodome, the successor library to PyCrypto.

>>> from Crypto.Cipher import AES
>>> AES.new(b"foobar")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: new() missing 1 required positional argument: 'mode'

Thank you!

Background: We switched to this library because it offers an almost drop-in replacement for the old PyCrypto library [2,3,4], which does not receive updates and is told to have some security flaws. See also #99 and #101.

With kind regards, Andreas.

[1] https://github.com/daq-tools/dragino/tree/terkin/dragino/LoRaWAN [2] https://www.dlitz.net/software/pycrypto/ [3] https://pypi.org/project/pycrypto/ [4] https://github.com/pycrypto/pycrypto

amotl commented 2 years ago

Indeed, the Compatibility with PyCrypto page is explicit about this detail:

For symmetric key cryptography:

Symmetric ciphers do not have ECB as default mode anymore. ECB is not semantically secure and it exposes correlation across blocks. An expression like AES.new(key) will now fail. If ECB is the desired mode, one has to explicitly use AES.new(key, AES.MODE_ECB).

However, the Dragino LoRaWAN library uses the variant without explicitly telling the mode, for example within decrypt_payload() and encrypt_payload(), but also at a few more other places:

dragino$ ag "AES\.new"

LoRaWAN/JoinAcceptPayload.py
59:        cipher = AES.new(bytes(key))
78:        cipher = AES.new(bytes(key))
88:        cipher = AES.new(bytes(key))
98:        cipher = AES.new(bytes(key))

LoRaWAN/AES_CMAC.py
6:        AES_128 = AES.new(K)
45:        AES_128= AES.new(K)

LoRaWAN/DataPayload.py
59:        cipher = AES.new(bytes(key))
87:        cipher = AES.new(bytes(key))
amotl commented 2 years ago

cf33021 temporarily reverts to the PyCrypto library.