Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 33 additions & 7 deletions kasa/smartcam/smartcamdevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

import base64
import hashlib
import logging
from typing import Any, cast

Expand Down Expand Up @@ -63,6 +64,15 @@

return DeviceType.Camera

def _pubkey_encrypt(self, plaintext: str) -> str:
public_key_b64 = self._public_key or self.STATIC_PUBLIC_KEY_B64
key_bytes = base64.b64decode(public_key_b64)
public_key = serialization.load_der_public_key(key_bytes)
if not isinstance(public_key, RSAPublicKey):
raise TypeError("Loaded public key is not an RSA public key")
ciphertext_bytes = public_key.encrypt(plaintext.encode(), padding.PKCS1v15())
return base64.b64encode(ciphertext_bytes).decode()

@staticmethod
def _get_device_info(
info: dict[str, Any], discovery_info: dict[str, Any] | None
Expand Down Expand Up @@ -357,13 +367,7 @@
if net is None:
raise DeviceError(f"Network with SSID '{ssid}' not found.")

public_key_b64 = self._public_key or self.STATIC_PUBLIC_KEY_B64
key_bytes = base64.b64decode(public_key_b64)
public_key = serialization.load_der_public_key(key_bytes)
if not isinstance(public_key, RSAPublicKey):
raise TypeError("Loaded public key is not an RSA public key")
encrypted = public_key.encrypt(password.encode(), padding.PKCS1v15())
encrypted_password = base64.b64encode(encrypted).decode()
encrypted_password = self._pubkey_encrypt(password)

payload = {
"onboarding": {
Expand All @@ -390,3 +394,25 @@
"Received a kasa exception for wifi join, but this is expected"
)
return {}

async def update_credentials(self, username: str, password: str) -> dict:
cur_pass = self.credentials.password if self.credentials.password else self.protocol._transport._default_credentials.password
cur_pass_hash = hashlib.sha256(cur_pass.encode()).hexdigest().upper()

Check failure

Code scanning / CodeQL

Use of a broken or weak cryptographic hashing algorithm on sensitive data High

Sensitive data (password)
is used in a hashing algorithm (SHA256) that is insecure for password hashing, since it is not a computationally expensive hash function.
Sensitive data (password)
is used in a hashing algorithm (SHA256) that is insecure for password hashing, since it is not a computationally expensive hash function.
new_pass_hash = hashlib.sha256(password.encode()).hexdigest().upper()

Check failure

Code scanning / CodeQL

Use of a broken or weak cryptographic hashing algorithm on sensitive data High

Sensitive data (password)
is used in a hashing algorithm (SHA256) that is insecure for password hashing, since it is not a computationally expensive hash function.

encrypted_password = self._pubkey_encrypt(password)

payload = {
"user_management": {
"change_admin_password": {
"encrypt_type": "3",
"secname": "root",
"passwd": new_pass_hash,
"old_passwd": cur_pass_hash,
"ciphertext": encrypted_password,
"username": "admin"
}
}
}

return await self.protocol.query({"changeAdminPassword": payload})
Loading