]> www.wagner.pp.ru Git - oss/ctypescrypto.git/blobdiff - ctypescrypto/x509.py
Fixed most pylint warning.
[oss/ctypescrypto.git] / ctypescrypto / x509.py
index 159956d72f457dc3640a95db75007092f8408bb0..40263cffea5d1e26528bb989231a92808bfc86a2 100644 (file)
@@ -1,5 +1,5 @@
 """
-Implements interface to openssl X509 and X509Store structures, 
+Implements interface to openssl X509 and X509Store structures,
 I.e allows to load, analyze and verify certificates.
 
 X509Store objects are also used to verify other signed documets,
@@ -8,23 +8,23 @@ such as CMS, OCSP and timestamps.
 
 
 
-from ctypes import c_void_p,create_string_buffer,c_long,c_int,POINTER,c_char_p,Structure,cast
+from ctypes import c_void_p, c_long, c_int, POINTER, c_char_p, Structure, cast
 from ctypescrypto.bio import Membio
 from ctypescrypto.pkey import PKey
 from ctypescrypto.oid import Oid
 from ctypescrypto.exception import LibCryptoError
 from ctypescrypto import libcrypto
 from datetime import datetime
+
 try:
     from pytz import utc
 except ImportError:
-    from datetime import timedelta,tzinfo
-    ZERO=timedelta(0)
+    from datetime import timedelta, tzinfo
+    ZERO = timedelta(0)
     class UTC(tzinfo):
-        """tzinfo object for UTC. 
+        """tzinfo object for UTC.
             If no pytz is available, we would use it.
         """
-
         def utcoffset(self, dt):
             return ZERO
 
@@ -34,33 +34,33 @@ except ImportError:
         def dst(self, dt):
             return ZERO
 
-    utc=UTC()
+    utc = UTC()
 
-__all__ = ['X509','X509Error','X509Name','X509Store','StackOfX509']
+__all__ = ['X509', 'X509Error', 'X509Name', 'X509Store', 'StackOfX509']
 
 class _validity(Structure):
-    """ ctypes representation of X509_VAL structure 
+    """ ctypes representation of X509_VAL structure
         needed to access certificate validity period, because openssl
         doesn't provide fuctions for it - only macros
     """
-    _fields_ =  [('notBefore',c_void_p),('notAfter',c_void_p)]
+    _fields_ = [('notBefore', c_void_p), ('notAfter', c_void_p)]
 
 class _cinf(Structure):
-    """ ctypes representtion of X509_CINF structure 
+    """ ctypes representtion of X509_CINF structure
         neede to access certificate data, which are accessable only
         via macros
     """
-    _fields_ = [('version',c_void_p),
-        ('serialNumber',c_void_p),
-        ('sign_alg',c_void_p),
-        ('issuer',c_void_p),
-        ('validity',POINTER(_validity)),
-        ('subject',c_void_p),
-        ('pubkey',c_void_p),
-        ('issuerUID',c_void_p),
-        ('subjectUID',c_void_p),
-        ('extensions',c_void_p),
-        ]
+    _fields_ = [('version', c_void_p),
+                ('serialNumber', c_void_p),
+                ('sign_alg', c_void_p),
+                ('issuer', c_void_p),
+                ('validity', POINTER(_validity)),
+                ('subject', c_void_p),
+                ('pubkey', c_void_p),
+                ('issuerUID', c_void_p),
+                ('subjectUID', c_void_p),
+                ('extensions', c_void_p),
+               ]
 
 class _x509(Structure):
     """
@@ -68,11 +68,11 @@ class _x509(Structure):
     to access certificate data which are accesable only via
     macros, not functions
     """
-    _fields_ = [('cert_info',POINTER(_cinf)),
-                ('sig_alg',c_void_p),
-                ('signature',c_void_p),
+    _fields_ = [('cert_info', POINTER(_cinf)),
+                ('sig_alg', c_void_p),
+                ('signature', c_void_p),
                 # There are a lot of parsed extension fields there
-                ]
+               ]
 _px509 = POINTER(_x509)
 
 class X509Error(LibCryptoError):
@@ -85,7 +85,7 @@ class X509Error(LibCryptoError):
 
 class X509Name(object):
     """
-    Class which represents X.509 distinguished name - typically 
+    Class which represents X.509 distinguished name - typically
     a certificate subject name or an issuer name.
 
     Now used only to represent information, extracted from the
@@ -93,22 +93,25 @@ class X509Name(object):
     certificate signing request
     """
     # XN_FLAG_SEP_COMMA_PLUS & ASN1_STRFLG_UTF8_CONVERT
