2017-02-12 63 views
2

我有一个从Apple的iOS开发人员门户PushNotifications .p8文件下载。Python调用OpenSSL函数segfaults

我试图加载P8文件可以用Python下面的代码:

from ctypes import * 
OpenSSL = cdll.LoadLibrary("/opt/local/lib/libssl.1.0.0.dylib") 


def loadPrivateKey(path): 
    bio = OpenSSL.BIO_new_file(path.encode("utf-8"), "rb".encode("utf-8")) 
    #pKey = OpenSSL.PEM_read_bio_PrivateKey(bio, None, None, None) 
    OpenSSL.BIO_free(bio) 

def main(): 
    loadPrivateKey("https://stackoverflow.com/users/Brandon/Desktop/APNsAuthKey.p8") 

main() 

然而,赛格线路故障:OpenSSL.BIO_free(bio)。我已经检查过bio是否具有0以外的值(它的确如此)。

如果我做同样的事情在C,它的工作原理:

struct EVP_PKEY* loadPrivateKey(const char* path) 
{ 
    struct BIO* bio = BIO_new_file(path, "rb"); 
    struct EVP_PKEY* pKey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); 
    BIO_free(bio); 
    return pKey; 
} 

int main() 
{ 
    struct EVP_PKEY* pKey = loadPrivateKey("https://stackoverflow.com/users/Brandon/Desktop/APNsAuthKey.p8"); 
    EVP_PKEY_free(pKey); 
} 

我用C代码工作已经验证了,我用它来签名数据。我在Python3一直无法做同样的,因为释放的BIO代码为11

我已经试过pyOpenssl出现segfaults,也出现segfaults当我尝试用loadprivatekey(FILETYPE_PEM, key)读取密钥,其中关键是P8文件的内容。

任何想法为什么它会segfault?

+0

您提供了哪个版本的OpenSSL,以及Python预期哪种版本的OpenSSL? OpenSSL 1.0.2和OpenSSL 1.1.0 *不是二进制兼容的。 – jww

+0

@wwww;我解决了它。试了几个小时..事实证明,你需要指定类型和类型必须完美匹配。否则失败。由于某些奇怪的原因,即使使用'ffi',pyOpenSSL'段错误。我结束了使用我发布的解决方案,因为没有任何第三方库工作atm,我找不到任何其他解决方案。 – Brandon

回答

2

如果其他人有相同的问题..您必须指定argtypesrestype。为此,您需要将函数指针分配给临时变量,指定类型,然后使用临时变量调用它。

例子:

from ctypes import * 
OpenSSL = cdll.LoadLibrary("/opt/local/lib/libssl.1.0.0.dylib") 


def BIO_new_file(path): 
    BIO_new_file_func = OpenSSL.BIO_new_file 
    BIO_new_file_func.argtypes = [c_char_p, c_char_p] 
    BIO_new_file_func.restype = c_void_p 
    return BIO_new_file_func(path.encode("utf-8"), "rb".encode("utf-8")) 

def BIO_free(bio): 
    BIO_free_func = OpenSSL.BIO_free 
    BIO_free_func.argtypes = [c_void_p] 
    BIO_free_func.restype = None 
    return BIO_free_func(bio) 


def loadPrivateKey(path): 
    bio = BIO_new_file(path) 
    #pKey = PEM_read_bio_PrivateKey(bio, None, None, None) 
    BIO_free(bio) 
    #return pKey 

def main(): 
    loadPrivateKey("https://stackoverflow.com/users/Brandon/Desktop/APNsAuthKey.p8") 

main() 

我的印象是,我不得不调用的函数用正确的参数之下,它会工作,但我错了。你必须指定类型!否则使用FFI,让你的生活更轻松。