signing.txt 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. =====================
  2. Cryptographic signing
  3. =====================
  4. .. module:: django.core.signing
  5. :synopsis: Django's signing framework.
  6. .. versionadded:: 1.4
  7. The golden rule of Web application security is to never trust data from
  8. untrusted sources. Sometimes it can be useful to pass data through an
  9. untrusted medium. Cryptographically signed values can be passed through an
  10. untrusted channel safe in the knowledge that any tampering will be detected.
  11. Django provides both a low-level API for signing values and a high-level API
  12. for setting and reading signed cookies, one of the most common uses of
  13. signing in Web applications.
  14. You may also find signing useful for the following:
  15. * Generating "recover my account" URLs for sending to users who have
  16. lost their password.
  17. * Ensuring data stored in hidden form fields has not been tampered with.
  18. * Generating one-time secret URLs for allowing temporary access to a
  19. protected resource, for example a downloadable file that a user has
  20. paid for.
  21. Protecting the SECRET_KEY
  22. =========================
  23. When you create a new Django project using :djadmin:`startproject`, the
  24. ``settings.py`` file it generates automatically gets a random
  25. :setting:`SECRET_KEY` value. This value is the key to securing signed
  26. data -- it is vital you keep this secure, or attackers could use it to
  27. generate their own signed values.
  28. Using the low-level API
  29. =======================
  30. .. class:: Signer
  31. Django's signing methods live in the ``django.core.signing`` module.
  32. To sign a value, first instantiate a ``Signer`` instance::
  33. >>> from django.core.signing import Signer
  34. >>> signer = Signer()
  35. >>> value = signer.sign('My string')
  36. >>> value
  37. 'My string:GdMGD6HNQ_qdgxYP8yBZAdAIV1w'
  38. The signature is appended to the end of the string, following the colon.
  39. You can retrieve the original value using the ``unsign`` method::
  40. >>> original = signer.unsign(value)
  41. >>> original
  42. u'My string'
  43. If the signature or value have been altered in any way, a
  44. ``django.core.signing.BadSigature`` exception will be raised::
  45. >>> value += 'm'
  46. >>> try:
  47. ... original = signer.unsign(value)
  48. ... except signing.BadSignature:
  49. ... print "Tampering detected!"
  50. By default, the ``Signer`` class uses the :setting:`SECRET_KEY` setting to
  51. generate signatures. You can use a different secret by passing it to the
  52. ``Signer`` constructor::
  53. >>> signer = Signer('my-other-secret')
  54. >>> value = signer.sign('My string')
  55. >>> value
  56. 'My string:EkfQJafvGyiofrdGnuthdxImIJw'
  57. Using the salt argument
  58. -----------------------
  59. If you do not wish to use the same key for every signing operation in your
  60. application, you can use the optional ``salt`` argument to the ``Signer``
  61. class to further strengthen your :setting:`SECRET_KEY` against brute force
  62. attacks. Using a salt will cause a new key to be derived from both the salt
  63. and your :setting:`SECRET_KEY`::
  64. >>> signer = Signer()
  65. >>> signer.sign('My string')
  66. 'My string:GdMGD6HNQ_qdgxYP8yBZAdAIV1w'
  67. >>> signer = Signer(salt='extra')
  68. >>> signer.sign('My string')
  69. 'My string:Ee7vGi-ING6n02gkcJ-QLHg6vFw'
  70. >>> signer.unsign('My string:Ee7vGi-ING6n02gkcJ-QLHg6vFw')
  71. u'My string'
  72. Unlike your :setting:`SECRET_KEY`, your salt argument does not need to stay
  73. secret.
  74. Verifying timestamped values
  75. ----------------------------
  76. .. class:: TimestampSigner
  77. ``TimestampSigner`` is a subclass of :class:`~Signer` that appends a signed
  78. timestamp to the value. This allows you to confirm that a signed value was
  79. created within a specified period of time::
  80. >>> from django.core.signing import TimestampSigner
  81. >>> signer = TimestampSigner()
  82. >>> value = signer.sign('hello')
  83. >>> value
  84. 'hello:1NMg5H:oPVuCqlJWmChm1rA2lyTUtelC-c'
  85. >>> signer.unsign(value)
  86. u'hello'
  87. >>> signer.unsign(value, max_age=10)
  88. ...
  89. SignatureExpired: Signature age 15.5289158821 > 10 seconds
  90. >>> signer.unsign(value, max_age=20)
  91. u'hello'
  92. Protecting complex data structures
  93. ----------------------------------
  94. If you wish to protect a list, tuple or dictionary you can do so using the
  95. signing module's dumps and loads functions. These imitate Python's pickle
  96. module, but uses JSON serialization under the hood. JSON ensures that even
  97. if your :setting:`SECRET_KEY` is stolen an attacker will not be able to
  98. execute arbitrary commands by exploiting the pickle format.::
  99. >>> from django.core import signing
  100. >>> value = signing.dumps({"foo": "bar"})
  101. >>> value
  102. 'eyJmb28iOiJiYXIifQ:1NMg1b:zGcDE4-TCkaeGzLeW9UQwZesciI'
  103. >>> signing.loads(value)
  104. {'foo': 'bar'}