fix: use KLAP v2 transport for IOT devices with login version 2 - #1731
fix: use KLAP v2 transport for IOT devices with login version 2#1731bm1549 wants to merge 1 commit into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1731 +/- ##
==========================================
+ Coverage 93.29% 93.30% +0.01%
==========================================
Files 157 157
Lines 9932 9934 +2
Branches 1022 1023 +1
==========================================
+ Hits 9266 9269 +3
Misses 471 471
+ Partials 195 194 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
e5fd5d7 to
168336b
Compare
Some IOT-family devices (e.g. the EP10 plug and HS300 strip) keep the legacy IOT command set after a firmware update but upgrade their KLAP authentication to login version 2 (sha256 hashing). The device factory mapped every IOT.KLAP device to the v1 KlapTransport (md5 hashing), so the handshake response never matched and authentication failed with "Device response did not match our challenge". Select KlapTransportV2 for IOT.KLAP devices that advertise login version >= 2, matching the transport already used for SMART.KLAP. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
168336b to
ff11447
Compare
|
Thanks for tracking this down and helping to figure out what is going on. I can confirm the underlying "IOT.KLAP hardcoded to v1" bug is real and matches what I'm seeing on two HS103(US) units, HW Ver 5.0. However, I don't think login_version alone is sufficient to pick the right transport, and this patch as written would regress previously-working devices. Here's the evidence: Device A — HS103(US), HW 5.0, freshly factory-reset and re-paired today (post Android Kasa app update): Fails against stock 0.10.2 (KlapTransport/v1/md5) with the "did not match our challenge" error. Succeeds once patched to force KlapTransportV2 — matches your PR's finding exactly. Device B — same model/hardware/firmware generation (HS103(US), HW 5.0), same TP-Link account, paired months ago, working correctly against stock 0.10.2 (KlapTransport/v1/md5) until today: Identical new_klap/lv values to Device A. After applying this patch (forcing KlapTransportV2 for any IOT.KLAP + lv >= 2), Device B now fails authentication with the same error — it needs the old v1/md5 transport, not v2. So both devices advertise the same discovery-time capability flags, but apparently have different actual stored credential hashes on-device (presumably determined by whichever app/firmware version was used at the time each device was originally paired, not by current firmware capability). Discovery doesn't expose anything that distinguishes them (Device B has a real owner hash, Device A didn't until re-pairing), but I don't know if that's the case always or just coincidental to my specific case. Given that, a static login_version-based rule can't safely choose the transport for both cases because it always breaks one class of device or the other. What about trying the try_connect_all() brute-force approach mentioned in the original analysis (trying both v1 and v2 and using whichever succeeds), rather than a single discovery-time decision? I'm now annoyingly stuck with one new device happily working with the patched version, or the original one working with the stock code. Both bought and shipped in same 2-pack box! :) So silly. |
|
BTW - I removed the Device B (originally paired months ago) which had failed with patch in place using KASA App. I then re-added the device via Kasa App and the patched version now works correctly. So now both Device A and B are working with your patched version. Seems the time the device is initialized plays a role in compatibility with the protocol/authentication changes. |
|
Confirmed this fixes the handshake on two HS300(US) hw2.0 units (fw 1.1.2 Build 241220, Heads up that multi outlet strips need a second fix on top of this one: with the V2 transport Details and a verified local fix here: #1604 (comment) Not asking you to widen this PR. I'm just flagging so it doesn't look unfixed for strip owners |
|
Confirming this fixes HS103(US) hw 5.0 on firmware 1.1.3 Build 250908 Rel.112508. Before (stock python-kasa, via Home Assistant 2026.8.1) Both plugs stopped working immediately after a firmware update offered by the Kasa Device response did not match our challenge on ip 192.168.4.52, The credentials were correct. Deleting and re-adding the integration, The coordinator error before the entries were removed is a useful signature, since Unable to connect to the device: 192.168.4.52:9999: Unauthenticated discovery already reports the deciding field, so this needs no 192.168.4.52 IotSmartPlugSwitch Klap login_version = 2 After (this PR’s head) Installed with: pip install "git+https://github.com/python-kasa/python-kasa.git@refs/pull/1731/head" XXX1 HS103 hw5.0 sw 1.1.3 Build 250908 Klap lv=2 KlapTransportV2 OK The third line is a control on the same model at an older hardware revision and Scope of this report Two single-outlet plugs only. This does not exercise the multi-outlet strip |
Summary
Some IOT-family devices keep the legacy IOT command set after a firmware
update but upgrade their KLAP authentication to login version 2 (sha256
hashing).
get_protocolmaps everyIOT.KLAPdevice to the v1KlapTransport(md5 hashing), so the handshake response never matches andauthentication fails with:
This affects at least the EP10 plug and the HS300 power strip once their
firmware advertises
login_version: 2.Fix
Select
KlapTransportV2forIOT.KLAPdevices that advertiselogin_version >= 2, matching the transport already used forSMART.KLAP.Devices with login version 1 (or unset) are unchanged and continue to use the
v1
KlapTransport.Testing
Verified against a real EP10(US) smart plug running firmware
1.1.1 Build 250908, which advertises
IOT.SMARTPLUGSWITCH/KLAP/login_version: 2in its discovery result:IotProtocol+KlapTransport(v1/md5) → handshake fails withthe "did not match our challenge" error.
KlapTransportV2(v2/sha256): the same credentials authenticateand a full
update()returns validget_sysinfostate.get_protocol()selectsKlapTransportV2for thisdevice and
update()succeeds end to end.Added a
test_get_protocolparametrization (iot-klap-v2) asserting thatIOT.KLAPwithlogin_version=2resolves toIotProtocol+KlapTransportV2, while the existing login-version-1 case still resolves toKlapTransport. Fulltest_get_protocolsuite passes;ruff checkandruff formatare clean.Fixes home-assistant/core#177207