From b2073150ac359300b9353cb1b3b985754c77212d Mon Sep 17 00:00:00 2001 From: Scott Gasch Date: Wed, 23 Feb 2022 14:40:50 -0800 Subject: [PATCH 1/1] Move encrypt and decrypt routines into tplink_utils. --- smart_home/tplink_utils.py | 64 +++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/smart_home/tplink_utils.py b/smart_home/tplink_utils.py index 91cdd75..d8a75a2 100644 --- a/smart_home/tplink_utils.py +++ b/smart_home/tplink_utils.py @@ -1,6 +1,25 @@ #!/usr/bin/env python3 -"""Wrapper functions for calling tplink.py""" +"""Wrapper functions for dealing with TPLink devices. Based on code +written by Lubomir Stroetmann and Copyright 2016 softScheck GmbH which +was covered by the Apache 2.0 license: + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Modifications by Scott Gasch Copyright 2020-2022 also released under +the Apache 2.0 license as required by the license (see above). + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +""" import json import logging @@ -8,6 +27,7 @@ import os import re import subprocess import sys +from struct import pack from typing import Dict, Optional import logging_utils @@ -51,3 +71,45 @@ def tplink_get_info(cmd: str) -> Optional[Dict]: logger.exception(e) print(out, file=sys.stderr) return None + + +def encrypt(string: str) -> bytes: + """Encryption and Decryption of TP-Link Smart Home Protocol. + + XOR Autokey Cipher with starting key = 171 + + >>> " ".join(hex(b).replace('0x', '') for b in encrypt('{"system":{"get_sysinfo":{}}}')) + '0 0 0 1d d0 f2 81 f8 8b ff 9a f7 d5 ef 94 b6 d1 b4 c0 9f ec 95 e6 8f e1 87 e8 ca f0 8b f6 8b f6' + + """ + key = 171 + result = pack(">I", len(string)) + for i in string: + a = key ^ ord(i) + key = a + result += bytes([a]) + return result + + +def decrypt(string: bytes) -> str: + """Opposite of encrypt (above). + + >>> b = encrypt('hi, mom') + >>> s = decrypt(b[4:]) + >>> s + 'hi, mom' + + """ + key = 171 + result = "" + for i in string: + a = key ^ i + key = i + result += chr(a) + return result + + +if __name__ == '__main__': + import doctest + + doctest.testmod() -- 2.45.2