]>
jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/itsdangerous/serializer.py
4 from .encoding
import want_bytes
5 from .exc
import BadPayload
6 from .exc
import BadSignature
7 from .signer
import _make_keys_list
8 from .signer
import Signer
10 _t_str_bytes
= _t
.Union
[str, bytes]
11 _t_opt_str_bytes
= _t
.Optional
[_t_str_bytes
]
12 _t_kwargs
= _t
.Dict
[str, _t
.Any
]
13 _t_opt_kwargs
= _t
.Optional
[_t_kwargs
]
14 _t_signer
= _t
.Type
[Signer
]
15 _t_fallbacks
= _t
.List
[_t
.Union
[_t_kwargs
, _t
.Tuple
[_t_signer
, _t_kwargs
], _t_signer
]]
16 _t_load_unsafe
= _t
.Tuple
[bool, _t
.Any
]
17 _t_secret_key
= _t
.Union
[_t
.Iterable
[_t_str_bytes
], _t_str_bytes
]
20 def is_text_serializer(serializer
: _t
.Any
) -> bool:
21 """Checks whether a serializer generates text or binary."""
22 return isinstance(serializer
.dumps({}), str)
26 """A serializer wraps a :class:`~itsdangerous.signer.Signer` to
27 enable serializing and securely signing data other than bytes. It
28 can unsign to verify that the data hasn't been changed.
30 The serializer provides :meth:`dumps` and :meth:`loads`, similar to
31 :mod:`json`, and by default uses :mod:`json` internally to serialize
34 The secret key should be a random string of ``bytes`` and should not
35 be saved to code or version control. Different salts should be used
36 to distinguish signing in different contexts. See :doc:`/concepts`
37 for information about the security of the secret key and salt.
39 :param secret_key: The secret key to sign and verify with. Can be a
40 list of keys, oldest to newest, to support key rotation.
41 :param salt: Extra key to combine with ``secret_key`` to distinguish
42 signatures in different contexts.
43 :param serializer: An object that provides ``dumps`` and ``loads``
44 methods for serializing data to a string. Defaults to
45 :attr:`default_serializer`, which defaults to :mod:`json`.
46 :param serializer_kwargs: Keyword arguments to pass when calling
48 :param signer: A ``Signer`` class to instantiate when signing data.
49 Defaults to :attr:`default_signer`, which defaults to
50 :class:`~itsdangerous.signer.Signer`.
51 :param signer_kwargs: Keyword arguments to pass when instantiating
53 :param fallback_signers: List of signer parameters to try when
54 unsigning with the default signer fails. Each item can be a dict
55 of ``signer_kwargs``, a ``Signer`` class, or a tuple of
56 ``(signer, signer_kwargs)``. Defaults to
57 :attr:`default_fallback_signers`.
59 .. versionchanged:: 2.0
60 Added support for key rotation by passing a list to
63 .. versionchanged:: 2.0
64 Removed the default SHA-512 fallback signer from
65 ``default_fallback_signers``.
67 .. versionchanged:: 1.1
68 Added support for ``fallback_signers`` and configured a default
69 SHA-512 fallback. This fallback is for users who used the yanked
70 1.0.0 release which defaulted to SHA-512.
72 .. versionchanged:: 0.14
73 The ``signer`` and ``signer_kwargs`` parameters were added to
77 #: The default serialization module to use to serialize data to a
78 #: string internally. The default is :mod:`json`, but can be changed
79 #: to any object that provides ``dumps`` and ``loads`` methods.
80 default_serializer
: _t
.Any
= json
82 #: The default ``Signer`` class to instantiate when signing data.
83 #: The default is :class:`itsdangerous.signer.Signer`.
84 default_signer
: _t_signer
= Signer
86 #: The default fallback signers to try when unsigning fails.
87 default_fallback_signers
: _t_fallbacks
= []
91 secret_key
: _t_secret_key
,
92 salt
: _t_opt_str_bytes
= b
"itsdangerous",
93 serializer
: _t
.Any
= None,
94 serializer_kwargs
: _t_opt_kwargs
= None,
95 signer
: _t
.Optional
[_t_signer
] = None,
96 signer_kwargs
: _t_opt_kwargs
= None,
97 fallback_signers
: _t
.Optional
[_t_fallbacks
] = None,
99 #: The list of secret keys to try for verifying signatures, from
100 #: oldest to newest. The newest (last) key is used for signing.
102 #: This allows a key rotation system to keep a list of allowed
103 #: keys and remove expired ones.
104 self
.secret_keys
: _t
.List
[bytes] = _make_keys_list(secret_key
)
107 salt
= want_bytes(salt
)
108 # if salt is None then the signer's default is used
112 if serializer
is None:
113 serializer
= self
.default_serializer
115 self
.serializer
: _t
.Any
= serializer
116 self
.is_text_serializer
: bool = is_text_serializer(serializer
)
119 signer
= self
.default_signer
121 self
.signer
: _t_signer
= signer
122 self
.signer_kwargs
: _t_kwargs
= signer_kwargs
or {}
124 if fallback_signers
is None:
125 fallback_signers
= list(self
.default_fallback_signers
or ())
127 self
.fallback_signers
: _t_fallbacks
= fallback_signers
128 self
.serializer_kwargs
: _t_kwargs
= serializer_kwargs
or {}
131 def secret_key(self
) -> bytes:
132 """The newest (last) entry in the :attr:`secret_keys` list. This
133 is for compatibility from before key rotation support was added.
135 return self
.secret_keys
[-1]
138 self
, payload
: bytes, serializer
: _t
.Optional
[_t
.Any
] = None
140 """Loads the encoded object. This function raises
141 :class:`.BadPayload` if the payload is not valid. The
142 ``serializer`` parameter can be used to override the serializer
143 stored on the class. The encoded ``payload`` should always be
146 if serializer
is None:
147 serializer
= self
.serializer
148 is_text
= self
.is_text_serializer
150 is_text
= is_text_serializer(serializer
)
154 return serializer
.loads(payload
.decode("utf-8"))
156 return serializer
.loads(payload
)
157 except Exception as e
:
159 "Could not load the payload because an exception"
160 " occurred on unserializing the data.",
164 def dump_payload(self
, obj
: _t
.Any
) -> bytes:
165 """Dumps the encoded object. The return value is always bytes.
166 If the internal serializer returns text, the value will be
169 return want_bytes(self
.serializer
.dumps(obj
, **self
.serializer_kwargs
))
171 def make_signer(self
, salt
: _t_opt_str_bytes
= None) -> Signer
:
172 """Creates a new instance of the signer to be used. The default
173 implementation uses the :class:`.Signer` base class.
178 return self
.signer(self
.secret_keys
, salt
=salt
, **self
.signer_kwargs
)
180 def iter_unsigners(self
, salt
: _t_opt_str_bytes
= None) -> _t
.Iterator
[Signer
]:
181 """Iterates over all signers to be tried for unsigning. Starts
182 with the configured signer, then constructs each signer
183 specified in ``fallback_signers``.
188 yield self
.make_signer(salt
)
190 for fallback
in self
.fallback_signers
:
191 if isinstance(fallback
, dict):
193 fallback
= self
.signer
194 elif isinstance(fallback
, tuple):
195 fallback
, kwargs
= fallback
197 kwargs
= self
.signer_kwargs
199 for secret_key
in self
.secret_keys
:
200 yield fallback(secret_key
, salt
=salt
, **kwargs
)
202 def dumps(self
, obj
: _t
.Any
, salt
: _t_opt_str_bytes
= None) -> _t_str_bytes
:
203 """Returns a signed string serialized with the internal
204 serializer. The return value can be either a byte or unicode
205 string depending on the format of the internal serializer.
207 payload
= want_bytes(self
.dump_payload(obj
))
208 rv
= self
.make_signer(salt
).sign(payload
)
210 if self
.is_text_serializer
:
211 return rv
.decode("utf-8")
215 def dump(self
, obj
: _t
.Any
, f
: _t
.IO
, salt
: _t_opt_str_bytes
= None) -> None:
216 """Like :meth:`dumps` but dumps into a file. The file handle has
217 to be compatible with what the internal serializer expects.
219 f
.write(self
.dumps(obj
, salt
))
222 self
, s
: _t_str_bytes
, salt
: _t_opt_str_bytes
= None, **kwargs
: _t
.Any
224 """Reverse of :meth:`dumps`. Raises :exc:`.BadSignature` if the
225 signature validation fails.
228 last_exception
= None
230 for signer
in self
.iter_unsigners(salt
):
232 return self
.load_payload(signer
.unsign(s
))
233 except BadSignature
as err
:
236 raise _t
.cast(BadSignature
, last_exception
)
238 def load(self
, f
: _t
.IO
, salt
: _t_opt_str_bytes
= None) -> _t
.Any
:
239 """Like :meth:`loads` but loads from a file."""
240 return self
.loads(f
.read(), salt
)
243 self
, s
: _t_str_bytes
, salt
: _t_opt_str_bytes
= None
245 """Like :meth:`loads` but without verifying the signature. This
246 is potentially very dangerous to use depending on how your
247 serializer works. The return value is ``(signature_valid,
248 payload)`` instead of just the payload. The first item will be a
249 boolean that indicates if the signature is valid. This function
252 Use it for debugging only and if you know that your serializer
253 module is not exploitable (for example, do not use it with a
256 .. versionadded:: 0.15
258 return self
._loads
_unsafe
_impl
(s
, salt
)
260 def _loads_unsafe_impl(
263 salt
: _t_opt_str_bytes
,
264 load_kwargs
: _t_opt_kwargs
= None,
265 load_payload_kwargs
: _t_opt_kwargs
= None,
267 """Low level helper function to implement :meth:`loads_unsafe`
268 in serializer subclasses.
270 if load_kwargs
is None:
274 return True, self
.loads(s
, salt
=salt
, **load_kwargs
)
275 except BadSignature
as e
:
276 if e
.payload
is None:
279 if load_payload_kwargs
is None:
280 load_payload_kwargs
= {}
285 self
.load_payload(e
.payload
, **load_payload_kwargs
),
290 def load_unsafe(self
, f
: _t
.IO
, salt
: _t_opt_str_bytes
= None) -> _t_load_unsafe
:
291 """Like :meth:`loads_unsafe` but loads from a file.
293 .. versionadded:: 0.15
295 return self
.loads_unsafe(f
.read(), salt
=salt
)