Repository navigation
Sign requests for firmware that requires it - #216
Open
ThomasMcCrossin wants to merge 1 commit into
Open
ThomasMcCrossin wants to merge 1 commit into
ThomasMcCrossin wants to merge 1 commit into
Conversation
Newer firmware tags replies with "env":"pro" and an hmac. Reads still work unsigned, but setPilot without a signature fails with -32602 and a wrong signature fails with -32605. wizlight() takes an optional signing_key, the udp_signing_key from the WiZ app's local integration export. When set, send() adds sigTs to params and signs the compact params JSON with HMAC-SHA256. Tested against an ESP25_SHORGB_01 strip on 1.39.0. Fixes sbidy#213 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
0x416d616e
pushed a commit
to 0x416d616e/core
that referenced
this pull request
Oct 11, 2026
Newer WiZ firmware can be set to only accept verified controls, which makes it reject unsigned setPilot commands (-32602). Commands then need to be signed with the home security key from the WiZ app. Store an optional signing key in the config entry and pass it to pywizlight, which signs every request when it is set. Without a key, commands stay unsigned, which works for homes that allow all controls. The key can be entered when setting up a device manually, and changed or removed with a new reconfigure step. It is redacted from diagnostics. The user step is now a menu that also offers importing the local integration file exported from the WiZ app (format version 1.0). The import adds the key to the configured devices listed in the file, and starts discovery flows carrying the key and the WiZ app name for listed devices that are not set up yet. This replaces pending discovery flows without the key, including those of devices the network scan misses. Device entries without a usable MAC address are skipped. Entries updated by discovery or the manual step are reloaded by their update listener when loaded, and reloaded right away otherwise. Requires pywizlight with signing support (sbidy/pywizlight#216), which is not released yet; the requirement still needs to be bumped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #213.
Newer WiZ firmware answers with
"env":"pro"and anhmacon every reply. Reads still work unsigned, but anysetPilotwithout a signature comes back as-32602 Invalid params, and a bad signature gets-32605 Security error. My ESP25_SHORGB_01 strip moved from 1.31.0 to 1.39.0 the day I set it up and has behaved this way on both versions.The key lives in the WiZ app. It can export your home for local integration, and that JSON has a
udp_signing_key(32 hex characters, one per home). Requests are signed by addingsigTs(unix seconds) toparamsand then sending"env":"pro"plushmac, which is base64 HMAC-SHA256 of the compactparamsJSON keyed with the hex-decoded key. Replies are signed the same way over theresult/errorobject. I confirmed the scheme on 10 captured replies before sending any writes.This PR adds:
signing_keyonwizlight(), which makessend()sign every requestutils.sign_request()tests/test_signing.pywith a known-answer test and a small fake bulb that rejects unsigned and wrongly signed writes like the real device doesWithout a key nothing changes, so older bulbs are unaffected.
On the real strip,
turn_onwithrgb,turn_offandcolortempall work with the key and fail with -32602 without it. The full suite passes (94 tests), and mypy and black are clean.Some device behaviour worth knowing for Home Assistant:
sigTs30 seconds old is accepted and 60 seconds old is rejected. Future timestamps and replays were both accepted.{"state": true}on its own can return success without changing the light. A colour or temp in the same call clears the scene.registrationstill works unsigned, so push updates are fine.Home Assistant would need a place to enter the key in the WiZ config flow. I can follow up there once this is released.
🤖 Generated with Claude Code