调用openssl_public_decrypt遇"解密数据非字符串"错误,如何获取正确结果?
问题分析与解决
错误原因
你遇到的"Decrypted data is not a string"错误主要由以下几个问题导致:
- 输出变量未初始化:
decrypted_zval在传递给openssl_public_decrypt前没有被初始化,函数无法正确写入解密结果。 - 引用参数传递错误:使用
ZVAL_NEW_REF创建引用的方式不符合PHP扩展的参数传递规范,导致函数无法正确修改引用变量。 - 忽略Base64解码失败场景:
php_base64_decode_ex可能返回NULL(输入无效Base64时),此时继续调用解密函数会引发异常。 - 未返回实际解密结果:当前代码仅返回布尔值,没有将解密后的字符串返回给调用者。
修正后的代码
#include "php.h" #include "ext/standard/info.h" #include "ext/standard/php_string.h" #include "ext/standard/base64.h" PHP_FUNCTION(my_openssl_public_decrypt) { zend_string *data, *public_key; zval func_name; zval result; zval params[3]; zval decrypted_zval; // 解析输入参数 if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &data, &public_key) == FAILURE) { RETURN_FALSE; } // Base64解码,处理解码失败的情况 zend_string *raw_data = php_base64_decode_ex((const unsigned char*)ZSTR_VAL(data), ZSTR_LEN(data), 0); if (!raw_data) { php_error_docref(NULL, E_WARNING, "Invalid Base64 data"); RETURN_FALSE; } // 初始化函数名字符串 ZVAL_STR(&func_name, zend_string_init("openssl_public_decrypt", strlen("openssl_public_decrypt"), 0)); // 初始化输出变量为NULL,准备作为引用传递 ZVAL_NULL(&decrypted_zval); // 将输出变量包装为引用类型,传递给openssl_public_decrypt ZVAL_REF(¶ms[1], &decrypted_zval); ZVAL_STR(¶ms[0], raw_data); ZVAL_STR(¶ms[2], public_key); // 调用PHP的openssl_public_decrypt函数 if (call_user_function(EG(function_table), NULL, &func_name, &result, 3, params) == FAILURE) { php_error_docref(NULL, E_WARNING, "Failed to call openssl_public_decrypt"); zend_string_release(raw_data); // 释放资源 RETURN_FALSE; } // 释放Base64解码后的字符串资源 zend_string_release(raw_data); // 检查解密是否成功 if (Z_TYPE(result) == IS_TRUE) { // 确保解密结果是字符串类型 if (Z_TYPE(decrypted_zval) == IS_STRING) { // 返回解密后的字符串给PHP层 RETURN_STR(Z_STR(decrypted_zval)); } else { php_error_docref(NULL, E_WARNING, "Decrypted data is not a string"); RETURN_FALSE; } } else { php_error_docref(NULL, E_WARNING, "Decryption failed"); RETURN_FALSE; } }
关键修正点说明
- 初始化输出变量:用
ZVAL_NULL(&decrypted_zval)初始化输出变量,确保它是一个有效的zval,让openssl_public_decrypt可以正确写入结果。 - 正确传递引用参数:使用
ZVAL_REF将decrypted_zval包装为引用类型,符合PHP函数对引用参数的要求。 - 处理Base64解码失败:检查
raw_data是否为NULL,避免无效数据进入解密流程。 - 返回解密结果:将解密后的字符串通过
RETURN_STR(Z_STR(decrypted_zval))返回给PHP层,满足获取解密结果的需求。 - 资源释放:在合适的地方释放
raw_data,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Dylan
相关产品推荐
相关产品推荐

