libeay32.dll包装:如何导入宏?

2024-06-01 10:11:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用Python为OpenSLLlibeay32.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

有什么想法,如何使用ctypes?在


Tags: 函数nameselfforgetexample方式function
2条回答

不能导入宏。您要导入的是DLL中的函数。宏不是从DLL中导出的,因此没有要导入的内容。在

幸运的是,大多数宏都非常简单,所以您可以在Python中重新实现它们。在

或者,用C语言创建一个为每个宏定义一个函数的包装DLL,编译并链接该宏,然后用ctypes导入包装函数。在

或者您可能希望使用^{}或其他一些技术来代替ctypes。它们通常的工作方式是生成和编译封装C库并导出Python类型和函数的C代码,通常将C宏导出为Python函数与导出C函数一样容易。在

或者,最简单的是,PyOpenSSL是否已经包装了您需要的所有东西?在

经过研究,我决定回答自己的问题。X509_get_notAfter的宏如下所示:

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

x-是X509结构,它包含X509_CINF结构,它包含X509_VAL结构,其中包含指向notAfter的指针:)

所以我的计划是在python代码中实现整个X509、X509 CINF和X509 VAL结构。在

在C语言里是这样的

^{pr2}$

X509的外观如下:

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的价值:

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

因此,OpenSSL宏X509的python函数将如下所示:

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

相关问题 更多 >