/gdata/tlslite/X509.py

http://radioappz.googlecode.com/ · Python · 133 lines · 77 code · 23 blank · 33 comment · 8 complexity · e3afcac86a9d62c97b65d65bb5bfabed MD5 · raw file

  1. """Class representing an X.509 certificate."""
  2. from utils.ASN1Parser import ASN1Parser
  3. from utils.cryptomath import *
  4. from utils.keyfactory import _createPublicRSAKey
  5. class X509:
  6. """This class represents an X.509 certificate.
  7. @type bytes: L{array.array} of unsigned bytes
  8. @ivar bytes: The DER-encoded ASN.1 certificate
  9. @type publicKey: L{tlslite.utils.RSAKey.RSAKey}
  10. @ivar publicKey: The subject public key from the certificate.
  11. """
  12. def __init__(self):
  13. self.bytes = createByteArraySequence([])
  14. self.publicKey = None
  15. def parse(self, s):
  16. """Parse a PEM-encoded X.509 certificate.
  17. @type s: str
  18. @param s: A PEM-encoded X.509 certificate (i.e. a base64-encoded
  19. certificate wrapped with "-----BEGIN CERTIFICATE-----" and
  20. "-----END CERTIFICATE-----" tags).
  21. """
  22. start = s.find("-----BEGIN CERTIFICATE-----")
  23. end = s.find("-----END CERTIFICATE-----")
  24. if start == -1:
  25. raise SyntaxError("Missing PEM prefix")
  26. if end == -1:
  27. raise SyntaxError("Missing PEM postfix")
  28. s = s[start+len("-----BEGIN CERTIFICATE-----") : end]
  29. bytes = base64ToBytes(s)
  30. self.parseBinary(bytes)
  31. return self
  32. def parseBinary(self, bytes):
  33. """Parse a DER-encoded X.509 certificate.
  34. @type bytes: str or L{array.array} of unsigned bytes
  35. @param bytes: A DER-encoded X.509 certificate.
  36. """
  37. if isinstance(bytes, type("")):
  38. bytes = stringToBytes(bytes)
  39. self.bytes = bytes
  40. p = ASN1Parser(bytes)
  41. #Get the tbsCertificate
  42. tbsCertificateP = p.getChild(0)
  43. #Is the optional version field present?
  44. #This determines which index the key is at.
  45. if tbsCertificateP.value[0]==0xA0:
  46. subjectPublicKeyInfoIndex = 6
  47. else:
  48. subjectPublicKeyInfoIndex = 5
  49. #Get the subjectPublicKeyInfo
  50. subjectPublicKeyInfoP = tbsCertificateP.getChild(\
  51. subjectPublicKeyInfoIndex)
  52. #Get the algorithm
  53. algorithmP = subjectPublicKeyInfoP.getChild(0)
  54. rsaOID = algorithmP.value
  55. if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]:
  56. raise SyntaxError("Unrecognized AlgorithmIdentifier")
  57. #Get the subjectPublicKey
  58. subjectPublicKeyP = subjectPublicKeyInfoP.getChild(1)
  59. #Adjust for BIT STRING encapsulation
  60. if (subjectPublicKeyP.value[0] !=0):
  61. raise SyntaxError()
  62. subjectPublicKeyP = ASN1Parser(subjectPublicKeyP.value[1:])
  63. #Get the modulus and exponent
  64. modulusP = subjectPublicKeyP.getChild(0)
  65. publicExponentP = subjectPublicKeyP.getChild(1)
  66. #Decode them into numbers
  67. n = bytesToNumber(modulusP.value)
  68. e = bytesToNumber(publicExponentP.value)
  69. #Create a public key instance
  70. self.publicKey = _createPublicRSAKey(n, e)
  71. def getFingerprint(self):
  72. """Get the hex-encoded fingerprint of this certificate.
  73. @rtype: str
  74. @return: A hex-encoded fingerprint.
  75. """
  76. return sha.sha(self.bytes).hexdigest()
  77. def getCommonName(self):
  78. """Get the Subject's Common Name from the certificate.
  79. The cryptlib_py module must be installed in order to use this
  80. function.
  81. @rtype: str or None
  82. @return: The CN component of the certificate's subject DN, if
  83. present.
  84. """
  85. import cryptlib_py
  86. import array
  87. c = cryptlib_py.cryptImportCert(self.bytes, cryptlib_py.CRYPT_UNUSED)
  88. name = cryptlib_py.CRYPT_CERTINFO_COMMONNAME
  89. try:
  90. try:
  91. length = cryptlib_py.cryptGetAttributeString(c, name, None)
  92. returnVal = array.array('B', [0] * length)
  93. cryptlib_py.cryptGetAttributeString(c, name, returnVal)
  94. returnVal = returnVal.tostring()
  95. except cryptlib_py.CryptException, e:
  96. if e[0] == cryptlib_py.CRYPT_ERROR_NOTFOUND:
  97. returnVal = None
  98. return returnVal
  99. finally:
  100. cryptlib_py.cryptDestroyCert(c)
  101. def writeBytes(self):
  102. return self.bytes