From b9af4955b9bf764ebbb38758bd3ab3a07b16a885 Mon Sep 17 00:00:00 2001 From: elkimek <36666630+elkimek@users.noreply.github.com> Date: Sun, 12 Apr 2026 08:53:16 +0000 Subject: [PATCH] fix(matrix): restore verify_with_recovery_key after device key rotation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After the PgCryptoStore migration in v0.8.0, the verify_with_recovery_key call that previously ran after share_keys() was dropped. On any rotation that uploads fresh device keys (fresh crypto.db, server had stale keys from a prior install, etc.), the new device keys carry no valid self- signing signature because the bot has no access to the self-signing private key. Peers like Element then refuse to share Megolm sessions with the rotated device, so the bot silently stops decrypting incoming messages. This restores the recovery-key bootstrap: on startup, if MATRIX_RECOVERY_KEY is set, import the cross-signing private keys from SSSS and sign_own_device(), producing a valid signature server-side. Idempotent and gated on MATRIX_RECOVERY_KEY — no behavior change for users who don't configure a recovery key. Verified end-to-end by deleting crypto.db and restarting: the bot rotates device identity keys, re-uploads, self-signs via recovery key, and decrypts+replies to fresh messages from a paired Element client. --- gateway/platforms/matrix.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/gateway/platforms/matrix.py b/gateway/platforms/matrix.py index 75d7e9c9f..9ba63c083 100644 --- a/gateway/platforms/matrix.py +++ b/gateway/platforms/matrix.py @@ -508,6 +508,19 @@ class MatrixAdapter(BasePlatformAdapter): await api.session.close() return False + # Import cross-signing private keys from SSSS and self-sign + # the current device. Required after any device-key rotation + # (fresh crypto.db, share_keys re-upload) — otherwise the + # device's self-signing signature is stale and peers refuse + # to share Megolm sessions with the rotated device. + recovery_key = os.getenv("MATRIX_RECOVERY_KEY", "").strip() + if recovery_key: + try: + await olm.verify_with_recovery_key(recovery_key) + logger.info("Matrix: cross-signing verified via recovery key") + except Exception as exc: + logger.warning("Matrix: recovery key verification failed: %s", exc) + client.crypto = olm logger.info( "Matrix: E2EE enabled (store: %s%s)",