python如何调用libcrypto实现RSA解密?

libraco
  • 760

python本身有很多实现rsa的不错的库,但是由于GIL的问题,不能利用多核,所以我尝试利用ctypes库调用openssl的libcrypto.so来突破多核限制。问题是我不知道libcrypto暴露的方法,不知道调用顺序和入参,网上有个签名的算法,我参照了一下写了这么一段代码:

import ctypes
from ctypes.util import find_library
_libcrypto = find_library('crypto')
sign = 'iYzF0bn6kwUtsqLmTSx8fx...'
cryptor = ctypes.cdll.LoadLibrary(_libcrypto)
RSA_size                    = cryptor.RSA_size
BIO_free                    = cryptor.BIO_free
RSA_free                    = cryptor.RSA_free
RSA_decrypt                 = cryptor.RSA_private_decrypt
PEM_read_bio_RSAPrivateKey  = cryptor.PEM_read_bio_RSAPrivateKey
# RSA_PKCS1_PADDING           = cryptor.RSA_NO_PADDING
privkey = '''-----BEGIN RSA PRIVATE KEY-----...-----END RSA PRIVATE KEY-----'''    
bio = cryptor.BIO_new_mem_buf(privkey, -1)
key = PEM_read_bio_RSAPrivateKey(bio, 0, 0, 0)
r = BIO_free(bio)
if r != 1:
    # break here
    print 'BIO_free error'
    return
rsa_size = RSA_size(key)
print rsa_size
rsa = ctypes.create_string_buffer(rsa_size)
#sign_size = ctypes.create_string_buffer(4)
ret = RSA_decrypt(len(sign), sign, rsa, key)

其中privkey是私钥,sign是我要解密的数据,然而这段代码并没有返回正确的结果。
想请问大家python调用libcrypto实现RSA解密的正确姿势,当然有其他能够利用多核的方案希望也能不吝赐教!

回复
阅读 4.4k
1 个回答
✓ 已被采纳

完全是试出来的结果……
首先base64的文本要转一下

sign = base64.decodestring(sign)

然后RSA_decrypt的第一个入参错了,应该是:

ret = RSA_private_decrypt(rsa_size, sign, rsa, key, 1)

官网定义:

 int RSA_private_decrypt(int flen, unsigned char *from,
    unsigned char *to, RSA *rsa, int padding);

这里flen是key长度,之前望文生义以为是from_len。
ret>0表示解密成功,结果从rsa.value里取,然后第五个参数是padding的模式,本应该是RSA_PKCS1_PADDING,但是libcrypto.so.6里好像找不到这个常量,我从0到5自己一个个试出来的,估计1是RSA_PKCS1_PADDING,2是SSLV23_PADDING(不一定这么拼),因为之前试过其他库,这两种填充模式才能解出来。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