调试php源代码,重写加密函数,封装接口供lua使用

本文档介绍了如何调试PHP的openssl_pkey_get_public函数,目的是理解其工作原理以便在Lua中重写加密功能。通过下载PHP源代码,使用cgdb进行调试,定位到关键函数并分析参数。最后,展示了如何在Lua中封装调用加密函数的示例,实现在Lua中使用加密功能,并对比了PHP和Lua的执行效率。
摘要由CSDN通过智能技术生成

由于项目中使用加密算法,但是接口是php写的,需要使用lua编写业务,提供加密结果给php,

先看php的代码

<?php

       // 获取PEM文件
$pubKey = file_get_contents(dirname(__FILE__).'/public_key.pem');

       // 通过xxx函数获取res, echo $res的时候 发现是个资源
$res = openssl_pkey_get_public($pubKey);
$encrypted = '';
$data = "appkey=111&val=45678";
        // 加密函数
openssl_public_encrypt($data, $encrypted, $res);

       // 然后转base64编码
$encrypted = base64_encode($encrypted);

echo $encrypted;

?>

为了要搞清楚php调用的是啥功能,需要调试php源代码

1) 下载php源代码, php.net下载.

2) 安装牛逼的cgdb工具,注意需要 flex, help2man, texinfo 

3) 查找源代码  php-5.6.15/ext/openssl/openssl.c 文件

ZEND_BEGIN_ARG_INFO(arginfo_openssl_pkey_get_public, 0)
ZEND_ARG_INFO(0, cert)
ZEND_END_ARG_INFO()

如上,好像是找到地方了. 


PHP_FE(openssl_pkey_get_public, arginfo_openssl_pkey_get_public)
PHP_FE(openssl_pkey_get_details, arginfo_openssl_pkey_get_details)


PHP_FALIAS(openssl_free_key, openssl_pkey_free, arginfo_openssl_pkey_free)
PHP_FALIAS(openssl_get_privatekey, openssl_pkey_get_private, arginfo_openssl_pkey_get_private)
PHP_FALIAS(openssl_get_publickey, openssl_pkey_get_public, arginfo_openssl_pkey_get_public)


先不理会这里面是什么东西,直接找到函数. 


PHP_FUNCTION(openssl_pkey_get_public)
{
zval **cert;
EVP_PKEY *pkey;

        // PHP用来校验参数的, 
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &cert) == FAILURE) {
return;
}
Z_TYPE_P(return_value) = IS_RESOURCE;
pkey = php_openssl_evp_from_zval(cert, 1, NULL, 1, &Z_LVAL_P(return_value) TSRMLS_CC);
        // 最核心的就是这个函数.

if (pkey == NULL) {
RETURN_FALSE;
}
zend_list_addref(Z_LVAL_P(return_value));
}


显示调用的函数



/* { { { EVP Public/Private key functions */


/* { { { php_openssl_evp_from_zval
   Given a zval, coerce it into a EVP_PKEY object.
It can be:
1. private key resource from openssl_get_privatekey()
2. X509 resource -> public key will be extracted from it
3. if it starts with file:// interpreted as path to key file
4. interpreted as the data from the cert/key file and interpreted in same way as openssl_get_privatekey()
5. an array(0 => [items 2..4], 1 => passphrase)
6. if val is a string (possibly starting with file:///) and it is not an X509 certificate, then interpret as public key
NOTE: If you are requesting a private key but have not specified a passphrase, you should use an
empty string rather than NULL for the passphrase - NULL causes a passphrase prompt to be emitted in
the Apache error log!
*/
static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char * passphrase, int makeresource, long * resourceval TSRMLS_DC)
{
EVP_PKEY * key = NULL;
X509 * cert = NULL;
int free_cert = 0;
long cert_res = -1;
char * filename = NULL;
zval tmp;


Z_TYPE(tmp) = IS_NULL;


#define TMP_CLEAN \
if (Z_TYPE(tmp) == IS_STRING) {\
zval_dtor(&tmp); \
} \
return NULL;


if (resourceval) {
*resourceval = -1;
}
if (Z_TYPE_PP(val) == IS_ARRAY) {
zval ** zphrase;

/* get passphrase */


if (zend_hash_index_find(HASH_OF(*val), 1, (void **)&zphrase) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "key array must be of the form array(0 => key, 1 => phrase)");
return NULL;
}

if (Z_TYPE_PP(zphrase) == IS_STRING) {
passphrase = Z_STRVAL_PP(zphrase);
} else {
tmp = **zphrase;
zval_copy_ctor(&tmp);
convert_to_string(&tmp);
passphrase = Z_STRVAL(tmp);
}


/* now set val to be the key param and continue */
if (zend_hash_index_find(HASH_OF(*val), 0, (void **)&val) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "key array must be of the form array(0 => key, 1 => phrase)");
TMP_CLEAN;
}
}


if (Z_TYPE_PP(val) == IS_RESOURCE) {
void * what;
int type;


what = zend_fetch_resource(val TSRMLS_CC, -1, "OpenSSL X.509/key", &type, 2, le_x509, le_key);
if (!what) {
TMP_CLEAN;
}
if (resourceval) { 
*resourceval = Z_LVAL_PP(val);
}
if (type == le_x509) {
/* extract key from cert, depending on public_key param */
cert = (X509*)what;
free_cert = 0;
} else if (type == le_key) {
int is_priv;


is_priv = php_openssl_is_private_key((EVP_PKEY*)what TSRMLS_CC);


/* check whether it is actually a private key if requested */
if (!public_key && !is_priv) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied key param is a public key");
TMP_CLEAN;
}


if (public_key && is_priv) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Don't know how to get public key from this private key");
TMP_CLEAN;
} else {
if (Z_TYPE(tmp) == IS_STRING) {
zval_dtor(&tmp);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值