serialization.py 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. from __future__ import absolute_import
  2. import base64
  3. import sys
  4. from kombu.serialization import registry, encode, decode
  5. from ..exceptions import SecurityError
  6. from ..utils.encoding import bytes_to_str, str_to_bytes
  7. from .certificate import Certificate, FSCertStore
  8. from .key import PrivateKey
  9. def b64encode(s):
  10. return bytes_to_str(base64.b64encode(str_to_bytes(s)))
  11. def b64decode(s):
  12. return base64.b64decode(str_to_bytes(s))
  13. class SecureSerializer(object):
  14. def __init__(self, key=None, cert=None, cert_store=None,
  15. digest="sha1", serializer="json"):
  16. self._key = key
  17. self._cert = cert
  18. self._cert_store = cert_store
  19. self._digest = digest
  20. self._serializer = serializer
  21. def serialize(self, data):
  22. """serialize data structure into string"""
  23. assert self._key is not None
  24. assert self._cert is not None
  25. try:
  26. content_type, content_encoding, body = encode(
  27. data, serializer=self._serializer)
  28. # What we sign is the serialized body, not the body itself.
  29. # this way the receiver doesn't have to decode the contents
  30. # to verify the signature (and thus avoiding potential flaws
  31. # in the decoding step).
  32. return self._pack(body, content_type, content_encoding,
  33. signature=self._key.sign(body, self._digest),
  34. signer=self._cert.get_id())
  35. except Exception, exc:
  36. raise SecurityError, SecurityError(
  37. "Unable to serialize: %r" % (exc, )), sys.exc_info()[2]
  38. def deserialize(self, data):
  39. """deserialize data structure from string"""
  40. assert self._cert_store is not None
  41. try:
  42. payload = self._unpack(data)
  43. signature, signer, body = (payload["signature"],
  44. payload["signer"],
  45. payload["body"])
  46. self._cert_store[signer].verify(body,
  47. signature, self._digest)
  48. except Exception, exc:
  49. raise SecurityError, SecurityError(
  50. "Unable to deserialize: %r" % (exc, )), sys.exc_info()[2]
  51. return decode(body, payload["content_type"],
  52. payload["content_encoding"], force=True)
  53. def _pack(self, body, content_type, content_encoding, signer, signature,
  54. sep='\x00\x01'):
  55. return b64encode(sep.join([signer, signature,
  56. content_type, content_encoding, body]))
  57. def _unpack(self, payload, sep='\x00\x01',
  58. fields=("signer", "signature", "content_type",
  59. "content_encoding", "body")):
  60. return dict(zip(fields, b64decode(payload).split(sep)))
  61. def register_auth(key=None, cert=None, store=None, digest="sha1",
  62. serializer="json"):
  63. """register security serializer"""
  64. s = SecureSerializer(key and PrivateKey(key),
  65. cert and Certificate(cert),
  66. store and FSCertStore(store),
  67. digest=digest, serializer=serializer)
  68. registry.register("auth", s.serialize, s.deserialize,
  69. content_type="application/data",
  70. content_encoding="utf-8")