1 Star 1 Fork 0

国密系列/基于go gmsm编写的sm2国密算法PHP扩展

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
go_sm2.c 15.74 KB
一键复制 编辑 原始数据 按行查看 历史
15238399426 提交于 2024-07-05 16:10 . 优化
/* go_sm2 extension for PHP */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#ifdef _WIN32 // 如果定义了_WIN32宏(通常是Windows系统)
#include "./lib/win/libgosm2.h"
#elif defined(__linux__) // 如果定义了__linux__宏(通常是Linux系统)
#include "./lib/linux/libgosm2.h"
#ifdef siginfo_t
#else
#include <asm-generic/siginfo.h>
#endif
#elif defined(__APPLE__) && defined(__MACH__) // 如果定义了__APPLE__和__MACH__宏(通常是macOS)
#include "./lib/mac/libgosm2.h"
#else
#error "Unsupported platform" // 如果不是上述任何一种系统,则报错
#endif
#include "php.h"
#include "ext/standard/info.h"
#include "php_go_sm2.h"
/* For compatibility with older PHP versions */
#ifndef ZEND_PARSE_PARAMETERS_NONE
#define ZEND_PARSE_PARAMETERS_NONE() \
ZEND_PARSE_PARAMETERS_START(0, 0) \
ZEND_PARSE_PARAMETERS_END()
#endif
void print_hex(char *name, const unsigned char *data, size_t length) {
printf("%s:", name);
for (size_t i = 0; i < length; i++) {
printf("%02X", data[i]);
}
printf("\n");
}
PHP_GO_SM2_API zval *return_result(int code, const char *msg, zval *data_array) {
zval return_array;
array_init(&return_array);
add_assoc_long(&return_array, "code", code);
add_assoc_string(&return_array, "msg", (char *)msg); // 已经是 char* 类型
if (data_array && Z_TYPE_P(data_array) == IS_ARRAY) {
add_assoc_zval(&return_array, "data", data_array);
} else {
// 如果 data_array 无效或不是数组,则创建一个空数组
zval empty_data_array;
array_init(&empty_data_array);
add_assoc_zval(&return_array, "data", &empty_data_array);
}
zval *return_zv = emalloc(sizeof(zval));
*return_zv = return_array; // 浅复制 zval 结构体(对于数组,它只复制了 HashTable 的指针)
zval_copy_ctor(return_zv); // 深度复制 zval 的内容(如果它是数组)
return return_zv;
}
/* 模块初始化函数 */
PHP_MINIT_FUNCTION(go_sm2)
{
/* 注册常量 */
REGISTER_LONG_CONSTANT("GO_SM2_MODE_DEFAULT", GO_SM2_MODE_DEFAULT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GO_SM2_MODE_ANS1", GO_SM2_MODE_ANS1, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GO_SM2_ORDER_C1C2C3", GO_SM2_ORDER_C1C2C3, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GO_SM2_ORDER_C1C3C2", GO_SM2_ORDER_C1C3C2, CONST_CS | CONST_PERSISTENT);
/* 返回成功 */
return SUCCESS;
}
PHP_FUNCTION(go_sm2_test1)
{
ZEND_PARSE_PARAMETERS_NONE();
php_printf("The extension %s is loaded and working!\r\n", "go_sm2");
// 创建一个 zval 数组来存储你的返回值
}
PHP_FUNCTION(go_sm2_test2)
{
char *var = "World";
size_t var_len = sizeof("World") - 1;
zend_string *retval;
ZEND_PARSE_PARAMETERS_START(0, 1)
Z_PARAM_OPTIONAL
Z_PARAM_STRING(var, var_len)
ZEND_PARSE_PARAMETERS_END();
retval = strpprintf(0, "Hello %s", var);
RETURN_STR(retval);
}
PHP_FUNCTION(go_sm2_key_pair) {
zend_string * pub_key_buff = NULL, *pri_key_buff = NULL;
GO_SM2_KEY_PAIR key_pair;
GO_SM2_ERROR_STRUCT error_struct;
int error;
size_t pubKey_len=65, priveKey_len=32; // 注意这里使用 size_t 而不是 int
// 假设 GenerateKeyPair 返回一个错误码和填充了长度的密钥
error = GenerateKeyPair(&key_pair,&error_struct);
if (error != 0) {
zval *result = return_result(-error, (const char *)error_struct.error, NULL); // 假设我们不传递 data_array
FreeError(&error_struct);
if (result) {
RETURN_ZVAL(result, 0, 1); // 0: 不增加引用计数, 1: 释放 result 在函数返回后的内存
} else {
RETURN_NULL();
}
}
// 分配内存来存储密钥
pub_key_buff = zend_string_alloc(pubKey_len, 0);
pri_key_buff = zend_string_alloc(priveKey_len, 0);
// 假设 key_pair.pub_key 和 key_pair.pri_key 是指向密钥数据的指针
memcpy(ZSTR_VAL(pub_key_buff), key_pair.pub_key, pubKey_len);
memcpy(ZSTR_VAL(pri_key_buff), key_pair.pri_key, priveKey_len);
zval data_array;
array_init(&data_array);
add_assoc_str(&data_array, "publicKey", pub_key_buff);
add_assoc_str(&data_array, "privateKey", pri_key_buff);
zval *result = return_result(200, "Key generation successful!", &data_array); // 假设我们不传递 data_array
if (result) {
RETURN_ZVAL(result, 0, 1); // 0: 不增加引用计数, 1: 释放 result 在函数返回后的内存
} else {
RETURN_NULL();
}
}
PHP_FUNCTION(go_sm2_sign) {
zend_string * signature_buff = NULL;
zval *result;
zend_long mode = GO_SM2_MODE_DEFAULT;
char *msg, *pri_key, *iv = "1234567812345678";
size_t msg_len, pri_key_len, iv_len = strlen(iv); // iv_len 应该被设置为 iv 的长度
int error = 0;
GO_SM2_SIGNATURE_STRUCT sm2_sig;
GO_SM2_ERROR_STRUCT error_struct;
// 解析参数
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|ls", &msg, &msg_len, &pri_key, &pri_key_len, &mode, &iv, &iv_len) == FAILURE) {
RETURN_NULL();
}
// 签名数据
// 注意:假设GoSm2SignData是一个外部定义的函数,它分配并填充了sm2_sig.sig
error = GoSm2SignData((unsigned char *)pri_key, (int)pri_key_len, (unsigned char *)msg, (int)msg_len, (unsigned char *)iv, (int)iv_len, mode, &sm2_sig,&error_struct);
if (error != 0) {
goto clean_up;
}
// 将签名转换为PHP字符串
signature_buff = zend_string_init((char *)sm2_sig.sig, sm2_sig.sig_len, 0);
// 返回签名
// 释放sm2_sig.sig(如果它是动态分配的)
if (sm2_sig.sig) {
FreeSm2Signature(&sm2_sig); // 假设这个函数也释放了sm2_sig.sig指向的内存
sm2_sig.sig = NULL;
}
zval data_array;
array_init(&data_array);
add_assoc_str(&data_array, "signature", signature_buff);
result = return_result(200, "Key generation successful!", &data_array); // 假设我们不传递 data_array
if (result) {
RETURN_ZVAL(result, 0, 1); // 0: 不增加引用计数, 1: 释放 result 在函数返回后的内存
} else {
RETURN_NULL();
}
clean_up:
result = return_result(-error, (const char *)error_struct.error, NULL); // 假设我们不传递 data_array
if (result) {
RETURN_ZVAL(result, 0, 1); // 0: 不增加引用计数, 1: 释放 result 在函数返回后的内存
} else {
RETURN_NULL();
}
}
PHP_FUNCTION(go_sm2_verify){
char *msg, *pub_key, *signature;
size_t msg_len, pub_key_len, signature_len;
int error = 0;
GO_SM2_SIGNATURE_STRUCT sm2_sig;
GO_SM2_ERROR_STRUCT error_struct;
zval *result;
const char *iv = "1234567812345678";
size_t iv_len = strlen(iv); // iv_len 应该是 iv 的长度
// 解析参数
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|s", &msg, &msg_len, &pub_key, &pub_key_len, &signature, &signature_len, &iv, &iv_len) == FAILURE) {
RETURN_NULL();
}
// 分配内存并复制签名
sm2_sig.sig = (unsigned char *) malloc(signature_len);
memcpy(sm2_sig.sig, signature, signature_len);
sm2_sig.sig_len = signature_len;
// 签名验证
error = Sm2SignVerify((unsigned char *)pub_key, (int)pub_key_len, (unsigned char *)msg, (int)msg_len, (unsigned char *)iv, (int)iv_len, &sm2_sig,&error_struct);
if (sm2_sig.sig) {
free(sm2_sig.sig); // 假设这个函数也释放了sm2_sig.sig指向的内存
sm2_sig.sig = NULL; // 设置为 NULL 以避免悬挂指针
}
if (error==0){
result = return_result(200, "message verify successful!", NULL); // 假设我们不传递 data_array
if (result) {
RETURN_ZVAL(result, 0, 1); // 0: 不增加引用计数, 1: 释放 result 在函数返回后的内存
} else {
RETURN_NULL();
}
}else{
result = return_result(-error, (const char *)error_struct.error, NULL); // 假设我们不传递 data_array
if (error_struct.error) {
FreeError(&error_struct); //
error_struct.error = NULL;
}
if (result) {
RETURN_ZVAL(result, 0, 1); // 0: 不增加引用计数, 1: 释放 result 在函数返回后的内存
} else {
RETURN_NULL();
}
}
}
PHP_FUNCTION(go_sm2_encrypt){
zend_long mode = GO_SM2_MODE_DEFAULT;
zend_long order = GO_SM2_ORDER_C1C2C3;
char *msg, *pub_key;
size_t msg_len, pub_key_len;
GO_SM2_ENCRYPT_STRUCT ciphertext;
zend_string * ciphertext_buff = NULL;
GO_SM2_ERROR_STRUCT error_struct;
zval *result;
int error = 0;
// 解析参数
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|ll", &msg, &msg_len, &pub_key, &pub_key_len, &order, &mode) == FAILURE) {
RETURN_NULL();
}
error=Sm2Encrypt((unsigned char*)pub_key, (int) pub_key_len, (unsigned char*) msg, (int) msg_len, (int)mode, (int) order, &ciphertext,&error_struct);
if (error!=0){
goto clean_up;
}
// 将签名转换为PHP字符串
ciphertext_buff = zend_string_init((char *)ciphertext.ciphertext, ciphertext.ciphertext_len, 0);
// 返回签名
if (ciphertext.ciphertext) {
free(ciphertext.ciphertext); // 假设这个函数也释放了sm2_sig.sig指向的内存
ciphertext.ciphertext = NULL;
}
zval data_array;
array_init(&data_array);
add_assoc_str(&data_array, "ciphertext", ciphertext_buff);
result = return_result(200, "message encrypt successful!", &data_array); // 假设我们不传递 data_array
if (result) {
RETURN_ZVAL(result, 0, 1); // 0: 不增加引用计数, 1: 释放 result 在函数返回后的内存
} else {
RETURN_NULL();
}
clean_up:
// 释放sm2_sig.sig(如果它是动态分配的)
result = return_result(-error, (const char *)error_struct.error, NULL); // 假设我们不传递 data_array
if (error_struct.error) {
FreeError(&error_struct); //
error_struct.error = NULL;
}
if (result) {
RETURN_ZVAL(result, 0, 1); // 0: 不增加引用计数, 1: 释放 result 在函数返回后的内存
} else {
RETURN_NULL();
}
}
PHP_FUNCTION(go_sm2_decrypt){
zend_long mode = GO_SM2_MODE_DEFAULT;
zend_long order = GO_SM2_ORDER_C1C2C3;
char *msg, *pri_key, *ciphertext;
size_t msg_len, pri_key_len, ciphertext_len;
GO_SM2_DECRYPT_STRUCT plaintext;
GO_SM2_ERROR_STRUCT error_struct;
zend_string * plaintext_buff = NULL;
zval *result;
int error = 0;
// 解析参数
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|ll", &pri_key, &pri_key_len, &ciphertext, &ciphertext_len, &order) == FAILURE) {
RETURN_NULL();
}
error=Sm2Decrypt((unsigned char*)pri_key, (int) pri_key_len, (unsigned char*) ciphertext, (int) ciphertext_len, (int)order, &plaintext,&error_struct);
if (error!=0){
goto clean_up;
}
// 将签名转换为PHP字符串
plaintext_buff = zend_string_init((char *)plaintext.plaintext, plaintext.plaintext_len, 0);
if (plaintext.plaintext) {
free(plaintext.plaintext);
plaintext.plaintext = NULL;
}
// 返回签名
zval data_array;
array_init(&data_array);
add_assoc_str(&data_array, "plaintext", plaintext_buff);
result = return_result(200, "ciphertext message decrypt successful!", &data_array); // 假设我们不传递 data_array
if (result) {
RETURN_ZVAL(result, 0, 1); // 0: 不增加引用计数, 1: 释放 result 在函数返回后的内存
} else {
RETURN_NULL();
}
clean_up:
result = return_result(-error, (const char *)error_struct.error, NULL); // 假设我们不传递 data_array
if (error_struct.error) {
FreeError(&error_struct); //
error_struct.error = NULL;
}
if (result) {
RETURN_ZVAL(result, 0, 1); // 0: 不增加引用计数, 1: 释放 result 在函数返回后的内存
} else {
RETURN_NULL();
}
}
/* {{{ PHP_RINIT_FUNCTION
*/
PHP_RINIT_FUNCTION(go_sm2)
{
#if defined(ZTS) && defined(COMPILE_DL_GO_SM2)
ZEND_TSRMLS_CACHE_UPDATE();
#endif
return SUCCESS;
}
PHP_MINFO_FUNCTION(go_sm2)
{
php_info_print_table_start();
php_info_print_table_header(2, "go_sm2 support", "enabled");
php_info_print_table_end();
}
ZEND_BEGIN_ARG_INFO(arginfo_go_sm2_test1,
0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_go_sm2_test2,
0)
ZEND_ARG_INFO(0, str)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_go_sm2_key_pair,
0,0,0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_go_sm2_sign,
0, 0, 2) // 至少两个必需参数
ZEND_ARG_INFO(0, msg)
ZEND_ARG_INFO(0, pri_key)
ZEND_ARG_INFO(0, mode)
ZEND_ARG_INFO(0, iv) // 假设 iv 是可选的
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_go_sm2_verify,
0, 0, 3) // 至少三个必需参数
ZEND_ARG_INFO(0, msg)
ZEND_ARG_INFO(0, pub_key)
ZEND_ARG_INFO(0, ciphertext)
ZEND_ARG_INFO(0, iv) // 假设 iv 是可选的
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_go_sm2_encrypt,
0, 0, 2) // 至少两个必需参数
ZEND_ARG_INFO(0, msg)
ZEND_ARG_INFO(0, pub_key)
ZEND_ARG_INFO(0, order)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_go_sm2_decrypt,
0, 0, 2) // 至少三个必需参数
ZEND_ARG_INFO(0, pri_key)
ZEND_ARG_INFO(0, signature)
ZEND_ARG_INFO(0, order)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ go_sm2_functions[]
*/
static const zend_function_entry go_sm2_functions[] = {
PHP_FE(go_sm2_test1, arginfo_go_sm2_test1)
PHP_FE(go_sm2_test2, arginfo_go_sm2_test2)
PHP_FE(go_sm2_key_pair, arginfo_go_sm2_key_pair)
PHP_FE(go_sm2_sign, arginfo_go_sm2_sign)
PHP_FE(go_sm2_verify, arginfo_go_sm2_verify)
PHP_FE(go_sm2_encrypt, arginfo_go_sm2_encrypt)
PHP_FE(go_sm2_decrypt, arginfo_go_sm2_decrypt)
PHP_FE_END
};
/* }}} */
/* {{{ go_sm2_module_entry
*/
zend_module_entry go_sm2_module_entry = {
STANDARD_MODULE_HEADER,
"go_sm2", /* Extension name */
go_sm2_functions, /* zend_function_entry */
PHP_MINIT(go_sm2), /* PHP_MINIT - Module initialization */
NULL, /* PHP_MSHUTDOWN - Module shutdown */
PHP_RINIT(go_sm2), /* PHP_RINIT - Request initialization */
NULL, /* PHP_RSHUTDOWN - Request shutdown */
PHP_MINFO(go_sm2), /* PHP_MINFO - Module info */
PHP_GO_SM2_VERSION, /* Version */
STANDARD_MODULE_PROPERTIES
};
/* }}} */
#ifdef COMPILE_DL_GO_SM2
# ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
# endif
ZEND_GET_MODULE(go_sm2)
#endif
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/state-secret-series/go-ext-sm2.git
git@gitee.com:state-secret-series/go-ext-sm2.git
state-secret-series
go-ext-sm2
基于go gmsm编写的sm2国密算法PHP扩展
master

搜索帮助