test_signer.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import hashlib
  2. from functools import partial
  3. import pytest
  4. from itsdangerous.exc import BadSignature
  5. from itsdangerous.signer import HMACAlgorithm
  6. from itsdangerous.signer import NoneAlgorithm
  7. from itsdangerous.signer import Signer
  8. from itsdangerous.signer import SigningAlgorithm
  9. class _ReverseAlgorithm(SigningAlgorithm):
  10. def get_signature(self, key, value):
  11. return (key + value)[::-1]
  12. class TestSigner(object):
  13. @pytest.fixture()
  14. def signer_factory(self):
  15. return partial(Signer, secret_key="secret-key")
  16. @pytest.fixture()
  17. def signer(self, signer_factory):
  18. return signer_factory()
  19. def test_signer(self, signer):
  20. signed = signer.sign("my string")
  21. assert isinstance(signed, bytes)
  22. assert signer.validate(signed)
  23. out = signer.unsign(signed)
  24. assert out == b"my string"
  25. def test_no_separator(self, signer):
  26. signed = signer.sign("my string")
  27. signed = signed.replace(signer.sep, b"*", 1)
  28. assert not signer.validate(signed)
  29. with pytest.raises(BadSignature):
  30. signer.unsign(signed)
  31. def test_broken_signature(self, signer):
  32. signed = signer.sign("b")
  33. bad_signed = signed[:-1]
  34. bad_sig = bad_signed.rsplit(b".", 1)[1]
  35. assert not signer.verify_signature(b"b", bad_sig)
  36. with pytest.raises(BadSignature) as exc_info:
  37. signer.unsign(bad_signed)
  38. assert exc_info.value.payload == b"b"
  39. def test_changed_value(self, signer):
  40. signed = signer.sign("my string")
  41. signed = signed.replace(b"my", b"other", 1)
  42. assert not signer.validate(signed)
  43. with pytest.raises(BadSignature):
  44. signer.unsign(signed)
  45. def test_invalid_separator(self, signer_factory):
  46. with pytest.raises(ValueError) as exc_info:
  47. signer_factory(sep="-")
  48. assert "separator cannot be used" in str(exc_info.value)
  49. @pytest.mark.parametrize(
  50. "key_derivation", ("concat", "django-concat", "hmac", "none")
  51. )
  52. def test_key_derivation(self, signer_factory, key_derivation):
  53. signer = signer_factory(key_derivation=key_derivation)
  54. assert signer.unsign(signer.sign("value")) == b"value"
  55. def test_invalid_key_derivation(self, signer_factory):
  56. signer = signer_factory(key_derivation="invalid")
  57. with pytest.raises(TypeError):
  58. signer.derive_key()
  59. def test_digest_method(self, signer_factory):
  60. signer = signer_factory(digest_method=hashlib.md5)
  61. assert signer.unsign(signer.sign("value")) == b"value"
  62. @pytest.mark.parametrize(
  63. "algorithm", (None, NoneAlgorithm(), HMACAlgorithm(), _ReverseAlgorithm())
  64. )
  65. def test_algorithm(self, signer_factory, algorithm):
  66. signer = signer_factory(algorithm=algorithm)
  67. assert signer.unsign(signer.sign("value")) == b"value"
  68. if algorithm is None:
  69. assert signer.algorithm.digest_method == signer.digest_method
  70. def test_abstract_algorithm():
  71. alg = SigningAlgorithm()
  72. with pytest.raises(NotImplementedError):
  73. alg.get_signature("a", "b")