| OLD | NEW |
| 1 # Authors: |
| 2 # Trevor Perrin |
| 3 # Google - parsing subject field |
| 4 # |
| 5 # See the LICENSE file for legal information regarding use of this file. |
| 6 |
| 1 """Class representing an X.509 certificate.""" | 7 """Class representing an X.509 certificate.""" |
| 2 | 8 |
| 3 from utils.asn1parser import ASN1Parser | 9 from .utils.asn1parser import ASN1Parser |
| 4 from utils.cryptomath import * | 10 from .utils.cryptomath import * |
| 5 from utils.keyfactory import _createPublicRSAKey | 11 from .utils.keyfactory import _createPublicRSAKey |
| 12 from .utils.pem import * |
| 6 | 13 |
| 7 | 14 |
| 8 class X509: | 15 class X509(object): |
| 9 """This class represents an X.509 certificate. | 16 """This class represents an X.509 certificate. |
| 10 | 17 |
| 11 @type bytes: L{array.array} of unsigned bytes | 18 @type bytes: L{bytearray} of unsigned bytes |
| 12 @ivar bytes: The DER-encoded ASN.1 certificate | 19 @ivar bytes: The DER-encoded ASN.1 certificate |
| 13 | 20 |
| 14 @type publicKey: L{tlslite.utils.RSAKey.RSAKey} | 21 @type publicKey: L{tlslite.utils.rsakey.RSAKey} |
| 15 @ivar publicKey: The subject public key from the certificate. | 22 @ivar publicKey: The subject public key from the certificate. |
| 16 | 23 |
| 17 @type subject: L{array.array} of unsigned bytes | 24 @type subject: L{bytearray} of unsigned bytes |
| 18 @ivar subject: The DER-encoded ASN.1 subject distinguished name. | 25 @ivar subject: The DER-encoded ASN.1 subject distinguished name. |
| 19 """ | 26 """ |
| 20 | 27 |
| 21 def __init__(self): | 28 def __init__(self): |
| 22 self.bytes = createByteArraySequence([]) | 29 self.bytes = bytearray(0) |
| 23 self.publicKey = None | 30 self.publicKey = None |
| 24 self.subject = None | 31 self.subject = None |
| 25 | 32 |
| 26 def parse(self, s): | 33 def parse(self, s): |
| 27 """Parse a PEM-encoded X.509 certificate. | 34 """Parse a PEM-encoded X.509 certificate. |
| 28 | 35 |
| 29 @type s: str | 36 @type s: str |
| 30 @param s: A PEM-encoded X.509 certificate (i.e. a base64-encoded | 37 @param s: A PEM-encoded X.509 certificate (i.e. a base64-encoded |
| 31 certificate wrapped with "-----BEGIN CERTIFICATE-----" and | 38 certificate wrapped with "-----BEGIN CERTIFICATE-----" and |
| 32 "-----END CERTIFICATE-----" tags). | 39 "-----END CERTIFICATE-----" tags). |
| 33 """ | 40 """ |
| 34 | 41 |
| 35 start = s.find("-----BEGIN CERTIFICATE-----") | 42 bytes = dePem(s, "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) | 43 self.parseBinary(bytes) |
| 45 return self | 44 return self |
| 46 | 45 |
| 47 def parseBinary(self, bytes): | 46 def parseBinary(self, bytes): |
| 48 """Parse a DER-encoded X.509 certificate. | 47 """Parse a DER-encoded X.509 certificate. |
| 49 | 48 |
| 50 @type bytes: str or L{array.array} of unsigned bytes | 49 @type bytes: str or L{bytearray} of unsigned bytes |
| 51 @param bytes: A DER-encoded X.509 certificate. | 50 @param bytes: A DER-encoded X.509 certificate. |
| 52 """ | 51 """ |
| 53 | 52 |
| 54 if isinstance(bytes, type("")): | 53 self.bytes = bytearray(bytes) |
| 55 bytes = stringToBytes(bytes) | |
| 56 | |
| 57 self.bytes = bytes | |
| 58 p = ASN1Parser(bytes) | 54 p = ASN1Parser(bytes) |
| 59 | 55 |
| 60 #Get the tbsCertificate | 56 #Get the tbsCertificate |
| 61 tbsCertificateP = p.getChild(0) | 57 tbsCertificateP = p.getChild(0) |
| 62 | 58 |
| 63 #Is the optional version field present? | 59 #Is the optional version field present? |
| 64 #This determines which index the key is at. | 60 #This determines which index the key is at. |
| 65 if tbsCertificateP.value[0]==0xA0: | 61 if tbsCertificateP.value[0]==0xA0: |
| 66 subjectPublicKeyInfoIndex = 6 | 62 subjectPublicKeyInfoIndex = 6 |
| 67 else: | 63 else: |
| (...skipping 24 matching lines...) Expand all Loading... |
| 92 #Get the modulus and exponent | 88 #Get the modulus and exponent |
| 93 modulusP = subjectPublicKeyP.getChild(0) | 89 modulusP = subjectPublicKeyP.getChild(0) |
| 94 publicExponentP = subjectPublicKeyP.getChild(1) | 90 publicExponentP = subjectPublicKeyP.getChild(1) |
| 95 | 91 |
| 96 #Decode them into numbers | 92 #Decode them into numbers |
| 97 n = bytesToNumber(modulusP.value) | 93 n = bytesToNumber(modulusP.value) |
| 98 e = bytesToNumber(publicExponentP.value) | 94 e = bytesToNumber(publicExponentP.value) |
| 99 | 95 |
| 100 #Create a public key instance | 96 #Create a public key instance |
| 101 self.publicKey = _createPublicRSAKey(n, e) | 97 self.publicKey = _createPublicRSAKey(n, e) |
| 102 return self | |
| 103 | 98 |
| 104 def getFingerprint(self): | 99 def getFingerprint(self): |
| 105 """Get the hex-encoded fingerprint of this certificate. | 100 """Get the hex-encoded fingerprint of this certificate. |
| 106 | 101 |
| 107 @rtype: str | 102 @rtype: str |
| 108 @return: A hex-encoded fingerprint. | 103 @return: A hex-encoded fingerprint. |
| 109 """ | 104 """ |
| 110 return sha.sha(self.bytes).hexdigest() | 105 return b2a_hex(SHA1(self.bytes)) |
| 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 | 106 |
| 139 def writeBytes(self): | 107 def writeBytes(self): |
| 140 return self.bytes | 108 return self.bytes |
| 141 | 109 |
| 142 | 110 |
| OLD | NEW |