X-Git-Url: https://www.wagner.pp.ru/gitweb/?a=blobdiff_plain;f=ctypescrypto%2Foid.py;h=516c2e9e1331416209de3002d3b0a6f28fabe0a9;hb=876630b04080b68d724e22066d374ce25efd8a97;hp=85b3aa03d888b8564f97c4b677309d3a71978177;hpb=954b6dc9e3312f8d8b49f20f8466e6d2a8342f35;p=oss%2Fctypescrypto.git diff --git a/ctypescrypto/oid.py b/ctypescrypto/oid.py index 85b3aa0..516c2e9 100644 --- a/ctypescrypto/oid.py +++ b/ctypescrypto/oid.py @@ -1,58 +1,82 @@ -""" - Interface to OpenSSL object identifier database. +""" +Interface to OpenSSL object identifier database. + +It is primarily intended to deal with OIDs which are compiled into the +database or defined in the openssl configuration files. - It is primarily intended to deal with OIDs which are compiled into the - database or defined in the openssl configuration files. +But see create() function. - But see create() function +OpenSSL maintains database of OIDs, which contain long and short +human-readable names, which correspond to Oid as well as canonical +dotted-decimal representation, and links it to small integer, named +numeric identifier or 'nid'. Most OpenSSL functions which deals with +ASN.1 structures such as certificates or cryptographic messages, +expect or return nids, but it is very bad idea to hardcode nids into +your app, because it can change after mere recompilation of OpenSSL +library. +This module provides Oid object which represents entry to OpenSSL +OID database. """ from ctypescrypto import libcrypto from ctypes import c_char_p, c_void_p, c_int, create_string_buffer +from ctypescrypto.exception import LibCryptoError -__all__ = ['Oid','create','cleanup'] +__all__ = ['Oid', 'create', 'cleanup'] class Oid(object): """ - Represents an OID. It can be consturucted by textual - representation like Oid("commonName") or Oid("CN"), - dotted-decimal Oid("1.2.3.4") or using OpenSSL numeric - identifer (NID), which is typically returned or required by - OpenSSL API functions. If object is consturcted from textual - representation which is not present in the database, it fails - with ValueError + Represents an OID (ASN.1 Object identifier). - attribute nid - contains object nid. + It can be consturucted by textual + representation like Oid("commonName") or Oid("CN"), + dotted-decimal Oid("1.2.3.4") or using OpenSSL numeric + identifer (NID), which is typically returned or required by + OpenSSL API functions. If object is consturcted from textual + representation which is not present in the database, it fails + with ValueError + attribute nid - contains object nid. """ - def __init__(self,value): - " Object constuctor. Accepts string or integer" - if isinstance(value,unicode): - value=value.encode('ascii') - if isinstance(value,str): - self.nid=libcrypto.OBJ_txt2nid(value) - if self.nid==0: - raise ValueError("Cannot find object %s in the database"%(value)) - elif isinstance(value,(int,long)): - cn=libcrypto.OBJ_nid2sn(value) - if cn is None: - raise ValueError("No such nid %d in the database"%(value)) - self.nid=value + def __init__(self, value): + """ + Object constructor. Accepts string, integer, or another Oid + object. + + Integer should be OpenSSL numeric identifier (nid) as returned + by some libcrypto function or extracted from some libcrypto + structure + """ + if isinstance(value, unicode): + value = value.encode('ascii') + if isinstance(value, str): + self.nid = libcrypto.OBJ_txt2nid(value) + if self.nid == 0: + raise ValueError("Cannot find object %s in the database" % + value) + elif isinstance(value, (int, long)): + short = libcrypto.OBJ_nid2sn(value) + if short is None: + raise ValueError("No such nid %d in the database" % value) + self.nid = value + elif isinstance(value, Oid): + self.nid = value.nid else: raise TypeError("Cannot convert this type to object identifier") def __hash__(self): - " Returns NID " + " Hash of object is equal to nid because Oids with same nid are same" return self.nid - def __cmp__(self,other): + def __cmp__(self, other): " Compares NIDs of two objects " - return self.nid-other.nid + return self.nid - other.nid def __str__(self): - " Default string representation of Oid is dotted-decimal" + " Default string representation of Oid is dotted-decimal " return self.dotted() def __repr__(self): - return "Oid('%s')"%(self.dotted()) + " Returns constructor call of Oid with dotted representation " + return "Oid('%s')" % (self.dotted()) def shortname(self): " Returns short name if any " return libcrypto.OBJ_nid2sn(self.nid) @@ -61,57 +85,65 @@ class Oid(object): return libcrypto.OBJ_nid2ln(self.nid) def dotted(self): " Returns dotted-decimal reperesentation " - obj=libcrypto.OBJ_nid2obj(self.nid) - buf=create_string_buffer(256) - libcrypto.OBJ_obj2txt(buf,256,obj,1) + obj = libcrypto.OBJ_nid2obj(self.nid) + buf = create_string_buffer(256) + libcrypto.OBJ_obj2txt(buf, 256, obj, 1) return buf.value @staticmethod def fromobj(obj): """ Creates an OID object from the pointer to ASN1_OBJECT c structure. - Strictly for internal use + This method intended for internal use for submodules which deal + with libcrypto ASN1 parsing functions, such as x509 or CMS """ - nid=libcrypto.OBJ_obj2nid(obj) - if nid==0: - buf=create_string_buffer(80) - l=libcrypto.OBJ_obj2txt(buf,80,obj,1) - oid=create(buf[0:l],buf[0:l],buf[0:l]) + nid = libcrypto.OBJ_obj2nid(obj) + if nid == 0: + buf = create_string_buffer(80) + dotted_len = libcrypto.OBJ_obj2txt(buf, 80, obj, 1) + dotted = buf[:dotted_len] + oid = create(dotted, dotted, dotted) else: - oid=Oid(nid) + oid = Oid(nid) return oid -def create(dotted,shortname,longname): +def create(dotted, shortname, longname): """ - Creates new OID in the database + Creates new OID in the database - @param dotted - dotted-decimal representation of new OID - @param shortname - short name for new OID - @param longname - long name for new OID + @param dotted - dotted-decimal representation of new OID + @param shortname - short name for new OID + @param longname - long name for new OID - @returns Oid object corresponding to new OID - - This function should be used with exreme care. Whenever - possible, it is better to add new OIDs via OpenSSL configuration - file + @returns Oid object corresponding to new OID + + This function should be used with exreme care. Whenever + possible, it is better to add new OIDs via OpenSSL configuration + file + + Results of calling this function twice for same OIDor for + Oid alredy in database are undefined - Results of calling this function twice for same OIDor for - Oid alredy in database are undefined """ - nid=libcrypto.OBJ_create(dotted,shortname,longname) + nid = libcrypto.OBJ_create(dotted, shortname, longname) if nid == 0: raise LibCryptoError("Problem adding new OID to the database") return Oid(nid) def cleanup(): """ - Removes all the objects, dynamically added by current - application from database. + Removes all the objects, dynamically added by current + application from database. + + Note that in OpenSSL 1.1.0 and above OBJ_cleanup really does nothing """ - libcrypto.OBJ_cleanup() - -libcrypto.OBJ_nid2sn.restype=c_char_p -libcrypto.OBJ_nid2ln.restype=c_char_p -libcrypto.OBJ_nid2obj.restype=c_void_p -libcrypto.OBJ_obj2txt.argtypes=(c_char_p,c_int,c_void_p,c_int) -libcrypto.OBJ_txt2nid.argtupes=(c_char_p,) -libcrypto.OBJ_create.argtypes=(c_char_p,c_char_p,c_char_p) + if hasattr(libcrypto,"OBJ_cleanup"): + libcrypto.OBJ_cleanup() + +libcrypto.OBJ_nid2sn.restype = c_char_p +libcrypto.OBJ_nid2ln.restype = c_char_p +libcrypto.OBJ_nid2obj.restype = c_void_p +libcrypto.OBJ_obj2nid.restype = c_int +libcrypto.OBJ_obj2txt.argtypes = (c_char_p, c_int, c_void_p, c_int) +libcrypto.OBJ_txt2nid.argtupes = (c_char_p, ) +libcrypto.OBJ_obj2nid.argtupes = (c_void_p, ) +libcrypto.OBJ_create.argtypes = (c_char_p, c_char_p, c_char_p)