(
secret: Union[str, bytes],
name: str,
value: bytes,
max_age_days: float,
clock: Callable[[], float],
)
| 3499 | |
| 3500 | |
| 3501 | def _decode_signed_value_v1( |
| 3502 | secret: Union[str, bytes], |
| 3503 | name: str, |
| 3504 | value: bytes, |
| 3505 | max_age_days: float, |
| 3506 | clock: Callable[[], float], |
| 3507 | ) -> Optional[bytes]: |
| 3508 | parts = utf8(value).split(b"|") |
| 3509 | if len(parts) != 3: |
| 3510 | return None |
| 3511 | signature = _create_signature_v1(secret, name, parts[0], parts[1]) |
| 3512 | if not hmac.compare_digest(parts[2], signature): |
| 3513 | gen_log.warning("Invalid cookie signature %r", value) |
| 3514 | return None |
| 3515 | timestamp = int(parts[1]) |
| 3516 | if timestamp < clock() - max_age_days * 86400: |
| 3517 | gen_log.warning("Expired cookie %r", value) |
| 3518 | return None |
| 3519 | if timestamp > clock() + 31 * 86400: |
| 3520 | # _cookie_signature does not hash a delimiter between the |
| 3521 | # parts of the cookie, so an attacker could transfer trailing |
| 3522 | # digits from the payload to the timestamp without altering the |
| 3523 | # signature. For backwards compatibility, sanity-check timestamp |
| 3524 | # here instead of modifying _cookie_signature. |
| 3525 | gen_log.warning("Cookie timestamp in future; possible tampering %r", value) |
| 3526 | return None |
| 3527 | if parts[1].startswith(b"0"): |
| 3528 | gen_log.warning("Tampered cookie %r", value) |
| 3529 | return None |
| 3530 | try: |
| 3531 | return base64.b64decode(parts[0]) |
| 3532 | except Exception: |
| 3533 | return None |
| 3534 | |
| 3535 | |
| 3536 | def _decode_fields_v2(value: bytes) -> Tuple[int, bytes, bytes, bytes, bytes]: |
no test coverage detected