certificate.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. from __future__ import absolute_import
  2. from __future__ import with_statement
  3. import glob
  4. import os
  5. import sys
  6. try:
  7. from OpenSSL import crypto
  8. except ImportError:
  9. crypto = None # noqa
  10. from ..exceptions import SecurityError
  11. class Certificate(object):
  12. """X.509 certificate."""
  13. def __init__(self, cert):
  14. assert crypto is not None
  15. try:
  16. self._cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
  17. except crypto.Error, exc:
  18. raise SecurityError, SecurityError(
  19. "Invalid certificate: %r" % (exc, )), sys.exc_info()[2]
  20. def has_expired(self):
  21. """Check if the certificate has expired."""
  22. return self._cert.has_expired()
  23. def get_serial_number(self):
  24. """Returns the certificates serial number."""
  25. return self._cert.get_serial_number()
  26. def get_issuer(self):
  27. """Returns issuer (CA) as a string"""
  28. return ' '.join(x[1] for x in
  29. self._cert.get_issuer().get_components())
  30. def get_id(self):
  31. """Serial number/issuer pair uniquely identifies a certificate"""
  32. return "%s %s" % (self.get_issuer(), self.get_serial_number())
  33. def verify(self, data, signature, digest):
  34. """Verifies the signature for string containing data."""
  35. try:
  36. crypto.verify(self._cert, signature, data, digest)
  37. except crypto.Error, exc:
  38. raise SecurityError, SecurityError(
  39. "Bad signature: %r" % (exc, )), sys.exc_info()[2]
  40. class CertStore(object):
  41. """Base class for certificate stores"""
  42. def __init__(self):
  43. self._certs = {}
  44. def itercerts(self):
  45. """an iterator over the certificates"""
  46. for c in self._certs.itervalues():
  47. yield c
  48. def __getitem__(self, id):
  49. """get certificate by id"""
  50. try:
  51. return self._certs[id]
  52. except KeyError:
  53. raise SecurityError("Unknown certificate: %r" % (id, ))
  54. def add_cert(self, cert):
  55. if cert.get_id() in self._certs:
  56. raise SecurityError("Duplicate certificate: %r" % (id, ))
  57. self._certs[cert.get_id()] = cert
  58. class FSCertStore(CertStore):
  59. """File system certificate store"""
  60. def __init__(self, path):
  61. CertStore.__init__(self)
  62. if os.path.isdir(path):
  63. path = os.path.join(path, '*')
  64. for p in glob.glob(path):
  65. with open(p) as f:
  66. cert = Certificate(f.read())
  67. if cert.has_expired():
  68. raise SecurityError(
  69. "Expired certificate: %r" % (cert.get_id(), ))
  70. self.add_cert(cert)