From dcd9322cfe177dff1bfc342c09cbac4b39931a0b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 25 Jan 2024 22:23:09 -1000 Subject: [PATCH 1/3] Reduce the number of times we recreate the cipher in klap --- kasa/klaptransport.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/kasa/klaptransport.py b/kasa/klaptransport.py index cd0e3de6..14f47868 100644 --- a/kasa/klaptransport.py +++ b/kasa/klaptransport.py @@ -46,6 +46,7 @@ import datetime import hashlib import logging import secrets +import struct import time from pprint import pformat as pf from typing import Any, Dict, Optional, Tuple, cast @@ -66,6 +67,8 @@ _LOGGER = logging.getLogger(__name__) ONE_DAY_SECONDS = 86400 SESSION_EXPIRE_BUFFER_SECONDS = 60 * 20 +PACK_SIGNED_LONG = struct.Struct(">l").pack + def _sha256(payload: bytes) -> bytes: digest = hashes.Hash(hashes.SHA256()) # noqa: S303 @@ -432,6 +435,8 @@ class KlapEncryptionSession: self.user_hash = user_hash self._key = self._key_derive(local_seed, remote_seed, user_hash) (self._iv, self._seq) = self._iv_derive(local_seed, remote_seed, user_hash) + self._aes = algorithms.AES(self._key) + self._generate_cipher() self._sig = self._sig_derive(local_seed, remote_seed, user_hash) def _key_derive(self, local_seed, remote_seed, user_hash): @@ -451,19 +456,20 @@ class KlapEncryptionSession: payload = b"ldk" + local_seed + remote_seed + user_hash return hashlib.sha256(payload).digest()[:28] - def _iv_seq(self): - seq = self._seq.to_bytes(4, "big", signed=True) - iv = self._iv + seq - return iv + def _generate_cipher(self): + iv_seq = self._iv + PACK_SIGNED_LONG(self._seq) + cbc = modes.CBC(iv_seq) + self._cipher = Cipher(self._aes, cbc) def encrypt(self, msg): """Encrypt the data and increment the sequence number.""" - self._seq = self._seq + 1 + self._seq += 1 + self._generate_cipher() + if isinstance(msg, str): msg = msg.encode("utf-8") - cipher = Cipher(algorithms.AES(self._key), modes.CBC(self._iv_seq())) - encryptor = cipher.encryptor() + encryptor = self._cipher.encryptor() padder = padding.PKCS7(128).padder() padded_data = padder.update(msg) + padder.finalize() ciphertext = encryptor.update(padded_data) + encryptor.finalize() @@ -478,8 +484,7 @@ class KlapEncryptionSession: def decrypt(self, msg): """Decrypt the data.""" - cipher = Cipher(algorithms.AES(self._key), modes.CBC(self._iv_seq())) - decryptor = cipher.decryptor() + decryptor = self._cipher.decryptor() dp = decryptor.update(msg[32:]) + decryptor.finalize() unpadder = padding.PKCS7(128).unpadder() plaintextbytes = unpadder.update(dp) + unpadder.finalize() From 26d1fcf208496db87c9127f2d16b1ff6f476b6db Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 26 Jan 2024 06:24:58 -1000 Subject: [PATCH 2/3] no need to do in init --- kasa/klaptransport.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kasa/klaptransport.py b/kasa/klaptransport.py index 6df45948..e6d5b188 100644 --- a/kasa/klaptransport.py +++ b/kasa/klaptransport.py @@ -436,7 +436,6 @@ class KlapEncryptionSession: self._key = self._key_derive(local_seed, remote_seed, user_hash) (self._iv, self._seq) = self._iv_derive(local_seed, remote_seed, user_hash) self._aes = algorithms.AES(self._key) - self._generate_cipher() self._sig = self._sig_derive(local_seed, remote_seed, user_hash) def _key_derive(self, local_seed, remote_seed, user_hash): @@ -474,7 +473,7 @@ class KlapEncryptionSession: padded_data = padder.update(msg) + padder.finalize() ciphertext = encryptor.update(padded_data) + encryptor.finalize() signature = hashlib.sha256( - self._sig + self._seq.to_bytes(4, "big", signed=True) + ciphertext + self._sig + PACK_SIGNED_LONG(self._seq) + ciphertext ).digest() return (signature + ciphertext, self._seq) From db1e3b21459f0a6ab883a5bb8dc15456e6532f1f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 26 Jan 2024 06:32:10 -1000 Subject: [PATCH 3/3] no need to do in init --- kasa/klaptransport.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kasa/klaptransport.py b/kasa/klaptransport.py index e6d5b188..2885c327 100644 --- a/kasa/klaptransport.py +++ b/kasa/klaptransport.py @@ -429,6 +429,8 @@ class KlapEncryptionSession: i.e. sequence number which the device expects to increment. """ + _cipher: Cipher + def __init__(self, local_seed, remote_seed, user_hash): self.local_seed = local_seed self.remote_seed = remote_seed