由于项目中使用加密算法,但是接口是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);
}