1 """Class representing an X.509 certificate."""
3 from utils.ASN1Parser import ASN1Parser
4 from utils.cryptomath import *
5 from utils.keyfactory import _createPublicRSAKey
9 """This class represents an X.509 certificate.
11 @type bytes: L{array.array} of unsigned bytes
12 @ivar bytes: The DER-encoded ASN.1 certificate
14 @type publicKey: L{tlslite.utils.RSAKey.RSAKey}
15 @ivar publicKey: The subject public key from the certificate.
17 @type subject: L{array.array} of unsigned bytes
18 @ivar subject: The DER-encoded ASN.1 subject distinguished name.
22 self.bytes = createByteArraySequence([])
27 """Parse a PEM-encoded X.509 certificate.
30 @param s: A PEM-encoded X.509 certificate (i.e. a base64-encoded
31 certificate wrapped with "-----BEGIN CERTIFICATE-----" and
32 "-----END CERTIFICATE-----" tags).
35 start = s.find("-----BEGIN CERTIFICATE-----")
36 end = s.find("-----END CERTIFICATE-----")
38 raise SyntaxError("Missing PEM prefix")
40 raise SyntaxError("Missing PEM postfix")
41 s = s[start+len("-----BEGIN CERTIFICATE-----") : end]
43 bytes = base64ToBytes(s)
44 self.parseBinary(bytes)
47 def parseBinary(self, bytes):
48 """Parse a DER-encoded X.509 certificate.
50 @type bytes: str or L{array.array} of unsigned bytes
51 @param bytes: A DER-encoded X.509 certificate.
54 if isinstance(bytes, type("")):
55 bytes = stringToBytes(bytes)
60 #Get the tbsCertificate
61 tbsCertificateP = p.getChild(0)
63 #Is the optional version field present?
64 #This determines which index the key is at.
65 if tbsCertificateP.value[0]==0xA0:
66 subjectPublicKeyInfoIndex = 6
68 subjectPublicKeyInfoIndex = 5
71 self.subject = tbsCertificateP.getChildBytes(\
72 subjectPublicKeyInfoIndex - 1)
74 #Get the subjectPublicKeyInfo
75 subjectPublicKeyInfoP = tbsCertificateP.getChild(\
76 subjectPublicKeyInfoIndex)
79 algorithmP = subjectPublicKeyInfoP.getChild(0)
80 rsaOID = algorithmP.value
81 if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]:
82 raise SyntaxError("Unrecognized AlgorithmIdentifier")
84 #Get the subjectPublicKey
85 subjectPublicKeyP = subjectPublicKeyInfoP.getChild(1)
87 #Adjust for BIT STRING encapsulation
88 if (subjectPublicKeyP.value[0] !=0):
90 subjectPublicKeyP = ASN1Parser(subjectPublicKeyP.value[1:])
92 #Get the modulus and exponent
93 modulusP = subjectPublicKeyP.getChild(0)
94 publicExponentP = subjectPublicKeyP.getChild(1)
96 #Decode them into numbers
97 n = bytesToNumber(modulusP.value)
98 e = bytesToNumber(publicExponentP.value)
100 #Create a public key instance
101 self.publicKey = _createPublicRSAKey(n, e)
104 def getFingerprint(self):
105 """Get the hex-encoded fingerprint of this certificate.
108 @return: A hex-encoded fingerprint.
110 return sha.sha(self.bytes).hexdigest()
112 def getCommonName(self):
113 """Get the Subject's Common Name from the certificate.
115 The cryptlib_py module must be installed in order to use this
119 @return: The CN component of the certificate's subject DN, if
124 c = cryptlib_py.cryptImportCert(self.bytes, cryptlib_py.CRYPT_UNUSED)
125 name = cryptlib_py.CRYPT_CERTINFO_COMMONNAME
128 length = cryptlib_py.cryptGetAttributeString(c, name, None)
129 returnVal = array.array('B', [0] * length)
130 cryptlib_py.cryptGetAttributeString(c, name, returnVal)
131 returnVal = returnVal.tostring()
132 except cryptlib_py.CryptException, e:
133 if e[0] == cryptlib_py.CRYPT_ERROR_NOTFOUND:
137 cryptlib_py.cryptDestroyCert(c)
139 def writeBytes(self):