Skip to content
Open
Show file tree
Hide file tree
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
8 changes: 7 additions & 1 deletion quantara/web_app/telegram/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,13 @@ def check_telegram_authorization(
secret_key, data_check_string.encode(), hashlib.sha256
).hexdigest()

if hash_value != check_hash:
# Constant-time compare so a remote timing oracle cannot recover the
# expected hash byte-by-byte (see issue #203). Unequal-length inputs
# make compare_digest raise; treat that as a failed verification.
try:
if not hmac.compare_digest(hash_value, check_hash):
return False
except (TypeError, ValueError):
return False

if expiration_seconds and (int(time.time()) - int(auth_data.get("auth_date", 0))) > expiration_seconds:
Expand Down
16 changes: 16 additions & 0 deletions quantara/web_app/tests/test_telegram.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,22 @@
)
assert ok is False

def test_uses_constant_time_compare(self):
"""Hash comparison must use hmac.compare_digest (timing-safe)."""
import hmac as hmac_mod
from web_app.telegram.utils import check_telegram_authorization

data = self._build_auth(self.BOT_TOKEN)
with patch.object(
hmac_mod, "compare_digest", wraps=hmac_mod.compare_digest
) as mock_cmp:
assert check_telegram_authorization(self.BOT_TOKEN, data) is True

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
assert mock_cmp.called

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
# Both sides must be str hex digests of equal length.
left, right = mock_cmp.call_args[0]
assert isinstance(left, str) and isinstance(right, str)

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
assert len(left) == len(right) == 64

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.


# ─────────────────────────────────────────────────────────────────────────────
# 2. notifications.send_health_ratio_notification
Expand Down
Loading