PageRenderTime 30ms CodeModel.GetById 22ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/gdata/tlslite/X509.py

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