Related to #37 but a distinct bug, only visible once #37’s padding fix (or an
equivalent) is applied.
Environment: Python 3.14, firebase-messaging @ main
(dc5acc3), Home Assistant 2026.4.2,
ring-doorbell 0.9.x, Ring Intercom.
What I saw: after locally patching _decrypt_raw_data to pad crypto_key_str/salt_str before decoding (same fix as #37), the padding crash went away, but the listener started dying instead with:
ERROR [firebase_messaging.fcmpushclient] Unknown error: Invalid EC key., shutting down FcmPushClient.
File ".../fcmpushclient.py", line ..., in _handle_data_message
File ".../fcmpushclient.py", line ..., in _decrypt_raw_data
File ".../http_ece/init.py", line ..., in derive_dh
pubkey = ec.EllipticCurvePublicKey.from_encoded_point(ec.SECP256R1(), dh)
ValueError: Invalid EC key.
Root cause: _handle_data_message does:
crypto_key = self._app_data_by_key(msg, "crypto-key")[3:] # strip dh=salt = self._app_data_by_key(msg, "encryption")[5:] # strip salt=
This unconditionally slices off the first 3/5 characters assuming the header value always literally starts with dh=/salt=. When it doesn’t, the slice removes real key bytes instead of a label, producing corrupted data instead of a clean error. This is why it’s easy to miss: the corrupted string is usually also the wrong base64 length, so it dies on Incorrect padding first (the bug #37 already fixes) — you only reach this second bug once padding is no longer the first thing to fail.
Suggested fix:
crypto_key = self._app_data_by_key(msg, "crypto-key").removeprefix("dh=")
salt = self._app_data_by_key(msg, "encryption").removeprefix("salt=")
Plus, independent of the above, wrapping the decrypt+callback portion of _handle_data_message in try/except Exception (log + skip that one message) rather than letting any exception propagate and tear down the whole FcmPushClient — same spirit as #37’s per-message isolation, just covering this path too since it’s easy for some malformed/unexpected message to slip through whatever validation exists today.
Running both changes live against a real Ring Intercom for 3 days with zero full-listener crashes since.
Related to #37 but a distinct bug, only visible once #37’s padding fix (or an
equivalent) is applied.
Environment: Python 3.14, firebase-messaging @ main
(dc5acc3), Home Assistant 2026.4.2,
ring-doorbell 0.9.x, Ring Intercom.
What I saw: after locally patching _decrypt_raw_data to pad crypto_key_str/salt_str before decoding (same fix as #37), the padding crash went away, but the listener started dying instead with:
ERROR [firebase_messaging.fcmpushclient] Unknown error: Invalid EC key., shutting down FcmPushClient.
File ".../fcmpushclient.py", line ..., in _handle_data_message
File ".../fcmpushclient.py", line ..., in _decrypt_raw_data
File ".../http_ece/init.py", line ..., in derive_dh
pubkey = ec.EllipticCurvePublicKey.from_encoded_point(ec.SECP256R1(), dh)
ValueError: Invalid EC key.
Root cause: _handle_data_message does:
crypto_key = self._app_data_by_key(msg, "crypto-key")[3:] # strip dh=salt = self._app_data_by_key(msg, "encryption")[5:] # strip salt=
This unconditionally slices off the first 3/5 characters assuming the header value always literally starts with dh=/salt=. When it doesn’t, the slice removes real key bytes instead of a label, producing corrupted data instead of a clean error. This is why it’s easy to miss: the corrupted string is usually also the wrong base64 length, so it dies on Incorrect padding first (the bug #37 already fixes) — you only reach this second bug once padding is no longer the first thing to fail.
Suggested fix:
crypto_key = self._app_data_by_key(msg, "crypto-key").removeprefix("dh=")
salt = self._app_data_by_key(msg, "encryption").removeprefix("salt=")
Plus, independent of the above, wrapping the decrypt+callback portion of _handle_data_message in try/except Exception (log + skip that one message) rather than letting any exception propagate and tear down the whole FcmPushClient — same spirit as #37’s per-message isolation, just covering this path too since it’s easy for some malformed/unexpected message to slip through whatever validation exists today.
Running both changes live against a real Ring Intercom for 3 days with zero full-listener crashes since.