tests.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. from __future__ import unicode_literals
  2. import time
  3. from django.core import signing
  4. from django.test import TestCase
  5. from django.utils.encoding import force_str
  6. from django.utils import six
  7. class TestSigner(TestCase):
  8. def test_signature(self):
  9. "signature() method should generate a signature"
  10. signer = signing.Signer('predictable-secret')
  11. signer2 = signing.Signer('predictable-secret2')
  12. for s in (
  13. b'hello',
  14. b'3098247:529:087:',
  15. '\u2019'.encode('utf-8'),
  16. ):
  17. self.assertEqual(
  18. signer.signature(s),
  19. signing.base64_hmac(signer.salt + 'signer', s,
  20. 'predictable-secret').decode()
  21. )
  22. self.assertNotEqual(signer.signature(s), signer2.signature(s))
  23. def test_signature_with_salt(self):
  24. "signature(value, salt=...) should work"
  25. signer = signing.Signer('predictable-secret', salt='extra-salt')
  26. self.assertEqual(
  27. signer.signature('hello'),
  28. signing.base64_hmac('extra-salt' + 'signer',
  29. 'hello', 'predictable-secret').decode()
  30. )
  31. self.assertNotEqual(
  32. signing.Signer('predictable-secret', salt='one').signature('hello'),
  33. signing.Signer('predictable-secret', salt='two').signature('hello'))
  34. def test_sign_unsign(self):
  35. "sign/unsign should be reversible"
  36. signer = signing.Signer('predictable-secret')
  37. examples = [
  38. 'q;wjmbk;wkmb',
  39. '3098247529087',
  40. '3098247:529:087:',
  41. 'jkw osanteuh ,rcuh nthu aou oauh ,ud du',
  42. '\u2019',
  43. ]
  44. if six.PY2:
  45. examples.append(b'a byte string')
  46. for example in examples:
  47. signed = signer.sign(example)
  48. self.assertIsInstance(signed, str)
  49. self.assertNotEqual(force_str(example), signed)
  50. self.assertEqual(example, signer.unsign(signed))
  51. def unsign_detects_tampering(self):
  52. "unsign should raise an exception if the value has been tampered with"
  53. signer = signing.Signer('predictable-secret')
  54. value = 'Another string'
  55. signed_value = signer.sign(value)
  56. transforms = (
  57. lambda s: s.upper(),
  58. lambda s: s + 'a',
  59. lambda s: 'a' + s[1:],
  60. lambda s: s.replace(':', ''),
  61. )
  62. self.assertEqual(value, signer.unsign(signed_value))
  63. for transform in transforms:
  64. self.assertRaises(
  65. signing.BadSignature, signer.unsign, transform(signed_value))
  66. def test_dumps_loads(self):
  67. "dumps and loads be reversible for any JSON serializable object"
  68. objects = [
  69. ['a', 'list'],
  70. 'a unicode string \u2019',
  71. {'a': 'dictionary'},
  72. ]
  73. if six.PY2:
  74. objects.append(b'a byte string')
  75. for o in objects:
  76. self.assertNotEqual(o, signing.dumps(o))
  77. self.assertEqual(o, signing.loads(signing.dumps(o)))
  78. self.assertNotEqual(o, signing.dumps(o, compress=True))
  79. self.assertEqual(o, signing.loads(signing.dumps(o, compress=True)))
  80. def test_decode_detects_tampering(self):
  81. "loads should raise exception for tampered objects"
  82. transforms = (
  83. lambda s: s.upper(),
  84. lambda s: s + 'a',
  85. lambda s: 'a' + s[1:],
  86. lambda s: s.replace(':', ''),
  87. )
  88. value = {
  89. 'foo': 'bar',
  90. 'baz': 1,
  91. }
  92. encoded = signing.dumps(value)
  93. self.assertEqual(value, signing.loads(encoded))
  94. for transform in transforms:
  95. self.assertRaises(
  96. signing.BadSignature, signing.loads, transform(encoded))
  97. def test_works_with_non_ascii_keys(self):
  98. binary_key = b'\xe7' # Set some binary (non-ASCII key)
  99. s = signing.Signer(binary_key)
  100. self.assertEquals('foo:6NB0fssLW5RQvZ3Y-MTerq2rX7w', s.sign('foo'))
  101. class TestTimestampSigner(TestCase):
  102. def test_timestamp_signer(self):
  103. value = 'hello'
  104. _time = time.time
  105. time.time = lambda: 123456789
  106. try:
  107. signer = signing.TimestampSigner('predictable-key')
  108. ts = signer.sign(value)
  109. self.assertNotEqual(ts,
  110. signing.Signer('predictable-key').sign(value))
  111. self.assertEqual(signer.unsign(ts), value)
  112. time.time = lambda: 123456800
  113. self.assertEqual(signer.unsign(ts, max_age=12), value)
  114. self.assertEqual(signer.unsign(ts, max_age=11), value)
  115. self.assertRaises(
  116. signing.SignatureExpired, signer.unsign, ts, max_age=10)
  117. finally:
  118. time.time = _time