-    PRINT_FLAG=0x10010
-    ESC_MSB=4
-    def __init__(self,ptr=None,copy=False):
+    PRINT_FLAG = 0x10010
+    ESC_MSB = 4
+    def __init__(self, ptr=None, copy=False):
         """
         Creates a X509Name object
-        @param ptr - pointer to X509_NAME C structure (as returned by some  OpenSSL functions
-        @param copy - indicates that this structure have to be freed upon object destruction
+        @param ptr - pointer to X509_NAME C structure (as returned by some
+                     OpenSSL functions
+        @param copy - indicates that this structure have to be freed upon
+                      object destruction
         """
         if ptr is not None:
-            self.ptr=ptr
-            self.need_free=copy
-            self.writable=False
+            self.ptr = ptr
+            self.need_free = copy
+            self.writable = False
         else:
-            self.ptr=libcrypto.X509_NAME_new()
-            self.need_free=True
-            self.writable=True
+            self.ptr = libcrypto.X509_NAME_new()
+            self.need_free = True
+            self.writable = True
+
     def __del__(self):
         """
         Frees if neccessary
@@ -117,62 +120,65 @@ class X509Name(object):
             libcrypto.X509_NAME_free(self.ptr)
     def __str__(self):
         """
-        Produces an ascii representation of the name, escaping all symbols > 0x80
-        Probably it is not what you want, unless your native language is English
+        Produces an ascii representation of the name, escaping all
+        symbols > 0x80.  Probably it is not what you want, unless
+        your native language is English
         """
-        b=Membio()
-        libcrypto.X509_NAME_print_ex(b.bio,self.ptr,0,self.PRINT_FLAG | self.ESC_MSB)
-        return str(b)
+        bio = Membio()
+        libcrypto.X509_NAME_print_ex(bio.bio, self.ptr, 0,
+                                     self.PRINT_FLAG | self.ESC_MSB)
+        return str(bio)
+
     def __unicode__(self):
         """
-        Produces unicode representation of the name. 
+        Produces unicode representation of the name.
         """
-        b=Membio()
-        libcrypto.X509_NAME_print_ex(b.bio,self.ptr,0,self.PRINT_FLAG)
-        return unicode(b)
+        bio = Membio()
+        libcrypto.X509_NAME_print_ex(bio.bio, self.ptr, 0, self.PRINT_FLAG)
+        return unicode(bio)
     def __len__(self):
         """
         return number of components in the name
         """
         return libcrypto.X509_NAME_entry_count(self.ptr)
-    def __cmp__(self,other):
+    def __cmp__(self, other):
         """
         Compares X509 names
         """
-        return libcrypto.X509_NAME_cmp(self.ptr,other.ptr)
-    def __eq__(self,other):
-        return libcrypto.X509_NAME_cmp(self.ptr,other.ptr)==0
+        return libcrypto.X509_NAME_cmp(self.ptr, other.ptr)
+    def __eq__(self, other):
+        return libcrypto.X509_NAME_cmp(self.ptr, other.ptr) == 0
 
-    def __getitem__(self,key):
-        if isinstance(key,Oid):
+    def __getitem__(self, key):
+        if isinstance(key, Oid):
             # Return first matching field
-            idx=libcrypto.X509_NAME_get_index_by_NID(self.ptr,key.nid,-1)
-            if idx<0:
-                raise KeyError("Key not found "+str(Oid))
-            entry=libcrypto.X509_NAME_get_entry(self.ptr,idx)
-            s=libcrypto.X509_NAME_ENTRY_get_data(entry)
-            b=Membio()
-            libcrypto.ASN1_STRING_print_ex(b.bio,s,self.PRINT_FLAG)
-            return unicode(b)
-        elif isinstance(key,(int,long)):
+            idx = libcrypto.X509_NAME_get_index_by_NID(self.ptr, key.nid, -1)
+            if idx < 0:
+                raise KeyError("Key not found " + str(Oid))
+            entry = libcrypto.X509_NAME_get_entry(self.ptr, idx)
+            value = libcrypto.X509_NAME_ENTRY_get_data(entry)
+            bio = Membio()
+            libcrypto.ASN1_STRING_print_ex(bio.bio, value, self.PRINT_FLAG)
+            return unicode(bio)
+        elif isinstance(key, (int, long)):
             # Return OID, string tuple
-            entry=libcrypto.X509_NAME_get_entry(self.ptr,key)
+            entry = libcrypto.X509_NAME_get_entry(self.ptr, key)
             if entry is None:
                 raise IndexError("name entry index out of range")
-            oid=Oid.fromobj(libcrypto.X509_NAME_ENTRY_get_object(entry))
-            s=libcrypto.X509_NAME_ENTRY_get_data(entry)
-            b=Membio()
-            libcrypto.ASN1_STRING_print_ex(b.bio,s,self.PRINT_FLAG)
-            return (oid,unicode(b))
+            oid = Oid.fromobj(libcrypto.X509_NAME_ENTRY_get_object(entry))
+            value = libcrypto.X509_NAME_ENTRY_get_data(entry)
+            bio = Membio()
+            libcrypto.ASN1_STRING_print_ex(bio.bio, value, self.PRINT_FLAG)
+            return (oid, unicode(bio))
         else:
             raise TypeError("X509 NAME can be indexed by Oids or integers only")
 
-    def __setitem__(self,key,val):
+    def __setitem__(self, key, val):
         if not self.writable:
             raise ValueError("Attempt to modify constant X509 object")
         else:
             raise NotImplementedError
-    def __delitem__(self,key):
+    def __delitem__(self, key):
         if not self.writable:
             raise ValueError("Attempt to modify constant X509 object")
         else:
@@ -182,111 +188,140 @@ class X509Name(object):
 
 class _x509_ext(Structure):
     """ Represens C structure X509_EXTENSION """
-    _fields_=[("object",c_void_p),
-            ("critical",c_int),
-            ("value",c_void_p)]
+    _fields_ = [("object", c_void_p),
+                ("critical", c_int),
+                ("value", c_void_p)
+               ]
 
 class X509_EXT(object):
     """ Python object which represents a certificate extension """
-    def __init__(self,ptr,copy=False):
+    def __init__(self, ptr, copy=False):
         """ Initializes from the pointer to X509_EXTENSION.
             If copy is True, creates a copy, otherwise just
             stores pointer.
         """
         if copy:
-            self.ptr=libcrypto.X509_EXTENSION_dup(ptr)
+            self.ptr = libcrypto.X509_EXTENSION_dup(ptr)
         else:
-            self.ptr=cast(ptr,POINTER(_x509_ext))
+            self.ptr = cast(ptr, POINTER(_x509_ext))
     def __del__(self):
         libcrypto.X509_EXTENSION_free(self.ptr)
     def __str__(self):
-        b=Membio()
-        libcrypto.X509V3_EXT_print(b.bio,self.ptr,0x20010,0)
-        return str(b)
+        bio = Membio()
+        libcrypto.X509V3_EXT_print(bio.bio, self.ptr, 0x20010, 0)
+        return str(bio)
     def __unicode__(self):
-        b=Membio()
-        libcrypto.X509V3_EXT_print(b.bio,self.ptr,0x20010,0)
-        return unicode(b)
+        bio = Membio()
+        libcrypto.X509V3_EXT_print(bio.bio, self.ptr, 0x20010, 0)
+        return unicode(bio)
     @property
     def oid(self):
+        "Returns OID of the extension"
         return Oid.fromobj(self.ptr[0].object)
     @property
-    def critical(self): 
-        return self.ptr[0].critical >0
-class _X509extlist(object): 
+    def critical(self):
+        "Returns True if extensin have critical flag set"
+        return self.ptr[0].critical > 0
+
+class _X509extlist(object):
     """
