mirror of
https://github.com/mjg59/python-broadlink.git
synced 2024-11-22 15:10:12 +01:00
Use cryptography instead of pycryptodome (#246)
* Use cryptography instad of pycryptodome * Use cryptography instad of pycryptodome
This commit is contained in:
parent
45e26fda23
commit
38a40c5a19
@ -1,17 +1,17 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
from datetime import datetime
|
import codecs
|
||||||
|
|
||||||
try:
|
|
||||||
from Crypto.Cipher import AES
|
|
||||||
except ImportError as e:
|
|
||||||
import pyaes
|
|
||||||
|
|
||||||
import time
|
|
||||||
import random
|
import random
|
||||||
import socket
|
import socket
|
||||||
import threading
|
import threading
|
||||||
import codecs
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
try:
|
||||||
|
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||||
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
except ImportError:
|
||||||
|
import pyaes
|
||||||
|
|
||||||
|
|
||||||
def gendevice(devtype, host, mac):
|
def gendevice(devtype, host, mac):
|
||||||
@ -55,10 +55,10 @@ def gendevice(devtype, host, mac):
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Look for the class associated to devtype in devices
|
# Look for the class associated to devtype in devices
|
||||||
[deviceClass] = [dev for dev in devices if devtype in devices[dev]] or [None]
|
[device_class] = [dev for dev in devices if devtype in devices[dev]] or [None]
|
||||||
if deviceClass is None:
|
if device_class is None:
|
||||||
return device(host=host, mac=mac, devtype=devtype)
|
return device(host=host, mac=mac, devtype=devtype)
|
||||||
return deviceClass(host=host, mac=mac, devtype=devtype)
|
return device_class(host=host, mac=mac, devtype=devtype)
|
||||||
|
|
||||||
|
|
||||||
def discover(timeout=None, local_ip_address=None):
|
def discover(timeout=None, local_ip_address=None):
|
||||||
@ -145,8 +145,6 @@ class device:
|
|||||||
self.devtype = devtype
|
self.devtype = devtype
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self.count = random.randrange(0xffff)
|
self.count = random.randrange(0xffff)
|
||||||
self.key = bytearray(
|
|
||||||
[0x09, 0x76, 0x28, 0x34, 0x3f, 0xe9, 0x9e, 0x23, 0x76, 0x5c, 0x15, 0x13, 0xac, 0xcf, 0x8b, 0x02])
|
|
||||||
self.iv = bytearray(
|
self.iv = bytearray(
|
||||||
[0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28, 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58])
|
[0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28, 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58])
|
||||||
self.id = bytearray([0, 0, 0, 0])
|
self.id = bytearray([0, 0, 0, 0])
|
||||||
@ -160,25 +158,38 @@ class device:
|
|||||||
if 'pyaes' in globals():
|
if 'pyaes' in globals():
|
||||||
self.encrypt = self.encrypt_pyaes
|
self.encrypt = self.encrypt_pyaes
|
||||||
self.decrypt = self.decrypt_pyaes
|
self.decrypt = self.decrypt_pyaes
|
||||||
|
self.update_aes = self.update_aes_pyaes
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.encrypt = self.encrypt_pycrypto
|
self.encrypt = self.encrypt_crypto
|
||||||
self.decrypt = self.decrypt_pycrypto
|
self.decrypt = self.decrypt_crypto
|
||||||
|
self.update_aes = self.update_aes_crypto
|
||||||
|
|
||||||
|
self.aes = None
|
||||||
|
key = bytearray(
|
||||||
|
[0x09, 0x76, 0x28, 0x34, 0x3f, 0xe9, 0x9e, 0x23, 0x76, 0x5c, 0x15, 0x13, 0xac, 0xcf, 0x8b, 0x02])
|
||||||
|
self.update_aes(key)
|
||||||
|
|
||||||
|
def update_aes_pyaes(self, key):
|
||||||
|
self.aes = pyaes.AESModeOfOperationCBC(key, iv=bytes(self.iv))
|
||||||
|
|
||||||
def encrypt_pyaes(self, payload):
|
def encrypt_pyaes(self, payload):
|
||||||
aes = pyaes.AESModeOfOperationCBC(self.key, iv=bytes(self.iv))
|
return b"".join([self.aes.encrypt(bytes(payload[i:i + 16])) for i in range(0, len(payload), 16)])
|
||||||
return b"".join([aes.encrypt(bytes(payload[i:i + 16])) for i in range(0, len(payload), 16)])
|
|
||||||
|
|
||||||
def decrypt_pyaes(self, payload):
|
def decrypt_pyaes(self, payload):
|
||||||
aes = pyaes.AESModeOfOperationCBC(self.key, iv=bytes(self.iv))
|
return b"".join([self.aes.decrypt(bytes(payload[i:i + 16])) for i in range(0, len(payload), 16)])
|
||||||
return b"".join([aes.decrypt(bytes(payload[i:i + 16])) for i in range(0, len(payload), 16)])
|
|
||||||
|
|
||||||
def encrypt_pycrypto(self, payload):
|
def update_aes_crypto(self, key):
|
||||||
aes = AES.new(bytes(self.key), AES.MODE_CBC, bytes(self.iv))
|
self.aes = Cipher(algorithms.AES(key), modes.CBC(self.iv),
|
||||||
return aes.encrypt(bytes(payload))
|
backend=default_backend())
|
||||||
|
|
||||||
def decrypt_pycrypto(self, payload):
|
def encrypt_crypto(self, payload):
|
||||||
aes = AES.new(bytes(self.key), AES.MODE_CBC, bytes(self.iv))
|
encryptor = self.aes.encryptor()
|
||||||
return aes.decrypt(bytes(payload))
|
return encryptor.update(payload) + encryptor.finalize()
|
||||||
|
|
||||||
|
def decrypt_crypto(self, payload):
|
||||||
|
decryptor = self.aes.decryptor()
|
||||||
|
return decryptor.update(payload) + decryptor.finalize()
|
||||||
|
|
||||||
def auth(self):
|
def auth(self):
|
||||||
payload = bytearray(0x50)
|
payload = bytearray(0x50)
|
||||||
@ -219,7 +230,7 @@ class device:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
self.id = payload[0x00:0x04]
|
self.id = payload[0x00:0x04]
|
||||||
self.key = key
|
self.update_aes(key)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -278,7 +289,7 @@ class device:
|
|||||||
packet[0x20] = checksum & 0xff
|
packet[0x20] = checksum & 0xff
|
||||||
packet[0x21] = checksum >> 8
|
packet[0x21] = checksum >> 8
|
||||||
|
|
||||||
starttime = time.time()
|
start_time = time.time()
|
||||||
with self.lock:
|
with self.lock:
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
@ -287,7 +298,7 @@ class device:
|
|||||||
response = self.cs.recvfrom(2048)
|
response = self.cs.recvfrom(2048)
|
||||||
break
|
break
|
||||||
except socket.timeout:
|
except socket.timeout:
|
||||||
if (time.time() - starttime) > self.timeout:
|
if (time.time() - start_time) > self.timeout:
|
||||||
raise
|
raise
|
||||||
return bytearray(response[0])
|
return bytearray(response[0])
|
||||||
|
|
||||||
@ -702,7 +713,6 @@ class hysen(device):
|
|||||||
# The sensor command is currently experimental
|
# The sensor command is currently experimental
|
||||||
def set_mode(self, auto_mode, loop_mode, sensor=0):
|
def set_mode(self, auto_mode, loop_mode, sensor=0):
|
||||||
mode_byte = ((loop_mode + 1) << 4) + auto_mode
|
mode_byte = ((loop_mode + 1) << 4) + auto_mode
|
||||||
# print 'Mode byte: 0x'+ format(mode_byte, '02x')
|
|
||||||
self.send_request(bytearray([0x01, 0x06, 0x00, 0x02, mode_byte, sensor]))
|
self.send_request(bytearray([0x01, 0x06, 0x00, 0x02, mode_byte, sensor]))
|
||||||
|
|
||||||
# Advanced settings
|
# Advanced settings
|
||||||
@ -787,8 +797,8 @@ class S1C(device):
|
|||||||
Its VERY VERY VERY DIRTY IMPLEMENTATION of S1C
|
Its VERY VERY VERY DIRTY IMPLEMENTATION of S1C
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *a, **kw):
|
def __init__(self, host, mac, devtype):
|
||||||
device.__init__(self, *a, **kw)
|
device.__init__(self, host, mac, devtype)
|
||||||
self.type = 'S1C'
|
self.type = 'S1C'
|
||||||
|
|
||||||
def get_sensors_status(self):
|
def get_sensors_status(self):
|
||||||
@ -798,9 +808,8 @@ class S1C(device):
|
|||||||
err = response[0x22] | (response[0x23] << 8)
|
err = response[0x22] | (response[0x23] << 8)
|
||||||
if err != 0:
|
if err != 0:
|
||||||
return None
|
return None
|
||||||
aes = AES.new(bytes(self.key), AES.MODE_CBC, bytes(self.iv))
|
|
||||||
|
|
||||||
payload = aes.decrypt(bytes(response[0x38:]))
|
payload = self.decrypt(bytes(response[0x38:]))
|
||||||
if not payload:
|
if not payload:
|
||||||
return None
|
return None
|
||||||
count = payload[0x4]
|
count = payload[0x4]
|
||||||
|
@ -1 +1 @@
|
|||||||
pycryptodome==3.6.6
|
cryptography==2.6.1
|
||||||
|
9
setup.py
9
setup.py
@ -2,15 +2,16 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from setuptools import setup, find_packages
|
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pyaes
|
import cryptography
|
||||||
|
dynamic_requires = ['cryptography>=2.1.1']
|
||||||
|
except ImportError:
|
||||||
dynamic_requires = ["pyaes==1.6.0"]
|
dynamic_requires = ["pyaes==1.6.0"]
|
||||||
except ImportError as e:
|
|
||||||
dynamic_requires = ['pycryptodome==3.6.6']
|
|
||||||
|
|
||||||
# For Hysen thermostatic heating controller
|
# For Hysen thermostatic heating controller
|
||||||
dynamic_requires.append('PyCRC')
|
dynamic_requires.append('PyCRC')
|
||||||
|
Loading…
Reference in New Issue
Block a user