至少对于一个C程序员来说是这样..
有一段RSA签名的程序,原本是用 C 调 libcrypto 包装成 jni 由 java 使用的,现在打算在 python 里面实现一个类似的功能,这段 C 代码大概是这样:
-
int rsa_sign(char *private_keyfile, char *message, int message_len, char *buf, int buf_size)
-
{
-
RSA *key;
-
int malloc_size, rsa_size;
-
unsigned char *rsa;
-
-
BIO *bio;
-
-
bio = BIO_new_file(private_keyfile, "r");
-
if (NULL == bio) {
-
return 0;
-
}
-
key = (RSA *)PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
-
BIO_free(bio);
-
if (NULL == key) {
-
return 0;
-
}
-
-
malloc_size = RSA_size(key);
-
rsa = (unsigned char *)malloc(malloc_size);
-
if (NULL == rsa) {
-
RSA_free(key);
-
return 0;
-
}
-
-
if (0 == RSA_sign(NID_md5, message, message_len, rsa, &rsa_size, key)) {
-
free(rsa);
-
RSA_free(key);
-
return 0;
-
}
-
RSA_free(key);
-
-
if (rsa_size/3 * 4 >= buf_size) { /* 结果的 Base64 编码后长度大于 buf_size, 等于也错误(后面需要放 '\0' 的位置) */
-
free(rsa);
-
return 0;
-
}
-
-
b64_encode(rsa, rsa_size, buf);
-
-
free(rsa);
-
return 1;
-
}
可是找遍 PyCrypto, 楞是没有看到怎么实现 PEM_read_bio_RSAPrivateKey 这样从一个 PEM 格式的私钥文件里加载的功能。然后去看哪些基于 PyCrypto 包装的其他的包,比如 ezPyCrypto, Keyczar(这还是 google 发布的),包括 mail-list 上提供的 patch.... 这些似乎倒是可以 load key 了,可缺省好像也并没有对 NID_MD5 的支持, 绝望~~~~
于是抱着试试的心态用 ctypes 直接去调 libcrypto——以前只是在 PyS60 上玩票似的用过 ctypes,以及在 Win32 下用过,而且那时候 ctypes 还不太成熟——结果发现 python2.5 的 ctypes 竟如此的好用:
-
import ctypes
-
import base64
-
-
crypto_handler = ctypes.cdll.LoadLibrary("/usr/lib/libcrypto.so")
-
BIO_new_file = crypto_handler.BIO_new_file
-
PEM_read_bio_RSAPrivateKey = crypto_handler.PEM_read_bio_RSAPrivateKey
-
RSA_size = crypto_handler.RSA_size
-
RSA_sign = crypto_handler.RSA_sign
-
BIO_free = crypto_handler.BIO_free
-
RSA_free = crypto_handler.RSA_free
-
NID_md5 = 4
-
-
bio = BIO_new_file("/yourpathfile.key", "r")
-
key = PEM_read_bio_RSAPrivateKey(bio, 0, 0, 0)
-
r = BIO_free(bio)
-
if r != 1:
-
# break here
-
print 'BIO_free error'
-
-
rsa_size = RSA_size(key)
-
rsa = ctypes.create_string_buffer(rsa_size)
-
sign_size = ctypes.create_string_buffer(4)
-
-
message = "foobar"
-
if 1 != RSA_sign(NID_md5, message, len(message), rsa, sign_size, key):
-
print 'RSA_sign error'
-
RSA_free(key)
-
-
print base64.urlsafe_b64encode(rsa.raw)
Topic:
最新评论