-    Represents list of certificate extensions
+    Represents list of certificate extensions. Really it keeps
+    reference to certificate object
     """
-    def __init__(self,cert):
-        self.cert=cert
+    def __init__(self, cert):
+        """
+        Initialize from X509 object
+        """
+        self.cert = cert
+
     def __len__(self):
+        """
+        Returns number of extensions
+        """
         return libcrypto.X509_get_ext_count(self.cert.cert)
-    def __getitem__(self,item):
-        p=libcrypto.X509_get_ext(self.cert.cert,item)
-        if p is None:
+
+    def __getitem__(self, item):
+        """
+        Returns extension by index, creating a copy
+        """
+        ext_ptr = libcrypto.X509_get_ext(self.cert.cert, item)
+        if ext_ptr is None:
             raise IndexError
-        return X509_EXT(p,True)
-    def find(self,oid):
+        return X509_EXT(ext_ptr, True)
+    def find(self, oid):
         """
         Return list of extensions with given Oid
         """
-        if not isinstance(oid,Oid):
+        if not isinstance(oid, Oid):
             raise TypeError("Need crytypescrypto.oid.Oid as argument")
-        found=[]
-        l=-1
-        end=len(self)
+        found = []
+        index = -1
+        end = len(self)
         while True:
-            l=libcrypto.X509_get_ext_by_NID(self.cert.cert,oid.nid,l)
-            if l>=end or l<0:
-                 break
-            found.append(self[l])
+            index = libcrypto.X509_get_ext_by_NID(self.cert.cert, oid.nid,
+                                                  index)
+            if index >= end or index < 0:
+                break
+            found.append(self[index])
         return found
-    def find_critical(self,crit=True):
+
+    def find_critical(self, crit=True):
         """
         Return list of critical extensions (or list of non-cricital, if
         optional second argument is False
         """
         if crit:
-            flag=1
+            flag = 1
         else:
-            flag=0
-        found=[]
-        end=len(self)
-        l=-1
+            flag = 0
+        found = []
+        end = len(self)
+        index = -1
         while True:
-            l=libcrypto.X509_get_ext_by_critical(self.cert.cert,flag,l)
-            if l>=end or l<0:
-                 break
-            found.append(self[l])
-        return found            
+            index = libcrypto.X509_get_ext_by_critical(self.cert.cert, flag,
+                                                       index)
+            if index >= end or index < 0:
+                break
+            found.append(self[index])
+        return found
+
+def _X509__asn1date_to_datetime(asn1date):
+    """ 
+    Converts openssl ASN1_TIME object to python datetime.datetime
+    """
+    bio = Membio()
+    libcrypto.ASN1_TIME_print(bio.bio, asn1date)
+    pydate = datetime.strptime(str(bio), "%b %d %H:%M:%S %Y %Z")
+    return pydate.replace(tzinfo=utc)
 
 class X509(object):
     """
-    Represents X.509 certificate. 
+    Represents X.509 certificate.
     """
-    def __init__(self,data=None,ptr=None,format="PEM"):
+    def __init__(self, data=None, ptr=None, format="PEM"):
         """
         Initializes certificate
         @param data - serialized certificate in PEM or DER format.
-        @param ptr - pointer to X509, returned by some openssl function. 
+        @param ptr - pointer to X509, returned by some openssl function.
             mutually exclusive with data
         @param format - specifies data format. "PEM" or "DER", default PEM
         """
         if ptr is not None:
-            if data is not None: 
+            if data is not None:
                 raise TypeError("Cannot use data and ptr simultaneously")
             self.cert = ptr
         elif data is None:
             raise TypeError("data argument is required")
         else:
-            b=Membio(data)
+            bio = Membio(data)
             if format == "PEM":
-                self.cert=libcrypto.PEM_read_bio_X509(b.bio,None,None,None)
+                self.cert = libcrypto.PEM_read_bio_X509(bio.bio, None, None,
+                                                        None)
             else:
-                self.cert=libcrypto.d2i_X509_bio(b.bio,None)
+                self.cert = libcrypto.d2i_X509_bio(bio.bio, None)
             if self.cert is None:
                 raise X509Error("error reading certificate")
-        self.extensions=_X509extlist(self)      
+        self.extensions = _X509extlist(self)
     def __del__(self):
         """
         Frees certificate object
@@ -294,62 +329,63 @@ class X509(object):
         libcrypto.X509_free(self.cert)
     def __str__(self):
         """ Returns der string of the certificate """
-        b=Membio()
-        if libcrypto.i2d_X509_bio(b.bio,self.cert)==0:
+        bio = Membio()
+        if libcrypto.i2d_X509_bio(bio.bio, self.cert) == 0:
             raise X509Error("error serializing certificate")
-        return str(b)
+        return str(bio)
     def __repr__(self):
         """ Returns valid call to the constructor """
-        return "X509(data="+repr(str(self))+",format='DER')"
+        return "X509(data=" + repr(str(self)) + ",format='DER')"
     @property
     def pubkey(self):
         """EVP PKEy object of certificate public key"""
-        return PKey(ptr=libcrypto.X509_get_pubkey(self.cert,False))
+        return PKey(ptr=libcrypto.X509_get_pubkey(self.cert, False))
     def pem(self):
         """ Returns PEM represntation of the certificate """
-        b=Membio()
-        if libcrypto.PEM_write_bio_X509(b.bio,self.cert)==0:
+        bio = Membio()
+        if libcrypto.PEM_write_bio_X509(bio.bio, self.cert) == 0:
             raise X509Error("error serializing certificate")
-        return str(b)
-    def verify(self,store=None,chain=[],key=None):  
-        """ 
-        Verify self. Supports verification on both X509 store object 
+        return str(bio)
+    def verify(self, store=None, chain=None, key=None):
+        """
+        Verify self. Supports verification on both X509 store object
         or just public issuer key
         @param store X509Store object.
         @param chain - list of X509 objects to add into verification
             context.These objects are untrusted, but can be used to
             build certificate chain up to trusted object in the store
         @param key - PKey object with open key to validate signature
-        
-        parameters store and key are mutually exclusive. If neither 
+
+        parameters store and key are mutually exclusive. If neither
         is specified, attempts to verify self as self-signed certificate
         """
         if store is not None and key is not None:
             raise X509Error("key and store cannot be specified simultaneously")
         if store is not None:
-            ctx=libcrypto.X509_STORE_CTX_new()
+            ctx = libcrypto.X509_STORE_CTX_new()
             if ctx is None:
                 raise X509Error("Error allocating X509_STORE_CTX")
-            if chain is not None and len(chain)>0:
-                ch=StackOfX509(chain)
+            if chain is not None and len(chain) > 0:
+                chain_ptr = StackOfX509(chain).ptr
             else:
-                ch=None
-            if libcrypto.X509_STORE_CTX_init(ctx,store.store,self.cert,ch) < 0:
+                chain_ptr = None
+            if libcrypto.X509_STORE_CTX_init(ctx, store.store, self.cert,
+                                             chain_ptr) < 0:
                 raise X509Error("Error allocating X509_STORE_CTX")
-            res= libcrypto.X509_verify_cert(ctx)
+            res = libcrypto.X509_verify_cert(ctx)
             libcrypto.X509_STORE_CTX_free(ctx)
-            return res>0
+            return res > 0
         else:
             if key is None:
                 if self.issuer != self.subject:
                     # Not a self-signed certificate
                     return False
                 key = self.pubkey
-            res = libcrypto.X509_verify(self.cert,key.key)
+            res = libcrypto.X509_verify(self.cert, key.key)
             if res < 0:
                 raise X509Error("X509_verify failed")
-            return res>0
-            
+            return res > 0
+
     @property
     def subject(self):
         """ X509Name for certificate subject name """
@@ -361,134 +397,139 @@ class X509(object):
     @property
     def serial(self):
         """ Serial number of certificate as integer """
-        asnint=libcrypto.X509_get_serialNumber(self.cert)
-        b=Membio()
-        libcrypto.i2a_ASN1_INTEGER(b.bio,asnint)
-        return int(str(b),16)
-    @property 
+        asnint = libcrypto.X509_get_serialNumber(self.cert)
+        bio = Membio()
+        libcrypto.i2a_ASN1_INTEGER(bio.bio, asnint)
+        return int(str(bio), 16)
+    @property
     def version(self):
-        """ certificate version as integer. Really certificate stores 0 for
-        version 1 and 2 for version 3, but we return 1 and 3 """
-        asn1int=cast(self.cert,_px509)[0].cert_info[0].version
-        return libcrypto.ASN1_INTEGER_get(asn1int)+1
+        """
+        certificate version as integer. Really certificate stores 0 for
+        version 1 and 2 for version 3, but we return 1 and 3
+        """
+        asn1int = cast(self.cert, _px509)[0].cert_info[0].version
+        return libcrypto.ASN1_INTEGER_get(asn1int) + 1
     @property
     def startDate(self):
         """ Certificate validity period start date """
-        # Need deep poke into certificate structure (x)->cert_info->validity->notBefore 
-        global utc
-        asn1date=cast(self.cert,_px509)[0].cert_info[0].validity[0].notBefore
-        b=Membio()
-        libcrypto.ASN1_TIME_print(b.bio,asn1date)
-        return datetime.strptime(str(b),"%b %d %H:%M:%S %Y %Z").replace(tzinfo=utc)
+        # Need deep poke into certificate structure
+        # (x)->cert_info->validity->notBefore
+        asn1 = cast(self.cert, _px509)[0].cert_info[0].validity[0].notBefore
+        return __asn1date_to_datetime(asn1)
     @property
     def endDate(self):
         """ Certificate validity period end date """
-        # Need deep poke into certificate structure (x)->cert_info->validity->notAfter
-        global utc
-        asn1date=cast(self.cert,_px509)[0].cert_info[0].validity[0].notAfter
-        b=Membio()
-        libcrypto.ASN1_TIME_print(b.bio,asn1date)
-        return datetime.strptime(str(b),"%b %d %H:%M:%S %Y %Z").replace(tzinfo=utc)
+        # Need deep poke into certificate structure
+        # (x)->cert_info->validity->notAfter
+        asn1 = cast(self.cert, _px509)[0].cert_info[0].validity[0].notAfter
+        return __asn1date_to_datetime(asn1)
     def check_ca(self):
         """ Returns True if certificate is CA certificate """
-        return libcrypto.X509_check_ca(self.cert)>0
+        return libcrypto.X509_check_ca(self.cert) > 0
+
 class X509Store(object):
     """
-        Represents trusted certificate store. Can be used to lookup CA 
-        certificates to verify
+    Represents trusted certificate store. Can be used to lookup CA
+    certificates to verify
 
-        @param file - file with several certificates and crls 
-                to load into store
-        @param dir - hashed directory with certificates and crls
-        @param default - if true, default verify location (directory) 
-            is installed
+    @param file - file with several certificates and crls
+            to load into store
+    @param dir - hashed directory with certificates and crls
+    @param default - if true, default verify location (directory)
+        is installed
 
     """
-    def __init__(self,file=None,dir=None,default=False):
+    def __init__(self, file=None, dir=None, default=False):
         """
-        Creates X509 store and installs lookup method. Optionally initializes 
+        Creates X509 store and installs lookup method. Optionally initializes
         by certificates from given file or directory.
         """
         #
         # Todo - set verification flags
-        # 
-        self.store=libcrypto.X509_STORE_new()
+        #
+        self.store = libcrypto.X509_STORE_new()
         if self.store is None:
             raise X509Error("allocating store")
-        lookup=libcrypto.X509_STORE_add_lookup(self.store,libcrypto.X509_LOOKUP_file())
+        lookup = libcrypto.X509_STORE_add_lookup(self.store,
+                                                 libcrypto.X509_LOOKUP_file())
         if lookup is None:
             raise X509Error("error installing file lookup method")
-        if (file is not None):
-            if not libcrypto.X509_LOOKUP_ctrl(lookup,1,file,1,None)>0:
+        if file is not None:
+            if not libcrypto.X509_LOOKUP_ctrl(lookup, 1, file, 1, None) > 0:
                 raise X509Error("error loading trusted certs from file "+file)
-        lookup=libcrypto.X509_STORE_add_lookup(self.store,libcrypto.X509_LOOKUP_hash_dir())
+        lookup = libcrypto.X509_STORE_add_lookup(self.store,
+                                             libcrypto.X509_LOOKUP_hash_dir())
         if lookup is None:
             raise X509Error("error installing hashed lookup method")
         if dir is not None:
-            if not libcrypto.X509_LOOKUP_ctrl(lookup,2,dir,1,None)>0:
+            if not libcrypto.X509_LOOKUP_ctrl(lookup, 2, dir, 1, None) > 0:
                 raise X509Error("error adding hashed  trusted certs dir "+dir)
         if default:
-            if not libcrypto.X509_LOOKUP_ctrl(lookup,2,None,3,None)>0:
+            if not libcrypto.X509_LOOKUP_ctrl(lookup, 2, None, 3, None) > 0:
                 raise X509Error("error adding default trusted certs dir ")
-    def add_cert(self,cert):
+    def add_cert(self, cert):
         """
         Explicitely adds certificate to set of trusted in the store
         @param cert - X509 object to add
         """
-        if not isinstance(cert,X509):
+        if not isinstance(cert, X509):
             raise TypeError("cert should be X509")
-        libcrypto.X509_STORE_add_cert(self.store,cert.cert)
-    def add_callback(self,callback):
+        libcrypto.X509_STORE_add_cert(self.store, cert.cert)
+    def add_callback(self, callback):
         """
         Installs callback function, which would receive detailed information
         about verified ceritificates
         """
         raise NotImplementedError
-    def setflags(self,flags):
+    def setflags(self, flags):
         """
         Set certificate verification flags.
         @param flags - integer bit mask. See OpenSSL X509_V_FLAG_* constants
         """
-        libcrypto.X509_STORE_set_flags(self.store,flags)    
-    def setpurpose(self,purpose):
+        libcrypto.X509_STORE_set_flags(self.store, flags)
+    def setpurpose(self, purpose):
         """
         Sets certificate purpose which verified certificate should match
-        @param purpose - number from 1 to 9 or standard strind defined in Openssl
-        possible strings - sslcient,sslserver, nssslserver, smimesign,smimeencrypt, crlsign, any,ocsphelper
-        """
-        if isinstance(purpose,str):
-            purp_no=X509_PURPOSE_get_by_sname(purpose)
-            if purp_no <=0:
-                raise X509Error("Invalid certificate purpose '"+purpose+"'")
-        elif isinstance(purpose,int):
+        @param purpose - number from 1 to 9 or standard strind defined
+                         in Openssl
+        possible strings - sslcient,sslserver, nssslserver, smimesign,i
+                         smimeencrypt, crlsign, any, ocsphelper
+        """
+        if isinstance(purpose, str):
+            purp_no = libcrypto.X509_PURPOSE_get_by_sname(purpose)
+            if purp_no <= 0:
+                raise X509Error("Invalid certificate purpose '%s'" % purpose)
+        elif isinstance(purpose, int):
             purp_no = purpose
-        if libcrypto.X509_STORE_set_purpose(self.store,purp_no)<=0:
+        if libcrypto.X509_STORE_set_purpose(self.store, purp_no) <= 0:
             raise X509Error("cannot set purpose")
-    def setdepth(self,depth):
+    def setdepth(self, depth):
         """
         Sets the verification depth i.e. max length of certificate chain
         which is acceptable
         """
-        libcrypto.X509_STORE_set_depth(self.store,depth)
+        libcrypto.X509_STORE_set_depth(self.store, depth)
     def settime(self, time):
         """
         Set point in time used to check validity of certificates for
         Time can be either python datetime object or number of seconds
         sinse epoch
         """
-        if isinstance(time,datetime.datetime) or isinstance(time,datetime.date):
-            d=int(time.strftime("%s"))
-        elif isinstance(time,int):
-            pass
+        if isinstance(time, datetime) or isinstance(time,
+                                                             datetime.date):
+            seconds = int(time.strftime("%s"))
+        elif isinstance(time, int):
+            seconds = time
         else:
-            raise TypeError("datetime.date, datetime.datetime or integer is required as time argument")
+            raise TypeError("datetime.date, datetime.datetime or integer " +
+                            "is required as time argument")
         raise NotImplementedError
 class StackOfX509(object):
     """
     Implements OpenSSL STACK_OF(X509) object.
     It looks much like python container types
     """
-    def __init__(self,certs=None,ptr=None,disposable=True):
+    def __init__(self, certs=None, ptr=None, disposable=True):
         """
         Create stack
         @param certs - list of X509 objects. If specified, read-write
@@ -502,83 +543,89 @@ class StackOfX509(object):
         """
         if  ptr is None:
             self.need_free = True
-            self.ptr=libcrypto.sk_new_null()
+            self.ptr = libcrypto.sk_new_null()
             if certs is not None:
                 for crt in certs:
                     self.append(crt)
         elif certs is not None:
-                raise ValueError("cannot handle certs an ptr simultaneously")
+            raise ValueError("cannot handle certs an ptr simultaneously")
         else:
             self.need_free = disposable
-            self.ptr=ptr
+            self.ptr = ptr
     def __len__(self):
         return libcrypto.sk_num(self.ptr)
-    def __getitem__(self,index):
-        if index <0 or index>=len(self):
+    def __getitem__(self, index):
+        if index < 0 or index >= len(self):
             raise IndexError
-        p=libcrypto.sk_value(self.ptr,index)
+        p = libcrypto.sk_value(self.ptr, index)
         return X509(ptr=libcrypto.X509_dup(p))
-    def __setitem__(self,index,value):
+    def __setitem__(self, index, value):
         if not self.need_free:
             raise ValueError("Stack is read-only")
-        if index <0 or index>=len(self):
+        if index < 0 or index >= len(self):
             raise IndexError
-        if not isinstance(value,X509):
+        if not isinstance(value, X509):
             raise TypeError('StackOfX508 can contain only X509 objects')
-        p=libcrypto.sk_value(self.ptr,index)
-        libcrypto.sk_set(self.ptr,index,libcrypto.X509_dup(value.cert))
+        p = libcrypto.sk_value(self.ptr, index)
+        libcrypto.sk_set(self.ptr, index, libcrypto.X509_dup(value.cert))
         libcrypto.X509_free(p)
-    def __delitem__(self,index):    
+    def __delitem__(self, index):
         if not self.need_free:
             raise ValueError("Stack is read-only")
-        if index <0 or index>=len(self):
+        if index < 0 or index >= len(self):
             raise IndexError
-        p=libcrypto.sk_delete(self.ptr,index)
+        p = libcrypto.sk_delete(self.ptr, index)
         libcrypto.X509_free(p)
     def __del__(self):
         if self.need_free:
-            libcrypto.sk_pop_free(self.ptr,libcrypto.X509_free)
-    def append(self,value):
+            libcrypto.sk_pop_free(self.ptr, libcrypto.X509_free)
+    def append(self, value):
+        """ Adds certificate to stack """
         if not self.need_free:
             raise ValueError("Stack is read-only")
-        if not isinstance(value,X509):
+        if not isinstance(value, X509):
             raise TypeError('StackOfX508 can contain only X509 objects')
-        libcrypto.sk_push(self.ptr,libcrypto.X509_dup(value.cert))
-libcrypto.i2a_ASN1_INTEGER.argtypes=(c_void_p,c_void_p)
-libcrypto.ASN1_STRING_print_ex.argtypes=(c_void_p,c_void_p,c_long)
-libcrypto.PEM_read_bio_X509.restype=c_void_p
-libcrypto.PEM_read_bio_X509.argtypes=(c_void_p,POINTER(c_void_p),c_void_p,c_void_p)
-libcrypto.PEM_write_bio_X509.restype=c_int
-libcrypto.PEM_write_bio_X509.argtypes=(c_void_p,c_void_p)
-libcrypto.ASN1_TIME_print.argtypes=(c_void_p,c_void_p)
-libcrypto.ASN1_INTEGER_get.argtypes=(c_void_p,)
-libcrypto.ASN1_INTEGER_get.restype=c_long
-libcrypto.X509_get_serialNumber.argtypes=(c_void_p,)
-libcrypto.X509_get_serialNumber.restype=c_void_p
-libcrypto.X509_NAME_ENTRY_get_object.restype=c_void_p
-libcrypto.X509_NAME_ENTRY_get_object.argtypes=(c_void_p,)
-libcrypto.OBJ_obj2nid.argtypes=(c_void_p,)
-libcrypto.X509_NAME_get_entry.restype=c_void_p
-libcrypto.X509_NAME_get_entry.argtypes=(c_void_p,c_int)
-libcrypto.X509_STORE_new.restype=c_void_p
-libcrypto.X509_STORE_add_lookup.restype=c_void_p
-libcrypto.X509_STORE_add_lookup.argtypes=(c_void_p,c_void_p)
-libcrypto.X509_LOOKUP_file.restype=c_void_p
-libcrypto.X509_LOOKUP_hash_dir.restype=c_void_p
-libcrypto.X509_LOOKUP_ctrl.restype=c_int
-libcrypto.X509_LOOKUP_ctrl.argtypes=(c_void_p,c_int,c_char_p,c_long,POINTER(c_char_p))
-libcrypto.X509_EXTENSION_dup.argtypes=(c_void_p,)
-libcrypto.X509_EXTENSION_dup.restype=POINTER(_x509_ext)
-libcrypto.X509V3_EXT_print.argtypes=(c_void_p,POINTER(_x509_ext),c_long,c_int)
-libcrypto.X509_get_ext.restype=c_void_p
-libcrypto.X509_get_ext.argtypes=(c_void_p,c_int)
-libcrypto.X509V3_EXT_print.argtypes=(c_void_p,POINTER(_x509_ext),c_long,c_int)
-libcrypto.sk_set.argtypes=(c_void_p,c_int,c_void_p)
-libcrypto.sk_set.restype=c_void_p
-libcrypto.sk_value.argtypes=(c_void_p,c_int)
-libcrypto.sk_value.restype=c_void_p
-libcrypto.X509_dup.restype=c_void_p
-libcrypto.sk_new_null.restype=c_void_p
-libcrypto.X509_dup.argtypes=(c_void_p,)
-libcrypto.X509_NAME_hash.restype=c_long
-libcrypto.X509_NAME_hash.argtypes=(c_void_p,)
+        libcrypto.sk_push(self.ptr, libcrypto.X509_dup(value.cert))
+
+libcrypto.i2a_ASN1_INTEGER.argtypes = (c_void_p, c_void_p)
+libcrypto.ASN1_STRING_print_ex.argtypes = (c_void_p, c_void_p, c_long)
+libcrypto.PEM_read_bio_X509.restype = c_void_p
+libcrypto.PEM_read_bio_X509.argtypes = (c_void_p, POINTER(c_void_p),
+                                        c_void_p, c_void_p)
+libcrypto.PEM_write_bio_X509.restype = c_int
+libcrypto.PEM_write_bio_X509.argtypes = (c_void_p, c_void_p)
+libcrypto.ASN1_TIME_print.argtypes = (c_void_p, c_void_p)
+libcrypto.ASN1_INTEGER_get.argtypes = (c_void_p, )
+libcrypto.ASN1_INTEGER_get.restype = c_long
+libcrypto.X509_get_serialNumber.argtypes = (c_void_p, )
+libcrypto.X509_get_serialNumber.restype = c_void_p
+libcrypto.X509_NAME_ENTRY_get_object.restype = c_void_p
+libcrypto.X509_NAME_ENTRY_get_object.argtypes = (c_void_p, )
+libcrypto.OBJ_obj2nid.argtypes = (c_void_p, )
+libcrypto.X509_NAME_get_entry.restype = c_void_p
+libcrypto.X509_NAME_get_entry.argtypes = (c_void_p, c_int)
+libcrypto.X509_STORE_new.restype = c_void_p
+libcrypto.X509_STORE_add_lookup.restype = c_void_p
+libcrypto.X509_STORE_add_lookup.argtypes = (c_void_p, c_void_p)
+libcrypto.X509_LOOKUP_file.restype = c_void_p
+libcrypto.X509_LOOKUP_hash_dir.restype = c_void_p
+libcrypto.X509_LOOKUP_ctrl.restype = c_int
+libcrypto.X509_LOOKUP_ctrl.argtypes = (c_void_p, c_int, c_char_p, c_long,
+                                       POINTER(c_char_p))
+libcrypto.X509_EXTENSION_dup.argtypes = (c_void_p, )
+libcrypto.X509_EXTENSION_dup.restype = POINTER(_x509_ext)
+libcrypto.X509V3_EXT_print.argtypes = (c_void_p, POINTER(_x509_ext), c_long,
+                                       c_int)
+libcrypto.X509_get_ext.restype = c_void_p
+libcrypto.X509_get_ext.argtypes = (c_void_p, c_int)
+libcrypto.X509V3_EXT_print.argtypes = (c_void_p, POINTER(_x509_ext), c_long,
+                                       c_int)
+libcrypto.sk_set.argtypes = (c_void_p, c_int, c_void_p)
+libcrypto.sk_set.restype = c_void_p
+libcrypto.sk_value.argtypes = (c_void_p, c_int)
+libcrypto.sk_value.restype = c_void_p
+libcrypto.X509_dup.restype = c_void_p
+libcrypto.sk_new_null.restype = c_void_p
+libcrypto.X509_dup.argtypes = (c_void_p, )
+libcrypto.X509_NAME_hash.restype = c_long
+libcrypto.X509_NAME_hash.argtypes = (c_void_p, )