]> www.wagner.pp.ru Git - oss/ctypescrypto.git/blob - ctypescrypto/oid.py
ff1684613ce5c948ae42925cdd1e469991ebe05a
[oss/ctypescrypto.git] / ctypescrypto / oid.py
1 """
2 Interface to OpenSSL object identifier database.
3
4 It is primarily intended to deal with OIDs which are compiled into the
5 database or defined in the openssl configuration files.
6
7 But see create() function.
8
9 OpenSSL maintains database of OIDs, which contain long and short
10 human-readable names, which correspond to Oid as well as canonical
11 dotted-decimal representation, and links it to small integer, named
12 numeric identifier or 'nid'. Most OpenSSL functions which deals with
13 ASN.1 structures such as certificates or cryptographic messages,
14 expect or return nids, but it is very bad idea to hardcode nids into
15 your app, because it can change after mere recompilation of OpenSSL
16 library.
17
18 This module provides Oid object which represents entry to OpenSSL
19 OID database.
20 """
21 from ctypescrypto import libcrypto
22 from ctypes import c_char_p, c_void_p, c_int, create_string_buffer
23 from ctypescrypto.exception import LibCryptoError
24
25 __all__ = ['Oid', 'create', 'cleanup']
26
27 class Oid(object):
28     """
29     Represents an OID (ASN.1 Object identifier).
30
31
32     It can be consturucted by textual
33     representation like Oid("commonName") or Oid("CN"),
34     dotted-decimal Oid("1.2.3.4") or using OpenSSL numeric
35     identifer (NID), which is typically returned or required by
36     OpenSSL API functions. If object is consturcted from textual
37     representation which is not present in the database, it fails
38     with ValueError
39
40     attribute nid - contains object nid.
41     """
42
43     def __init__(self, value):
44         """
45         Object constructor. Accepts string, integer, or another Oid
46         object.
47
48         Integer should be OpenSSL numeric identifier (nid) as returned
49         by some libcrypto function or extracted from some libcrypto
50         structure
51         """
52         if isinstance(value, unicode):
53             value = value.encode('ascii')
54         if isinstance(value, str):
55             self.nid = libcrypto.OBJ_txt2nid(value)
56             if self.nid == 0:
57                 raise ValueError("Cannot find object %s in the database" %
58                                  value)
59         elif isinstance(value, (int, long)):
60             short = libcrypto.OBJ_nid2sn(value)
61             if short is None:
62                 raise ValueError("No such nid %d in the database" % value)
63             self.nid = value
64         elif isinstance(value, Oid):
65             self.nid = value.nid
66         else:
67             raise TypeError("Cannot convert this type to object identifier")
68     def __hash__(self):
69         " Hash of object is equal to nid because Oids with same nid are same"
70         return self.nid
71     def __cmp__(self, other):
72         " Compares NIDs of two objects "
73         return self.nid - other.nid
74     def __str__(self):
75         " Default string representation of Oid is dotted-decimal "
76         return self.dotted()
77     def __repr__(self):
78         " Returns constructor call of Oid with dotted representation "
79         return "Oid('%s')" % (self.dotted())
80     def shortname(self):
81         " Returns short name if any "
82         return libcrypto.OBJ_nid2sn(self.nid)
83     def longname(self):
84         " Returns logn name if any "
85         return  libcrypto.OBJ_nid2ln(self.nid)
86     def dotted(self):
87         " Returns dotted-decimal reperesentation "
88         obj = libcrypto.OBJ_nid2obj(self.nid)
89         buf = create_string_buffer(256)
90         libcrypto.OBJ_obj2txt(buf, 256, obj, 1)
91         return buf.value
92     @staticmethod
93     def fromobj(obj):
94         """
95         Creates an OID object from the pointer to ASN1_OBJECT c structure.
96         This method intended for internal use for submodules which deal
97         with libcrypto ASN1 parsing functions, such as x509 or CMS
98         """
99         nid = libcrypto.OBJ_obj2nid(obj)
100         if nid == 0:
101             buf = create_string_buffer(80)
102             dotted_len = libcrypto.OBJ_obj2txt(buf, 80, obj, 1)
103             dotted = buf[:dotted_len]
104             oid = create(dotted, dotted, dotted)
105         else:
106             oid = Oid(nid)
107         return oid
108
109 def create(dotted, shortname, longname):
110     """
111     Creates new OID in the database
112
113     @param dotted - dotted-decimal representation of new OID
114     @param shortname - short name for new OID
115     @param longname - long name for new OID
116
117     @returns Oid object corresponding to new OID
118
119     This function should be used with exreme care. Whenever
120     possible, it is better to add new OIDs via OpenSSL configuration
121     file
122
123     Results of calling this function twice for same OIDor for
124     Oid alredy in database are undefined
125
126     """
127     nid = libcrypto.OBJ_create(dotted, shortname, longname)
128     if nid == 0:
129         raise LibCryptoError("Problem adding new OID to the  database")
130     return Oid(nid)
131
132 def cleanup():
133     """
134     Removes all the objects, dynamically added by current
135     application from database.
136     """
137     libcrypto.OBJ_cleanup()
138
139 libcrypto.OBJ_nid2sn.restype = c_char_p
140 libcrypto.OBJ_nid2ln.restype = c_char_p
141 libcrypto.OBJ_nid2obj.restype = c_void_p
142 libcrypto.OBJ_obj2nid.restype = c_int
143 libcrypto.OBJ_obj2txt.argtypes = (c_char_p, c_int, c_void_p, c_int)
144 libcrypto.OBJ_txt2nid.argtupes = (c_char_p, )
145 libcrypto.OBJ_obj2nid.argtupes = (c_void_p, )
146 libcrypto.OBJ_create.argtypes = (c_char_p, c_char_p, c_char_p)