2013-02-28 78 views
1

我正在用Python編寫OpenSLL libeay32.dll的小包裝。對於大部分功能,可以導入如下: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_notAfterX509_get_notBefore

任何想法,怎麼樣與​​一起做?

+0

您無法導入「定義爲宏的函數」beca使用它們不存在於圖書館中。 – wRAR 2013-02-28 01:10:38

回答

0

經過一番研究,我決定回答我自己的問題。宏X509_get_notAfter看起來是這樣的:

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

X - 是X509的結構,其中包含X509_CINF結構,它包含X509_VAL結構包含指向notAfter :)

所以我的計劃是實行全X509,X509_CINF和python代碼中的X509_VAL結構。

在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

所以我的Python代碼現在看起來是這樣的:

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 = [] 

所以Python功能OpenSSL宏X509_get_notBefore將如下所示:

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

您不能導入宏。你要導入的是DLL中的函數。宏不會從DLL中導出,因此無需導入。

幸運的是,大多數宏很簡單,所以你可以用Python重新實現它們。

或者,也可以在C中創建一個包裝DLL,爲每個宏定義一個函數,編譯並鏈接該函數,然後用​​導入包裝函數。

或者你可能想使用Cython或其他一些技術,而不是​​。他們通常工作的方式是生成和編譯包裝C庫並導出Python類型和函數的C代碼,將C宏導出爲Python函數和導出C函數一樣容易。

或者,最簡單的...所有的不PyOpenSSL已經包裹你需要的一切?

+0

感謝您的回答。我想學習如何使用ctypes導入dll。這就是爲什麼我不打算使用PyOpenSSL或M2Crypto。問候! – Marek 2013-02-28 01:19:02

+0

@Marek:好的,這是不使用'PyOpenSSL'並使用'ctypes'而不是'Cython'的理由。所以這給你留下了前兩個答案(在Python中重新實現宏,或者創建一個爲宏導出函數的包裝器DLL);做任何你感覺更舒適的事情。好消息是,你已經學到了一些關於'ctypes'和DLL的新東西,這是重點,對吧? – abarnert 2013-02-28 01:30:49