mirror of
https://github.com/bvanroll/cicdTest.git
synced 2025-08-29 20:12:43 +00:00
build test
This commit is contained in:
179
venv/lib/python3.7/site-packages/itsdangerous/signer.py
Normal file
179
venv/lib/python3.7/site-packages/itsdangerous/signer.py
Normal file
@@ -0,0 +1,179 @@
|
||||
import hashlib
|
||||
import hmac
|
||||
|
||||
from ._compat import constant_time_compare
|
||||
from .encoding import _base64_alphabet
|
||||
from .encoding import base64_decode
|
||||
from .encoding import base64_encode
|
||||
from .encoding import want_bytes
|
||||
from .exc import BadSignature
|
||||
|
||||
|
||||
class SigningAlgorithm(object):
|
||||
"""Subclasses must implement :meth:`get_signature` to provide
|
||||
signature generation functionality.
|
||||
"""
|
||||
|
||||
def get_signature(self, key, value):
|
||||
"""Returns the signature for the given key and value."""
|
||||
raise NotImplementedError()
|
||||
|
||||
def verify_signature(self, key, value, sig):
|
||||
"""Verifies the given signature matches the expected
|
||||
signature.
|
||||
"""
|
||||
return constant_time_compare(sig, self.get_signature(key, value))
|
||||
|
||||
|
||||
class NoneAlgorithm(SigningAlgorithm):
|
||||
"""Provides an algorithm that does not perform any signing and
|
||||
returns an empty signature.
|
||||
"""
|
||||
|
||||
def get_signature(self, key, value):
|
||||
return b""
|
||||
|
||||
|
||||
class HMACAlgorithm(SigningAlgorithm):
|
||||
"""Provides signature generation using HMACs."""
|
||||
|
||||
#: The digest method to use with the MAC algorithm. This defaults to
|
||||
#: SHA1, but can be changed to any other function in the hashlib
|
||||
#: module.
|
||||
default_digest_method = staticmethod(hashlib.sha1)
|
||||
|
||||
def __init__(self, digest_method=None):
|
||||
if digest_method is None:
|
||||
digest_method = self.default_digest_method
|
||||
self.digest_method = digest_method
|
||||
|
||||
def get_signature(self, key, value):
|
||||
mac = hmac.new(key, msg=value, digestmod=self.digest_method)
|
||||
return mac.digest()
|
||||
|
||||
|
||||
class Signer(object):
|
||||
"""This class can sign and unsign bytes, validating the signature
|
||||
provided.
|
||||
|
||||
Salt can be used to namespace the hash, so that a signed string is
|
||||
only valid for a given namespace. Leaving this at the default value
|
||||
or re-using a salt value across different parts of your application
|
||||
where the same signed value in one part can mean something different
|
||||
in another part is a security risk.
|
||||
|
||||
See :ref:`the-salt` for an example of what the salt is doing and how
|
||||
you can utilize it.
|
||||
|
||||
.. versionadded:: 0.14
|
||||
``key_derivation`` and ``digest_method`` were added as arguments
|
||||
to the class constructor.
|
||||
|
||||
.. versionadded:: 0.18
|
||||
``algorithm`` was added as an argument to the class constructor.
|
||||
"""
|
||||
|
||||
#: The digest method to use for the signer. This defaults to
|
||||
#: SHA1 but can be changed to any other function in the hashlib
|
||||
#: module.
|
||||
#:
|
||||
#: .. versionadded:: 0.14
|
||||
default_digest_method = staticmethod(hashlib.sha1)
|
||||
|
||||
#: Controls how the key is derived. The default is Django-style
|
||||
#: concatenation. Possible values are ``concat``, ``django-concat``
|
||||
#: and ``hmac``. This is used for deriving a key from the secret key
|
||||
#: with an added salt.
|
||||
#:
|
||||
#: .. versionadded:: 0.14
|
||||
default_key_derivation = "django-concat"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
secret_key,
|
||||
salt=None,
|
||||
sep=".",
|
||||
key_derivation=None,
|
||||
digest_method=None,
|
||||
algorithm=None,
|
||||
):
|
||||
self.secret_key = want_bytes(secret_key)
|
||||
self.sep = want_bytes(sep)
|
||||
if self.sep in _base64_alphabet:
|
||||
raise ValueError(
|
||||
"The given separator cannot be used because it may be"
|
||||
" contained in the signature itself. Alphanumeric"
|
||||
" characters and `-_=` must not be used."
|
||||
)
|
||||
self.salt = "itsdangerous.Signer" if salt is None else salt
|
||||
if key_derivation is None:
|
||||
key_derivation = self.default_key_derivation
|
||||
self.key_derivation = key_derivation
|
||||
if digest_method is None:
|
||||
digest_method = self.default_digest_method
|
||||
self.digest_method = digest_method
|
||||
if algorithm is None:
|
||||
algorithm = HMACAlgorithm(self.digest_method)
|
||||
self.algorithm = algorithm
|
||||
|
||||
def derive_key(self):
|
||||
"""This method is called to derive the key. The default key
|
||||
derivation choices can be overridden here. Key derivation is not
|
||||
intended to be used as a security method to make a complex key
|
||||
out of a short password. Instead you should use large random
|
||||
secret keys.
|
||||
"""
|
||||
salt = want_bytes(self.salt)
|
||||
if self.key_derivation == "concat":
|
||||
return self.digest_method(salt + self.secret_key).digest()
|
||||
elif self.key_derivation == "django-concat":
|
||||
return self.digest_method(salt + b"signer" + self.secret_key).digest()
|
||||
elif self.key_derivation == "hmac":
|
||||
mac = hmac.new(self.secret_key, digestmod=self.digest_method)
|
||||
mac.update(salt)
|
||||
return mac.digest()
|
||||
elif self.key_derivation == "none":
|
||||
return self.secret_key
|
||||
else:
|
||||
raise TypeError("Unknown key derivation method")
|
||||
|
||||
def get_signature(self, value):
|
||||
"""Returns the signature for the given value."""
|
||||
value = want_bytes(value)
|
||||
key = self.derive_key()
|
||||
sig = self.algorithm.get_signature(key, value)
|
||||
return base64_encode(sig)
|
||||
|
||||
def sign(self, value):
|
||||
"""Signs the given string."""
|
||||
return want_bytes(value) + want_bytes(self.sep) + self.get_signature(value)
|
||||
|
||||
def verify_signature(self, value, sig):
|
||||
"""Verifies the signature for the given value."""
|
||||
key = self.derive_key()
|
||||
try:
|
||||
sig = base64_decode(sig)
|
||||
except Exception:
|
||||
return False
|
||||
return self.algorithm.verify_signature(key, value, sig)
|
||||
|
||||
def unsign(self, signed_value):
|
||||
"""Unsigns the given string."""
|
||||
signed_value = want_bytes(signed_value)
|
||||
sep = want_bytes(self.sep)
|
||||
if sep not in signed_value:
|
||||
raise BadSignature("No %r found in value" % self.sep)
|
||||
value, sig = signed_value.rsplit(sep, 1)
|
||||
if self.verify_signature(value, sig):
|
||||
return value
|
||||
raise BadSignature("Signature %r does not match" % sig, payload=value)
|
||||
|
||||
def validate(self, signed_value):
|
||||
"""Only validates the given signed value. Returns ``True`` if
|
||||
the signature exists and is valid.
|
||||
"""
|
||||
try:
|
||||
self.unsign(signed_value)
|
||||
return True
|
||||
except BadSignature:
|
||||
return False
|
Reference in New Issue
Block a user