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 7"""Class representing an X.509 certificate.""" 8 9from .utils.asn1parser import ASN1Parser 10from .utils.cryptomath import * 11from .utils.keyfactory import _createPublicRSAKey 12from .utils.pem import * 13 14 15class X509(object): 16 """This class represents an X.509 certificate. 17 18 @type bytes: L{bytearray} of unsigned bytes 19 @ivar bytes: The DER-encoded ASN.1 certificate 20 21 @type publicKey: L{tlslite.utils.rsakey.RSAKey} 22 @ivar publicKey: The subject public key from the certificate. 23 24 @type subject: L{bytearray} of unsigned bytes 25 @ivar subject: The DER-encoded ASN.1 subject distinguished name. 26 """ 27 28 def __init__(self): 29 self.bytes = bytearray(0) 30 self.publicKey = None 31 self.subject = None 32 33 def parse(self, s): 34 """Parse a PEM-encoded X.509 certificate. 35 36 @type s: str 37 @param s: A PEM-encoded X.509 certificate (i.e. a base64-encoded 38 certificate wrapped with "-----BEGIN CERTIFICATE-----" and 39 "-----END CERTIFICATE-----" tags). 40 """ 41 42 bytes = dePem(s, "CERTIFICATE") 43 self.parseBinary(bytes) 44 return self 45 46 def parseBinary(self, bytes): 47 """Parse a DER-encoded X.509 certificate. 48 49 @type bytes: str or L{bytearray} of unsigned bytes 50 @param bytes: A DER-encoded X.509 certificate. 51 """ 52 53 self.bytes = bytearray(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 subject 67 self.subject = tbsCertificateP.getChildBytes(\ 68 subjectPublicKeyInfoIndex - 1) 69 70 #Get the subjectPublicKeyInfo 71 subjectPublicKeyInfoP = tbsCertificateP.getChild(\ 72 subjectPublicKeyInfoIndex) 73 74 #Get the algorithm 75 algorithmP = subjectPublicKeyInfoP.getChild(0) 76 rsaOID = algorithmP.value 77 if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]: 78 raise SyntaxError("Unrecognized AlgorithmIdentifier") 79 80 #Get the subjectPublicKey 81 subjectPublicKeyP = subjectPublicKeyInfoP.getChild(1) 82 83 #Adjust for BIT STRING encapsulation 84 if (subjectPublicKeyP.value[0] !=0): 85 raise SyntaxError() 86 subjectPublicKeyP = ASN1Parser(subjectPublicKeyP.value[1:]) 87 88 #Get the modulus and exponent 89 modulusP = subjectPublicKeyP.getChild(0) 90 publicExponentP = subjectPublicKeyP.getChild(1) 91 92 #Decode them into numbers 93 n = bytesToNumber(modulusP.value) 94 e = bytesToNumber(publicExponentP.value) 95 96 #Create a public key instance 97 self.publicKey = _createPublicRSAKey(n, e) 98 99 def getFingerprint(self): 100 """Get the hex-encoded fingerprint of this certificate. 101 102 @rtype: str 103 @return: A hex-encoded fingerprint. 104 """ 105 return b2a_hex(SHA1(self.bytes)) 106 107 def writeBytes(self): 108 return self.bytes 109 110 111