Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / third_party / tlslite / tlslite / X509.py
1 """Class representing an X.509 certificate."""
2
3 from utils.ASN1Parser import ASN1Parser
4 from utils.cryptomath import *
5 from utils.keyfactory import _createPublicRSAKey
6
7
8 class 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     @type subject: L{array.array} of unsigned bytes
18     @ivar subject: The DER-encoded ASN.1 subject distinguished name.
19     """
20
21     def __init__(self):
22         self.bytes = createByteArraySequence([])
23         self.publicKey = None
24         self.subject = None
25
26     def parse(self, s):
27         """Parse a PEM-encoded X.509 certificate.
28
29         @type s: str
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).
33         """
34
35         start = s.find("-----BEGIN CERTIFICATE-----")
36         end = s.find("-----END CERTIFICATE-----")
37         if start == -1:
38             raise SyntaxError("Missing PEM prefix")
39         if end == -1:
40             raise SyntaxError("Missing PEM postfix")
41         s = s[start+len("-----BEGIN CERTIFICATE-----") : end]
42
43         bytes = base64ToBytes(s)
44         self.parseBinary(bytes)
45         return self
46
47     def parseBinary(self, bytes):
48         """Parse a DER-encoded X.509 certificate.
49
50         @type bytes: str or L{array.array} of unsigned bytes
51         @param bytes: A DER-encoded X.509 certificate.
52         """
53
54         if isinstance(bytes, type("")):
55             bytes = stringToBytes(bytes)
56
57         self.bytes = bytes
58         p = ASN1Parser(bytes)
59
60         #Get the tbsCertificate
61         tbsCertificateP = p.getChild(0)
62
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
67         else:
68             subjectPublicKeyInfoIndex = 5
69
70         #Get the subject
71         self.subject = tbsCertificateP.getChildBytes(\
72                            subjectPublicKeyInfoIndex - 1)
73
74         #Get the subjectPublicKeyInfo
75         subjectPublicKeyInfoP = tbsCertificateP.getChild(\
76                                     subjectPublicKeyInfoIndex)
77
78         #Get the algorithm
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")
83
84         #Get the subjectPublicKey
85         subjectPublicKeyP = subjectPublicKeyInfoP.getChild(1)
86
87         #Adjust for BIT STRING encapsulation
88         if (subjectPublicKeyP.value[0] !=0):
89             raise SyntaxError()
90         subjectPublicKeyP = ASN1Parser(subjectPublicKeyP.value[1:])
91
92         #Get the modulus and exponent
93         modulusP = subjectPublicKeyP.getChild(0)
94         publicExponentP = subjectPublicKeyP.getChild(1)
95
96         #Decode them into numbers
97         n = bytesToNumber(modulusP.value)
98         e = bytesToNumber(publicExponentP.value)
99
100         #Create a public key instance
101         self.publicKey = _createPublicRSAKey(n, e)
102         return self
103
104     def getFingerprint(self):
105         """Get the hex-encoded fingerprint of this certificate.
106
107         @rtype: str
108         @return: A hex-encoded fingerprint.
109         """
110         return sha.sha(self.bytes).hexdigest()
111
112     def getCommonName(self):
113         """Get the Subject's Common Name from the certificate.
114
115         The cryptlib_py module must be installed in order to use this
116         function.
117
118         @rtype: str or None
119         @return: The CN component of the certificate's subject DN, if
120         present.
121         """
122         import cryptlib_py
123         import array
124         c = cryptlib_py.cryptImportCert(self.bytes, cryptlib_py.CRYPT_UNUSED)
125         name = cryptlib_py.CRYPT_CERTINFO_COMMONNAME
126         try:
127             try:
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:
134                     returnVal = None
135             return returnVal
136         finally:
137             cryptlib_py.cryptDestroyCert(c)
138
139     def writeBytes(self):
140         return self.bytes
141
142