2013-02-28 2 views
1

Я пишу небольшую обертку для OpenSLL libeay32.dll в Python. Для большинства функций можно импортировать их следующим образом:Wrapper для libeay32.dll: как импортировать макрос?

self.Function_Name = self._dll.Function_Name 
self.Function_Name.restype = ctypes.c_int #for example 
self.Function_Name.argtypes = [list of ctypes arguments] 

К сожалению, я не в состоянии импортировать этот путь любые макросы:

X509_get_notAfter, X509_get_notBefore и т.д.

Любые идеи, как сделать это с ctypes?

+0

Вы не можете импортировать «функции, определенные как макросы» beca они не существуют в библиотеке. – wRAR

ответ

0

После некоторых исследований я решил ответить на свой вопрос. Макрос для X509_get_notAfter выглядит следующим образом:

#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter) 

х - это X509 структура, которая содержит структуру X509_CINF, которая содержит структуру X509_VAL, которые содержат указатель на NotAfter :)

Так что мой план реализовать весь X509, X509_CINF и X509_VAL в коде python.

В C это выглядит следующим образом

struct x509_st 
{ 
X509_CINF *cert_info; 
X509_ALGOR *sig_alg; 
ASN1_BIT_STRING *signature; 
int valid; 
int references; 
char *name; 
CRYPTO_EX_DATA ex_data; 
/* These contain copies of various extension values */ 
long ex_pathlen; 
long ex_pcpathlen; 
unsigned long ex_flags; 
unsigned long ex_kusage; 
unsigned long ex_xkusage; 
unsigned long ex_nscert; 
ASN1_OCTET_STRING *skid; 
AUTHORITY_KEYID *akid; 
X509_POLICY_CACHE *policy_cache; 
STACK_OF(DIST_POINT) *crldp; 
STACK_OF(GENERAL_NAME) *altname; 
NAME_CONSTRAINTS *nc; 
#ifndef OPENSSL_NO_RFC3779 
STACK_OF(IPAddressFamily) *rfc3779_addr; 
struct ASIdentifiers_st *rfc3779_asid; 
#endif 
#ifndef OPENSSL_NO_SHA 
unsigned char sha1_hash[SHA_DIGEST_LENGTH]; 
#endif 
X509_CERT_AUX *aux; 
} /* X509 */; 

И X509_CINF выглядит следующим образом:

typedef struct x509_cinf_st 
{ 
ASN1_INTEGER *version;  /* [ 0 ] default of v1 */ 
ASN1_INTEGER *serialNumber; 
X509_ALGOR *signature; 
X509_NAME *issuer; 
X509_VAL *validity; 
X509_NAME *subject; 
X509_PUBKEY *key; 
ASN1_BIT_STRING *issuerUID;  /* [ 1 ] optional in v2 */ 
ASN1_BIT_STRING *subjectUID;  /* [ 2 ] optional in v2 */ 
STACK_OF(X509_EXTENSION) *extensions; /* [ 3 ] optional in v3 */ 
ASN1_ENCODING enc; 
} X509_CINF; 

А вот X509_VAL:

typedef struct X509_val_st 
{ 
ASN1_TIME *notBefore; 
ASN1_TIME *notAfter; 
} X509_VAL; 

Чтобы сделать всю задачу, я решил заменить все указатели на структуры, к которым я не хочу обращаться с помощью ctypes.c_void_p

Так что мой питон код теперь выглядит так:

class X509_val_st(ctypes.Structure): 

_fields_ = [('notBefore',  ctypes.c_void_p), 
      ('notAfter',  ctypes.c_void_p)] 


class X509_cinf_st(ctypes.Structure): 

_fields_ = [('version',   ctypes.c_void_p), 
      ('serialNumber', ctypes.c_void_p), 
      ('signature',  ctypes.c_void_p), 
      ('issuer',   ctypes.c_void_p), 
      ('validity',  X509_val_st), 
      ('subject',   ctypes.c_void_p), 
      ('key',    ctypes.c_void_p), 
      ('issuerUID',  ctypes.c_void_p), 
      ('subjectUID',  ctypes.c_void_p), 
      ('extensions',  ctypes.c_void_p), 
      ('enc',    ctypes.c_uint)] 


class X509_st(ctypes.Structure): 

_fields_ = [('cert_info',  X509_cinf_st), 
      ('sig_alg',  ctypes.c_void_p), 
      ('signature',  ctypes.c_void_p), 
      ('valid',   ctypes.c_int), 
      ('references', ctypes.c_int), 
      ('name',   ctypes.c_void_p), 
      ('ex_data',  ctypes.c_int), 
      ('ex_pathlen', ctypes.c_long), 
      ('ex_pcpathlen', ctypes.c_long), 
      ('ex_flags',  ctypes.c_ulong), 
      ('ex_kusage',  ctypes.c_ulong), 
      ('ex_xkusage', ctypes.c_ulong), 
      ('ex_nscert',  ctypes.c_ulong), 
      ('skid',   ctypes.c_void_p), 
      ('akid',   ctypes.c_void_p), 
      ('policy_cache', ctypes.c_void_p), 
      ('crldp',   ctypes.c_void_p), 
      ('altname',  ctypes.c_void_p), 
      ('nc',   ctypes.c_void_p), 
      ('rfc3779_addr', ctypes.c_void_p), 
      ('rfc3779_asid', ctypes.c_void_p), 
      ('sha1_hash',  ctypes.c_char), 
      ('aux',   ctypes.c_void_p)] 

И последний шаг: назначить структуру указателя, полученного от функции X509_new():

self.X509_new = self._lib.X509_new 
self.X509_new.restype = ctypes.POINTER(X509_st) 
self.X509_new.argtypes = [] 

Так питон функции для OpenSSL macro X509_get_notBefore будет выглядеть так:

def X509_get_notBefore(self): 
    return self.X509[0].cert_info.validity.notBefore 
2

Вы не можете импортировать макросы. Импортируются функции из библиотеки DLL. Макросы не экспортируются из DLL, поэтому импортировать нечего.

К счастью, большинство макросов очень просты, поэтому вы можете просто переопределить их в Python.

Или, альтернативно, создайте DLL-оболочку в C, которая определяет функцию для каждого макроса, компилирует и связывает ее и импортирует функции-обертки с помощью ctypes.

Или вы можете использовать Cython или какую-либо другую технологию вместо ctypes. Обычно они работают, чтобы сгенерировать и скомпилировать C-код, который обертывает библиотеку C и экспортирует типы и функции Python, и обычно легко экспортировать макрос C как функцию Python, так как он предназначен для экспорта функции C.

Или, простейший из всех ... PyOpenSSL уже обертывают все, что вам нужно?

+0

Спасибо за ваш ответ. Я хочу узнать, как импортировать dll с помощью ctypes. Вот почему я не буду использовать PyOpenSSL или M2Crypto. С уважением! – Marek

+0

@Marek: Хорошо, это хорошая причина не использовать 'PyOpenSSL' и использовать' ctypes' вместо 'Cython'. Таким образом, вы получите первые два ответа (переопределите макросы в Python или создайте DLL-оболочку, которая экспортирует функции для макросов); сделайте то, что вам будет лучше. Хорошая новость заключается в том, что вы узнали что-то новое о 'ctypes' и DLL, что было в целом, не так ли? – abarnert