Coverage for paperless/signed_pickle.py: 52%
25 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 09:07 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 09:07 +0000
1from __future__ import annotations
3import hmac
4import pickle
5from hashlib import sha256
6from typing import Any
8from django.conf import settings
10HMAC_SIZE = sha256().digest_size
13class SignedPickleError(ValueError):
14 """Raised when a signed pickle payload cannot be authenticated."""
17def _get_signing_key() -> bytes:
18 return settings.SECRET_KEY.encode()
21def signed_pickle_dumps(obj: object) -> bytes:
22 data = pickle.dumps(obj, protocol=pickle.HIGHEST_PROTOCOL)
23 signature = hmac.new(_get_signing_key(), data, sha256).digest()
24 return signature + data
27def signed_pickle_loads(payload: bytes) -> Any:
28 if len(payload) <= HMAC_SIZE:
29 msg = "Signed-pickle payload too short"
30 raise SignedPickleError(msg)
32 signature = payload[:HMAC_SIZE]
33 data = payload[HMAC_SIZE:]
34 expected = hmac.new(_get_signing_key(), data, sha256).digest()
35 if not hmac.compare_digest(signature, expected):
36 msg = "Signed-pickle HMAC verification failed; payload may have been tampered with"
37 raise SignedPickleError(msg)
39 return pickle.loads(data)