从v0.20.0版本开始,在编译时,可以添加openssl模块,从而可以执行RSA加密,解密,签名,验签之类的操作。只要在make命令后面加入USE_OPENSSL=yes即可。

    页面导航:

项目下载地址:

    zenglServer源代码的相关地址:https://github.com/zenglong/zenglServer  当前版本对应的tag标签为:v0.20.0

zenglServer v0.20.0:

    从v0.20.0版本开始,在编译时,可以添加openssl模块,从而可以执行RSA加密,解密,签名,验签之类的操作。只要在make命令后面加入USE_OPENSSL=yes即可。

    当然,要使用openssl模块,前提是系统中安装了底层的openssl开发库。

    如果是ubuntu系统,可以通过 sudo apt-get install openssl libssl-dev 来安装openssl相关的库和开发头文件等。

    如果是centos系统,则可以通过 yum install openssl openssl-devel 来安装相关的底层库。

    要同时使用mysql,magick,pcre,curl,redis,以及openssl模块,可以使用 make USE_MYSQL=yes USE_MAGICK=6 USE_PCRE=yes USE_CURL=yes USE_REDIS=yes USE_OPENSSL=yes 命令:

[root@localhost zenglServerTest]# make USE_MYSQL=yes USE_MAGICK=6 USE_PCRE=yes USE_CURL=yes USE_REDIS=yes USE_OPENSSL=yes
............................................................
gcc -g3 -ggdb -O0 -std=c99 main.c http_parser.c module_request.c module_builtin.c module_session.c dynamic_string.c multipart_parser.c resources.c client_socket_list.c json.c randutils.c md5.c debug.c zlsrv_setproctitle.c pointer.c main.h http_parser.h common_header.h module_request.h module_builtin.h module_session.h dynamic_string.h multipart_parser.h resources.h client_socket_list.h json.h randutils.h md5.h debug.h zlsrv_setproctitle.h pointer.h module_mysql.c module_mysql.h  module_magick.c module_magick.h module_pcre.c module_pcre.h module_curl.c module_curl.h module_redis.c module_redis.h module_openssl.c module_openssl.h zengl/linux/zengl_exportfuns.h  -o zenglServer zengl/linux/libzengl.a crustache/libcrustache.a   -lpthread -lm -DUSE_MYSQL `mysql_config --cflags --libs`  -D USE_MAGICK=6 `pkg-config --cflags --libs Wand` -DUSE_PCRE `pcre-config --cflags --libs` -DUSE_CURL `curl-config --cflags --libs` -DUSE_REDIS `pkg-config --cflags --libs hiredis` -DUSE_OPENSSL `pkg-config --cflags --libs openssl`

mysql module is enabled!!!
magick module is enabled!!!
pcre module is enabled!!!
curl module is enabled!!!
redis module is enabled!!!
openssl module is enabled!!!
[root@localhost zenglServerTest]# 

opensslGetError模块函数:

    opensslGetError模块函数,用于获取openssl操作失败时的出错信息。相关的C源码位于module_openssl.c文件中:

/**
 * opensslGetError模块函数,用于获取openssl操作失败时的出错信息
 *
 * 例如:
	use builtin,openssl;
	def NULL 0;

	.............................. // 省略中间代码

	key = opensslReadKey(key_content, is_public, password);
	if(key == NULL)
		exit('read key "'+ file +'" failed: ' + opensslGetError());
	endif

	上面代码片段中,如果opensslReadKey读取密钥key失败,则会通过opensslGetError来获取具体的错误信息,从而可以知道大概的出错原因

	模块函数版本历史:
	 - v0.20.0版本新增此模块函数
 */
ZL_EXP_VOID module_openssl_get_error(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT argcount)
{
	ZENGL_EXPORT_MOD_FUN_ARG arg = {ZL_EXP_FAT_NONE,{0}};
	char * err = malloc(130);
	ERR_load_crypto_strings();
	ERR_error_string(ERR_get_error(), err);
	zenglApi_SetRetVal(VM_ARG, ZL_EXP_FAT_STR, err, 0, 0);
	free(err);
}

opensslReadKey模块函数:

    opensslReadKey模块函数,用于读取RSA相关的密钥key,并返回和key相关的指针。该模块函数相关的C源码也位于module_openssl.c文件中:

/**
 * opensslReadKey模块函数,读取密钥key,并返回和key相关的指针
 * 第一个参数key必须是字符串类型,表示密钥的具体内容,如果密钥存在于文件中,则需要先将文件里的密钥内容读取出来,然后再传给此函数
 * 第二个参数is_public必须是整数类型,当值为不为0的整数时表示公钥,为0时表示私钥
 * 第三个参数password是可选参数(如果提供了的话,必须是字符串类型),表示密钥相关的密码,密钥可以经过加密处理,如果密钥被加密过,就需要提供相关的密码
 *
 * 例如:
	use builtin,openssl;
	def RSA_PUBLIC 1;
	def RSA_PRIVATE 0;
	def NULL 0;

	fun exit(msg)
		print msg;
		bltExit();
	endfun

	fun read_rsa_key(file, is_public, password = '')
		ret = bltReadFile(file, &key_content, &file_size);
		if(ret == 0)
			print file + ' file size: ' + file_size;
			if(password)
				key = opensslReadKey(key_content, is_public, password);
			else
				key = opensslReadKey(key_content, is_public);
			endif
			if(key == NULL)
				exit('read key "'+ file +'" failed: ' + opensslGetError());
			endif
			print 'key:' + key;
			return key;
		else
			exit('read '+file+' failed, maybe the file does not exists, or open failed.');
		endif
	endfun

	key = read_rsa_key('rsa_public.key', RSA_PUBLIC);
	p_key = read_rsa_key('rsa_private.key', RSA_PRIVATE);
	p_aes_key = read_rsa_key('rsa_aes_private.key', RSA_PRIVATE, '111111');

	上面代码片段中,由于密钥存储于文件中,因此,会先通过bltReadFile模块函数根据文件名读取出密钥的具体内容,
	接着将密钥内容传递给opensslReadKey模块函数,并通过第二个is_public参数来指定该密钥是公钥还是私钥,
	如果密钥经过了加密处理,就再通过第三个password参数设置相关的密码,opensslReadKey在成功读取了密钥后,
	会返回一个和密钥相关的key指针,通过该指针就可以进行RSA加密解密,签名之类的操作了

	模块函数版本历史:
	 - v0.20.0版本新增此模块函数
 */
ZL_EXP_VOID module_openssl_read_key(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT argcount)
{
	ZENGL_EXPORT_MOD_FUN_ARG arg = {ZL_EXP_FAT_NONE,{0}};
	if(argcount < 2)
		zenglApi_Exit(VM_ARG,"usage: opensslReadKey(key, is_public[, password]): integer");
	zenglApi_GetFunArg(VM_ARG,1,&arg);
	if(arg.type != ZL_EXP_FAT_STR) {
		zenglApi_Exit(VM_ARG,"the first argument [key] of opensslReadKey must be string");
	}
	char * key = arg.val.str;
	zenglApi_GetFunArg(VM_ARG,2,&arg);
	int is_public = 0;
	if(arg.type == ZL_EXP_FAT_INT) {
		is_public = (int)arg.val.integer;
	}
	else {
		zenglApi_Exit(VM_ARG,"the second argument [is_public] of opensslReadKey must be integer");
	}
	char * password = NULL;
	if(argcount > 2) {
		zenglApi_GetFunArg(VM_ARG,3,&arg);
		if(arg.type != ZL_EXP_FAT_STR) {
			zenglApi_Exit(VM_ARG,"the third argument [password] of opensslReadKey must be string");
		}
		password = arg.val.str;
	}
	BIO * keybio = BIO_new_mem_buf(key, -1);
	if(keybio == NULL) {
		zenglApi_Exit(VM_ARG,"failed to create key BIO in opensslReadKey");
	}
	RSA * rsa = NULL;
	if(password != NULL) {
		OpenSSL_add_all_algorithms(); //密钥有经过口令加密需要这个函数
	}
	if(is_public) {
		rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, password);
	}
	else {
		rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, password);
	}
	BIO_free_all(keybio);
	if(rsa == NULL) {
		zenglApi_SetRetVal(VM_ARG,ZL_EXP_FAT_INT, ZL_EXP_NULL, 0, 0);
		return;
	}
	MODULE_OPENSSL_RSA_KEY * mod_openssl_rsa = zenglApi_AllocMem(VM_ARG, sizeof(MODULE_OPENSSL_RSA_KEY));
	mod_openssl_rsa->is_public_key = (is_public ? ZL_EXP_TRUE : ZL_EXP_FALSE);
	mod_openssl_rsa->rsa = rsa;
	MAIN_DATA * my_data = zenglApi_GetExtraData(VM_ARG, "my_data");
	int ret_code = resource_list_set_member(&(my_data->resource_list), mod_openssl_rsa, module_openssl_free_rsa_resource_callback);
	if(ret_code != 0) {
		zenglApi_Exit(VM_ARG, "opensslReadKey add resource to resource_list failed, resource_list_set_member error code:%d", ret_code);
	}
	zenglApi_SetRetVal(VM_ARG,ZL_EXP_FAT_INT, ZL_EXP_NULL, (ZL_EXP_LONG)mod_openssl_rsa, 0);
}

RSA加密解密模块函数:

    当前版本增加了 opensslPublicEncrypt(执行RSA公钥加密),opensslPrivateEncrypt(执行RSA私钥加密),opensslPrivateDecrypt(执行RSA私钥解密),opensslPublicDecrypt(执行RSA公钥解密)这四个和RSA加密解密相关的模块函数。这几个模块函数相关的C源码都位于module_openssl.c文件里:

/**
 * 下面的C函数是 opensslPublicEncrypt,opensslPrivateEncrypt,opensslPrivateDecrypt,opensslPublicDecrypt 这四个RSA加密解密模块函数的通用C代码
 * 第一个参数data表示需要加密或解密的原数据,可以是字符串类型,也可以是整数形式的指针类型
 * 第二个参数data_len表示需要加密或解密的原数据的字节大小,必须是整数类型
 * 第三个参数key表示密钥相关的key指针,也就是opensslReadKey模块函数返回的指针
 * 第四个参数&result必须是引用类型,用于存储加密或解密后的结果
 * 第五个参数padding是可选参数(如果提供了的话,必须是整数类型),表示加密或解密操作时的padding类型,目前暂时支持4个padding值(默认值是0):
 *  - 当padding值为0时表示 RSA_PKCS1_PADDING,
 *  - 当padding值为1时表示 RSA_PKCS1_OAEP_PADDING,
 *  - 当padding值为2时表示 RSA_SSLV23_PADDING,
 *  - 当padding值为3时表示 RSA_NO_PADDING
 *  上面的某些padding在有的操作中无法使用,例如:
 *  在1.0.2k-fips版本的openssl底层库中,私钥加密opensslPrivateEncrypt相关的底层库函数 RSA_private_encrypt 不支持 RSA_PKCS1_OAEP_PADDING 和 RSA_SSLV23_PADDING,
 *  详情可以通过man RSA_private_encrypt命令查看到,当提供了不支持的padding时,底层库函数也会反馈相应的错误信息
 *
 * 第六个参数decrypt_to_str是可选参数(如果提供了的话,也必须是整数类型),表示在进行RSA解密操作时,是否需要将result结果转为字符串类型,
 *  - decrypt_to_str参数的默认值是1表示需要将结果转为字符串类型,如果提供0值则表示不需要转为字符串类型,则结果会以整数类型的指针形式存储到result参数中
 *
 * 第七个参数use_block也是可选参数(如果提供了的话,也必须是整数类型),表示加密和解密操作时,是否需要根据key的尺寸进行分块的加密和解密操作,因为密钥key对
 * 加密或解密的数据是有尺寸要求的,超出尺寸时,会提示数据太长,因此将太长的数据进行分块,每块数据都使用相同的密钥,进行加密和解密,就可以解决这个问题。
 *  - 当use_block的值为1时表示需要进行分块处理,当为0时表示不需要进行分块处理,默认值为0表示不需要进行分块
 *
 * 例如:
	use builtin,openssl;
	use builtin,openssl;
	def RSA_PUBLIC 1;
	def RSA_PRIVATE 0;
	def RSA_PKCS1_PADDING 0;
	def TRUE 1;
	def FALSE 0;
	def NULL 0;
	def DUMP_HEX 2;

	fun exit(msg)
		print msg;
		bltExit();
	endfun

	fun read_rsa_key(file, is_public, password = '')
		.........................  // 省略中间代码,读取密钥key的代码可以参考opensslReadKey模块函数的示例代码
	endfun

	fun print_header()
		print '\n=======================================\n';
	endfun

	fun encrypt_and_decrypt(pub_pri, str, key, p_key, decrypt_to_str = TRUE, use_block = FALSE)
		print_header();

		if(pub_pri == 'public')
			if(use_block)
				enc_len = opensslPublicEncrypt(str, -1, key, &enc, RSA_PKCS1_PADDING, FALSE, use_block);
			else
				enc_len = opensslPublicEncrypt(str, -1, key, &enc);
			endif
		else
			enc_len = opensslPrivateEncrypt(str, -1, p_key, &enc, RSA_PKCS1_PADDING, FALSE, use_block);
		endif
		if(enc_len == -1)
			exit(pub_pri + ' encrypt failed: ' + opensslGetError());
		endif

		file_name = pub_pri + '_enc.data';
		bltWriteFile(file_name, enc, enc_len);
		bltReadFile(file_name, &file_data, &file_size, &file_data_ptr);
		print file_name + ' - size:' + file_size;
		print file_name + ' - data:' + bltDumpPtrData(file_data_ptr, file_size, DUMP_HEX);

		if(pub_pri == 'public')
			dec_len = opensslPrivateDecrypt(file_data_ptr, file_size, p_key, &dec, RSA_PKCS1_PADDING, decrypt_to_str, use_block);
		else
			dec_len = opensslPublicDecrypt(file_data_ptr, file_size, key, &dec, RSA_PKCS1_PADDING, decrypt_to_str, use_block);
		endif

		if(dec_len == -1)
			exit(pub_pri + ' decrypt failed: ' + opensslGetError());
		endif
		print 'decrypt_to_str: ' + decrypt_to_str;
		print 'dec_len:' + dec_len;
		if(decrypt_to_str)
			print 'dec:' + dec;
		else
			print 'dec ptr:' + dec;
			print 'dec ptr data:' + bltDumpPtrData(dec, dec_len, DUMP_CHAR);
			bltFree(dec);
		endif

		bltFree(enc);
	endfun

	key = read_rsa_key('rsa_public.key', RSA_PUBLIC);
	p_key = read_rsa_key('rsa_private.key', RSA_PRIVATE);
	p_aes_key = read_rsa_key('rsa_aes_private.key', RSA_PRIVATE, '111111');

	encrypt_and_decrypt('public', 'hello world!', key, p_key);

	encrypt_and_decrypt('private', '!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!', key, p_aes_key, TRUE, TRUE);

	encrypt_and_decrypt('public', 'hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!', key, p_key, TRUE, TRUE);

	encrypt_and_decrypt('private', '!!! hello world! other test!!!', key, p_aes_key);
	encrypt_and_decrypt('private2', '!!! hello world! hahaha ~~~', key, p_aes_key, FALSE);

	上面代码片段中的encrypt_and_decrypt是测试加密和解密操作的脚本函数,
	当该函数的第一个参数是public时,会先通过opensslPublicEncrypt进行公钥加密,再通过opensslPrivateDecrypt进行私钥解密,
	当该函数的第一个参数不是public时,,则会先通过opensslPrivateEncrypt进行私钥加密,再通过opensslPublicDecrypt进行公钥解密
	该脚本函数在进行加密和解密后,会将加密和解密的结果打印出来,当结果是整数类型的指针时,会通过bltDumpPtrData模块函数,将指针所指向的二进制数据以十六进制的格式显示出来。

	以上代码片段的执行结果类似如下所示:

	rsa_public.key file size: 451
	key:20127712
	rsa_private.key file size: 1679
	key:20129488
	rsa_aes_private.key file size: 1766
	key:20023904

	=======================================

	public_enc.data - size:256
	public_enc.data - data:05 D8 17 45 03 70 68 93 F5 98 AF E7 E2 64 04 53 AF D5 DF B4 44 36 30 06 82 78 71 B3 1C ......................
	decrypt_to_str: 1
	dec_len:12
	dec:hello world!

	=======================================

	private_enc.data - size:1024
	private_enc.data - data:C4 CC 02 82 F3 2D 83 F6 B7 40 4F EC 38 03 82 54 65 63 AD FE 0C 8D AF 82 98 A7 7C 79 EE ......................
	decrypt_to_str: 1
	dec_len:750
	dec:!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!

	=======================================

	public_enc.data - size:512
	public_enc.data - data:A6 0E 35 49 2D 0A 9D FC 4F D4 70 28 8E 78 79 3A 00 CD 19 B1 71 B5 35 AA D2 B1 A7 09 05 ......................
	decrypt_to_str: 1
	dec_len:372
	dec:hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!

	=======================================

	private_enc.data - size:256
	private_enc.data - data:29 C3 F5 11 92 AD C9 8E 07 2F 3E F6 8C FE 93 F9 3E D2 86 13 F4 51 78 24 CD D2 01 74 53 ......................
	decrypt_to_str: 1
	dec_len:30
	dec:!!! hello world! other test!!!

	=======================================

	private2_enc.data - size:256
	private2_enc.data - data:1C 7A FB 80 2D AE 74 5E DC 6E 6E C4 1C 9D 7F EB 14 42 82 63 2D AF CC E7 BF BC 33 7D C6 ......................
	decrypt_to_str: 0
	dec_len:27
	dec ptr:20125216
	dec ptr data:! ! !   h e l l o   w o r l d !   h a h a h a   ~ ~ ~
 */
static void common_encrypt_decrypt(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT argcount, const char * func_name,
		ZL_EXP_BOOL is_public, ZL_EXP_BOOL is_encrypt)
{
	ZENGL_EXPORT_MOD_FUN_ARG arg = {ZL_EXP_FAT_NONE,{0}};
	if(argcount < 4)
		zenglApi_Exit(VM_ARG,"usage: %s(data, data_len, key, &result[, padding = 0[, decrypt_to_str = 1[, use_block = 0]]]): integer", func_name);
	zenglApi_GetFunArg(VM_ARG,1,&arg);
	if(arg.type != ZL_EXP_FAT_STR && arg.type != ZL_EXP_FAT_INT) {
		zenglApi_Exit(VM_ARG,"the first argument [data] of %s must be string or integer", func_name);
	}
	unsigned char * data = NULL;
	ZL_EXP_BOOL is_data_str = ZL_EXP_FALSE;
	MAIN_DATA * my_data = zenglApi_GetExtraData(VM_ARG, "my_data");
	int data_ptr_size = 0;
	if(arg.type == ZL_EXP_FAT_STR) {
		data = (unsigned char *)arg.val.str;
		is_data_str = ZL_EXP_TRUE;
	}
	else {
		data = (unsigned char *)arg.val.integer;
		int ptr_idx = pointer_list_get_ptr_idx(&(my_data->pointer_list), data);
		if(ptr_idx < 0) {
			zenglApi_Exit(VM_ARG,"runtime error: the first argument [data] of %s is invalid pointer", func_name);
		}
		data_ptr_size = my_data->pointer_list.list[ptr_idx].ptr_size;
	}
	zenglApi_GetFunArg(VM_ARG,2,&arg);
	if(arg.type != ZL_EXP_FAT_INT) {
		zenglApi_Exit(VM_ARG,"the second argument [data_len] of %s must be integer", func_name);
	}
	int data_len = (int)arg.val.integer;
	if(data_len < 0 && is_data_str) {
		data_len = (int)strlen((char *)data);
	}
	if(data_ptr_size > 0 && data_len > data_ptr_size) {
		data_len = data_ptr_size;
	}
	zenglApi_GetFunArg(VM_ARG,3,&arg);
	if(arg.type != ZL_EXP_FAT_INT) {
		zenglApi_Exit(VM_ARG,"the third argument [key] of %s must be integer", func_name);
	}
	MODULE_OPENSSL_RSA_KEY * mod_openssl_rsa = (MODULE_OPENSSL_RSA_KEY *)arg.val.integer;
	if(!is_valid_rsa_key(&(my_data->resource_list), mod_openssl_rsa)) {
		zenglApi_Exit(VM_ARG,"%s runtime error: invalid key", func_name);
	}
	if(is_public) {
		if(!mod_openssl_rsa->is_public_key) {
			zenglApi_Exit(VM_ARG,"%s runtime error: the key is not a public key", func_name);
		}
	}
	else {
		if(mod_openssl_rsa->is_public_key) {
			zenglApi_Exit(VM_ARG,"%s runtime error: the key is not a private key", func_name);
		}
	}
	RSA * rsa = mod_openssl_rsa->rsa;
	int paddings[MODULE_OPENSSL_PADDING_NUM] = {
		RSA_PKCS1_PADDING,       // 索引: 0
		RSA_PKCS1_OAEP_PADDING,  // 索引: 1
		RSA_SSLV23_PADDING,      // 索引: 2
		RSA_NO_PADDING           // 索引: 3
	};
	int padding = paddings[0];
	if(argcount > 4) {
		zenglApi_GetFunArg(VM_ARG,5,&arg);
		if(arg.type != ZL_EXP_FAT_INT) {
			zenglApi_Exit(VM_ARG,"the fifth argument [padding] of %s must be integer", func_name);
		}
		int padding_idx = (int)arg.val.integer;
		if(padding_idx < 0 || padding_idx >= MODULE_OPENSSL_PADDING_NUM) {
			zenglApi_Exit(VM_ARG,"the fifth argument [padding] of %s is invalid, must be in [0, %d)", func_name, MODULE_OPENSSL_PADDING_NUM);
		}
		padding = paddings[padding_idx];
	}
	detect_arg_is_address_type(VM_ARG, 4, &arg, "fourth", "result", func_name);
	int rsa_size = RSA_size(rsa);
	int data_blocks = 1;
	int data_block_size = data_len;
	int result_block_size = rsa_size;
	ZL_EXP_BOOL use_block = ZL_EXP_FALSE;
	if(argcount > 6) {
		zenglApi_GetFunArg(VM_ARG,7,&arg);
		if(arg.type != ZL_EXP_FAT_INT) {
			zenglApi_Exit(VM_ARG,"the seventh argument [use_block] of %s must be integer", func_name);
		}
		if(arg.val.integer != 0)
			use_block = ZL_EXP_TRUE;
		else
			use_block = ZL_EXP_FALSE;
	}
	if(data_len > 0 && use_block) {
		if(is_public && is_encrypt) {
			switch(padding) {
			case RSA_SSLV23_PADDING:
			case RSA_PKCS1_PADDING:
				data_block_size = rsa_size - 12;
				break;
			case RSA_PKCS1_OAEP_PADDING:
				data_block_size = rsa_size - 42;
				break;
			case RSA_NO_PADDING:
				data_block_size = rsa_size - 1;
				break;
			}
			result_block_size = rsa_size;
		}
		else if(!is_public && !is_encrypt) {
			data_block_size = rsa_size;
			result_block_size = rsa_size - 1;
		}
		else if(!is_public && is_encrypt) {
			data_block_size = rsa_size - 12;
			result_block_size = rsa_size;
		}
		else {
			data_block_size = rsa_size;
			result_block_size = rsa_size - 12;
		}
		data_blocks = data_len / data_block_size;
		if(data_blocks > 0) {
			if(data_len % data_block_size > 0) {
				data_blocks += 1;
			}
		}
		else {
			data_blocks = 1;
		}
	}
	int result_size = data_blocks * result_block_size;
	unsigned char * result = (unsigned char *)zenglApi_AllocMem(VM_ARG, result_size);
	memset(result, 0, result_size);
	int retval = 0;
	int i;
	for(i = 0 ; i < data_blocks ; i++) {
		int data_block_len = data_block_size;
		if(data_len > 0) {
			if(i == (data_blocks - 1)) {
				data_block_len = data_len - (i * data_block_size);
			}
		}
		else
			data_block_len = 0;
		int inner_retval = 0;
		int data_step = i * data_block_size;
		if(is_public) {
			if(is_encrypt) {
				inner_retval = RSA_public_encrypt(data_block_len,data + data_step,result + retval,rsa,padding);
			}
			else {
				inner_retval = RSA_public_decrypt(data_block_len,data + data_step,result + retval,rsa,padding);
			}
		}
		else {
			if(is_encrypt) {
				inner_retval = RSA_private_encrypt(data_block_len,data + data_step,result + retval,rsa,padding);
			}
			else {
				inner_retval = RSA_private_decrypt(data_block_len,data + data_step,result + retval,rsa,padding);
			}
		}
		if(inner_retval == -1) {
			zenglApi_SetRetVal(VM_ARG,ZL_EXP_FAT_INT, ZL_EXP_NULL, (ZL_EXP_LONG)inner_retval, 0);
			return ;
		}
		retval += inner_retval;
	}
	ZL_EXP_BOOL is_result_ptr = ZL_EXP_FALSE;
	if(is_encrypt) {
		set_arg_value(VM_ARG, 4, ZL_EXP_FAT_INT, NULL, (ZL_EXP_LONG)result);
		is_result_ptr = ZL_EXP_TRUE;
	}
	else {
		int decrypt_to_str = ZL_EXP_TRUE;
		if(argcount > 5) {
			zenglApi_GetFunArg(VM_ARG,6,&arg);
			if(arg.type != ZL_EXP_FAT_INT) {
				zenglApi_Exit(VM_ARG,"the sixth argument [decrypt_to_str] of %s must be integer", func_name);
			}
			decrypt_to_str = (int)arg.val.integer;
		}
		if(decrypt_to_str) {
			result[retval] = '\0';
			set_arg_value(VM_ARG, 4, ZL_EXP_FAT_STR, (ZL_EXP_CHAR *)result, 0);
			zenglApi_FreeMem(VM_ARG, result);
		}
		else {
			set_arg_value(VM_ARG, 4, ZL_EXP_FAT_INT, NULL, (ZL_EXP_LONG)result);
			is_result_ptr = ZL_EXP_TRUE;
		}
	}
	if(is_result_ptr) {
		int ret_set_ptr = pointer_list_set_member(&(my_data->pointer_list), result, retval, module_openssl_free_ptr_callback);
		if(ret_set_ptr != 0) {
			zenglApi_Exit(VM_ARG, "%s add pointer to pointer_list failed, pointer_list_set_member error code:%d", func_name, ret_set_ptr);
		}
	}
	zenglApi_SetRetVal(VM_ARG,ZL_EXP_FAT_INT, ZL_EXP_NULL, (ZL_EXP_LONG)retval, 0);
}

...................................................................

/**
 * opensslPublicEncrypt模块函数,用于执行公钥加密操作,和此模块函数相关的详细说明请参考 common_encrypt_decrypt 函数的注释
 *
 * 模块函数版本历史:
 *  - v0.20.0版本新增此模块函数
 */
ZL_EXP_VOID module_openssl_public_encrypt(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT argcount)
{
	common_encrypt_decrypt(VM_ARG, argcount, "opensslPublicEncrypt", ZL_EXP_TRUE, ZL_EXP_TRUE);
}

/**
 * opensslPrivateDecrypt模块函数,用于执行私钥解密操作,和此模块函数相关的详细说明请参考 common_encrypt_decrypt 函数的注释
 *
 * 模块函数版本历史:
 *  - v0.20.0版本新增此模块函数
 */
ZL_EXP_VOID module_openssl_private_decrypt(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT argcount)
{
	common_encrypt_decrypt(VM_ARG, argcount, "opensslPrivateDecrypt", ZL_EXP_FALSE, ZL_EXP_FALSE);
}

/**
 * opensslPrivateEncrypt模块函数,用于执行私钥加密操作,和此模块函数相关的详细说明请参考 common_encrypt_decrypt 函数的注释
 *
 * 模块函数版本历史:
 *  - v0.20.0版本新增此模块函数
 */
ZL_EXP_VOID module_openssl_private_encrypt(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT argcount)
{
	common_encrypt_decrypt(VM_ARG, argcount, "opensslPrivateEncrypt", ZL_EXP_FALSE, ZL_EXP_TRUE);
}

/**
 * opensslPublicDecrypt模块函数,用于执行公钥解密操作,和此模块函数相关的详细说明请参考 common_encrypt_decrypt 函数的注释
 *
 * 模块函数版本历史:
 *  - v0.20.0版本新增此模块函数
 */
ZL_EXP_VOID module_openssl_public_decrypt(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT argcount)
{
	common_encrypt_decrypt(VM_ARG, argcount, "opensslPublicDecrypt", ZL_EXP_TRUE, ZL_EXP_FALSE);
}

RSA签名及验签模块函数:

    当前版本增加了 opensslSign 和 opensslVerify模块函数,用于执行RSA签名和验签的操作。相关的C源码位于module_openssl.c文件里:

/**
 * 下面C函数是 opensslSign 和 opensslVerify 模块函数的通用C代码
 * 第一个参数data表示RSA签名或验签的原数据,必须是字符串类型,或者是整数类型的指针
 * 第二个参数data_len表示签名或验签的原数据的字节大小,必须是整数类型
 * 第三个参数private_key|public_key表示签名需要的私钥key,或者验签需要的公钥key,通过opensslReadKey模块函数返回,必须是整数类型
 * 第四个参数当执行签名操作时,必须是引用类型,用于存储RSA签名的结果,如果是验签操作,则必须是整数类型的指针,用于指向验签用的签名数据
 * 第五个参数当执行签名操作时,必须是引用类型,用于存储RSA签名结果的字节大小,如果是验签操作,则必须是整数类型,表示用于验签的签名数据的字节大小
 * 第六个参数type必须是整数,表示签名数据类型,目前暂时只支持9种类型:
 *  - type 为0时表示 NID_sha 签名类型
 *  - type 为1时表示 NID_sha1 签名类型
 *  - type 为2时表示 NID_ripemd160 签名类型
 *  - type 为3时表示 NID_md5 签名类型
 *  - type 为4时表示 NID_md5_sha1 签名类型
 *  - type 为5时表示 NID_sha256 签名类型
 *  - type 为6时表示 NID_sha256WithRSAEncryption 签名类型
 *  - type 为7时表示 NID_sha512 签名类型
 *  - type 为8时表示 NID_sha512WithRSAEncryption 签名类型
 *  这些签名类型和底层openssl库的具体版本相关,如果底层库因为历史版本原因不支持某个签名类型时,有可能会报不支持该类型的错误
 *  无论底层库是否支持这些签名类型,也无论底层库中这些签名类型实际的宏值是多少,type值与签名类型的对应关系都不会变,也就是说
 *  当type为1时,它始终表示 NID_sha1 的签名类型,如果底层库不支持该类型的话,模块函数也会反馈相应的错误提示
 *  type是可选参数,默认值是0,也就是 NID_sha 签名类型
 *
 * 例如:
	use builtin,openssl;
	def RSA_PUBLIC 1;
	def RSA_PRIVATE 0;
	def RSA_SIGN_SHA1 1;
	def TRUE 1;
	def FALSE 0;
	def NULL 0;
	def DUMP_HEX 2;

	fun exit(msg)
		print msg;
		bltExit();
	endfun

	fun read_rsa_key(file, is_public, password = '')
		.........................  // 省略中间代码,读取密钥key的代码可以参考opensslReadKey模块函数的示例代码
	endfun

	fun print_header()
		print '\n=======================================\n';
	endfun

	fun sign_verify(str, p_key, verify_str, key, print_sign = TRUE, sign_type = RSA_SIGN_SHA1)
		if(print_sign)
			print_header();
		endif

		ret = opensslSign(str, -1, p_key, &sign, &sign_len, sign_type);
		if(!ret)
			exit('sign failed: ' + opensslGetError());
		endif

		if(print_sign)
			print 'sign len: ' + sign_len;
			print 'sign data: ' + bltDumpPtrData(sign, sign_len, DUMP_HEX);
		endif

		ret = opensslVerify(verify_str, -1, key, sign, sign_len, sign_type);
		print verify_str + ' - verify :' + (ret ? 'True' : 'False');

		bltFree(sign);
	endfun

	key = read_rsa_key('rsa_public.key', RSA_PUBLIC);
	p_key = read_rsa_key('rsa_private.key', RSA_PRIVATE);
	p_aes_key = read_rsa_key('rsa_aes_private.key', RSA_PRIVATE, '111111');

	sign_str = "hello world test sign!";
	sign_verify(sign_str, p_key, "hello world test sign!", key);
	sign_verify(sign_str, p_key, "hello world!", key, FALSE);

	上面的代码片段中的sign_verify脚本函数,是用于测试RSA签名和验证签名数据的函数,在该脚本函数里,会先通过opensslSign模块函数生成签名数据,
	再通过opensslVerify模块函数来验证签名数据

	该测试代码的执行结果类似如下所示:

	rsa_public.key file size: 451
	key:20127712
	rsa_private.key file size: 1679
	key:20129488
	rsa_aes_private.key file size: 1766
	key:20023904

	=======================================

	sign len: 256
	sign data: 90 6C CA F0 94 EA D9 FA 84 13 64 89 C1 EA A6 03 3C 27 DB 39 0D 6A A6 92 C6 DC 9E 74 77 .................................
	hello world test sign! - verify :True
	hello world! - verify :False

	从执行结果中可以看到,hello world test sign!通过了签名验证,而hello world!则没有通过签名验证
 */
static void common_sign_verify(ZL_EXP_VOID * VM_ARG, ZL_EXP_INT argcount, const char * func_name,
		ZL_EXP_BOOL is_sign)
{
	ZENGL_EXPORT_MOD_FUN_ARG arg = {ZL_EXP_FAT_NONE,{0}};
	if(argcount < 5) {
		if(is_sign)
			zenglApi_Exit(VM_ARG,"usage: %s(data, data_len, private_key, &sigret, &siglen[, type = 0]): integer", func_name);
		else
			zenglApi_Exit(VM_ARG,"usage: %s(data, data_len, public_key, sigbuf, siglen[, type = 0]): integer", func_name);
	}
	zenglApi_GetFunArg(VM_ARG,1,&arg);
	if(arg.type != ZL_EXP_FAT_STR && arg.type != ZL_EXP_FAT_INT) {
		zenglApi_Exit(VM_ARG,"the first argument [data] of %s must be string or integer", func_name);
	}
	unsigned char * data = NULL;
	ZL_EXP_BOOL is_data_str = ZL_EXP_FALSE;
	MAIN_DATA * my_data = zenglApi_GetExtraData(VM_ARG, "my_data");
	int data_ptr_size = 0;
	if(arg.type == ZL_EXP_FAT_STR) {
		data = (unsigned char *)arg.val.str;
		is_data_str = ZL_EXP_TRUE;
	}
	else {
		data = (unsigned char *)arg.val.integer;
		int ptr_idx = pointer_list_get_ptr_idx(&(my_data->pointer_list), data);
		if(ptr_idx < 0) {
			zenglApi_Exit(VM_ARG,"runtime error: the first argument [data] of %s is invalid pointer", func_name);
		}
		data_ptr_size = my_data->pointer_list.list[ptr_idx].ptr_size;
	}
	zenglApi_GetFunArg(VM_ARG,2,&arg);
	if(arg.type != ZL_EXP_FAT_INT) {
		zenglApi_Exit(VM_ARG,"the second argument [data_len] of %s must be integer", func_name);
	}
	int data_len = (int)arg.val.integer;
	if(data_len < 0 && is_data_str) {
		data_len = (int)strlen((char *)data);
	}
	if(data_ptr_size > 0 && data_len > data_ptr_size) {
		data_len = data_ptr_size;
	}
	zenglApi_GetFunArg(VM_ARG,3,&arg);
	if(arg.type != ZL_EXP_FAT_INT) {
		zenglApi_Exit(VM_ARG,"the third argument [key] of %s must be integer", func_name);
	}
	MODULE_OPENSSL_RSA_KEY * mod_openssl_rsa = (MODULE_OPENSSL_RSA_KEY *)arg.val.integer;
	if(!is_valid_rsa_key(&(my_data->resource_list), mod_openssl_rsa)) {
		zenglApi_Exit(VM_ARG,"%s runtime error: invalid key", func_name);
	}
	if(is_sign) {
		if(mod_openssl_rsa->is_public_key) {
			zenglApi_Exit(VM_ARG,"%s runtime error: the key is not a private key", func_name);
		}
	}
	else {
		if(!mod_openssl_rsa->is_public_key) {
			zenglApi_Exit(VM_ARG,"%s runtime error: the key is not a public key", func_name);
		}
	}
	RSA * rsa = mod_openssl_rsa->rsa;
	if(is_sign) {
		detect_arg_is_address_type(VM_ARG, 4, &arg, "fourth", "sigret", func_name);
		detect_arg_is_address_type(VM_ARG, 5, &arg, "fifth", "siglen", func_name);
	}
	int sign_types[MODULE_OPENSSL_SIGN_TYPE] = {
		MOD_OPENSSL_NID_sha,                       // 索引: 0
		MOD_OPENSSL_NID_sha1,                      // 索引: 1
		MOD_OPENSSL_NID_ripemd160,                 // 索引: 2
		MOD_OPENSSL_NID_md5,                       // 索引: 3
		MOD_OPENSSL_NID_md5_sha1,                  // 索引: 4
		MOD_OPENSSL_NID_sha256,                    // 索引: 5
		MOD_OPENSSL_NID_sha256WithRSAEncryption,   // 索引: 6
		MOD_OPENSSL_NID_sha512,                    // 索引: 7
		MOD_OPENSSL_NID_sha512WithRSAEncryption    // 索引: 8
	};
	int sign_type_idx = 0;
	int sign_type = sign_types[sign_type_idx];
	if(argcount > 5) {
		zenglApi_GetFunArg(VM_ARG,6,&arg);
		if(arg.type != ZL_EXP_FAT_INT) {
			zenglApi_Exit(VM_ARG,"the sixth argument [type] of %s must be integer", func_name);
		}
		sign_type_idx = (int)arg.val.integer;
		if(sign_type_idx < 0 || sign_type_idx >= MODULE_OPENSSL_SIGN_TYPE) {
			zenglApi_Exit(VM_ARG,"the sixth argument [type] of %s is invalid, must be in [0, %d)", func_name, MODULE_OPENSSL_SIGN_TYPE);
		}
		sign_type = sign_types[sign_type_idx];
	}
	if(sign_type == -1) {
		zenglApi_Exit(VM_ARG,"the sixth argument [type:%d] of %s is not supported", sign_type_idx, func_name);
	}
	if(is_sign) {
		int rsa_len = RSA_size(rsa);
		unsigned char * sigret = (unsigned char *)zenglApi_AllocMem(VM_ARG, rsa_len);
		memset(sigret, 0, rsa_len);
		unsigned int siglen = 0;
		int retval = RSA_sign(sign_type, data, data_len, sigret, &siglen, rsa);
		if(!retval) {
			zenglApi_FreeMem(VM_ARG, sigret);
			set_arg_value(VM_ARG, 4, ZL_EXP_FAT_INT, NULL, 0);
			set_arg_value(VM_ARG, 5, ZL_EXP_FAT_INT, NULL, 0);
			zenglApi_SetRetVal(VM_ARG,ZL_EXP_FAT_INT, ZL_EXP_NULL, 0, 0);
		}
		else {
			set_arg_value(VM_ARG, 4, ZL_EXP_FAT_INT, NULL, (ZL_EXP_LONG)sigret);
			set_arg_value(VM_ARG, 5, ZL_EXP_FAT_INT, NULL, (ZL_EXP_LONG)siglen);
			int ret_set_ptr = pointer_list_set_member(&(my_data->pointer_list), sigret, siglen, module_openssl_free_ptr_callback);
			if(ret_set_ptr != 0) {
				zenglApi_Exit(VM_ARG, "%s add pointer to pointer_list failed, pointer_list_set_member error code:%d", func_name, ret_set_ptr);
			}
			zenglApi_SetRetVal(VM_ARG,ZL_EXP_FAT_INT, ZL_EXP_NULL, 1, 0);
		}
	}
	else {
		zenglApi_GetFunArg(VM_ARG,4,&arg);
		if(arg.type != ZL_EXP_FAT_INT) {
			zenglApi_Exit(VM_ARG,"the fourth argument [sigbuf] of %s must be integer", func_name);
		}
		unsigned char * sigbuf = (unsigned char *)arg.val.integer;
		int sigbuf_ptr_idx = pointer_list_get_ptr_idx(&(my_data->pointer_list), sigbuf);
		if(sigbuf_ptr_idx < 0) {
			zenglApi_Exit(VM_ARG,"runtime error: the fourth argument [sigbuf] of %s is invalid pointer", func_name);
		}
		int sigbuf_ptr_size = my_data->pointer_list.list[sigbuf_ptr_idx].ptr_size;
		zenglApi_GetFunArg(VM_ARG,5,&arg);
		if(arg.type != ZL_EXP_FAT_INT) {
			zenglApi_Exit(VM_ARG,"the fifth argument [siglen] of %s must be integer", func_name);
		}
		unsigned int siglen = (unsigned int)arg.val.integer;
		if(sigbuf_ptr_size > 0 && siglen > sigbuf_ptr_size) {
			siglen = sigbuf_ptr_size;
		}
		int retval = RSA_verify(sign_type, data, data_len, sigbuf, siglen, rsa);
		if(!retval) {
			zenglApi_SetRetVal(VM_ARG,ZL_EXP_FAT_INT, ZL_EXP_NULL, 0, 0);
		}
		else {
			zenglApi_SetRetVal(VM_ARG,ZL_EXP_FAT_INT, ZL_EXP_NULL, 1, 0);
		}
	}
}

............................................................................................

/**
 * opensslSign模块函数,用于生成RSA签名数据,和此模块函数相关的详细说明请参考 common_sign_verify 函数的注释
 *
 * 模块函数版本历史:
 *  - v0.20.0版本新增此模块函数
 */
ZL_EXP_VOID module_openssl_sign(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT argcount)
{
	common_sign_verify(VM_ARG, argcount, "opensslSign", ZL_EXP_TRUE);
}

/**
 * opensslVerify模块函数,用于验证RSA签名数据,和此模块函数相关的详细说明请参考 common_sign_verify 函数的注释
 *
 * 模块函数版本历史:
 *  - v0.20.0版本新增此模块函数
 */
ZL_EXP_VOID module_openssl_verify(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT argcount)
{
	common_sign_verify(VM_ARG, argcount, "opensslVerify", ZL_EXP_FALSE);
}

opensslFreeKey模块函数:

    opensslFreeKey模块函数,用于释放opensslReadKey返回的密钥key,和此模块函数相关的C源码也位于module_openssl.c文件中:

/**
 * opensslFreeKey模块函数,用于释放opensslReadKey返回的密钥key
 * 该模块函数的参数是可变参数,用法:opensslFreeKey(key1, key2, key3......)
 * 每个参数都必须是有效的密钥key
 *
 * 例如:
	use builtin,openssl;
	def RSA_PUBLIC 1;
	def RSA_PRIVATE 0;

	.................................. // 省略中间代码

	key = read_rsa_key('rsa_public.key', RSA_PUBLIC);
	p_key = read_rsa_key('rsa_private.key', RSA_PRIVATE);
	p_aes_key = read_rsa_key('rsa_aes_private.key', RSA_PRIVATE, '111111');

	.................................. // 省略中间代码

	opensslFreeKey(key, p_key, p_aes_key);

	上面在用完key,p_key等密钥key后,就通过opensslFreeKey将这些密钥key给释放掉了,释放掉的密钥不能再用于加密解密,签名验签等操作,
	如果释放后,还继续使用这些key的话,加密解密等模块函数会反馈相应的错误

	模块函数版本历史:
	- v0.20.0版本新增此模块函数
 */
ZL_EXP_VOID module_openssl_free_key(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT argcount)
{
	ZENGL_EXPORT_MOD_FUN_ARG arg = {ZL_EXP_FAT_NONE,{0}};
	const char * func_name = "opensslFreeKey";
	if(argcount < 1) {
		zenglApi_Exit(VM_ARG,"usage: %s(key...): integer", func_name);
	}
	int i;
	MAIN_DATA * my_data = zenglApi_GetExtraData(VM_ARG, "my_data");
	for(i = 1; i <= argcount; i++) {
		zenglApi_GetFunArg(VM_ARG,i,&arg);
		if(arg.type != ZL_EXP_FAT_INT) {
			zenglApi_Exit(VM_ARG,"the %d argument of %s must be integer", i, func_name);
		}
		MODULE_OPENSSL_RSA_KEY * mod_openssl_rsa = (MODULE_OPENSSL_RSA_KEY *)arg.val.integer;
		if(!is_valid_rsa_key(&(my_data->resource_list), mod_openssl_rsa)) {
			zenglApi_Exit(VM_ARG,"runtime error: the %d argument of %s is invalid key", i, func_name);
		}
		module_openssl_free_rsa_resource_callback(VM_ARG, mod_openssl_rsa);
		int ret_code = resource_list_remove_member(&(my_data->resource_list), mod_openssl_rsa); // 将释放掉的实例指针从资源列表中移除
		if(ret_code != 0) {
			zenglApi_Exit(VM_ARG, "%s remove resource from resource_list failed [the %d argument], resource_list_remove_member error code:%d",
					func_name, i, ret_code);
		}
	}
	zenglApi_SetRetVal(VM_ARG,ZL_EXP_FAT_INT, ZL_EXP_NULL, i, 0);
}

bltDumpPtrData模块函数:

    当前版本增加了bltDumpPtrData模块函数,用于以十进制,十六进制,八进制等形式显示出指针所指向的二进制数据。相关的C源码位于module_builtin.c文件中:

/**
 * bltDumpPtrData模块函数,以十进制,十六进制,八进制等形式显示出指针所指向的二进制数据
 * 第一个ptr必须是整数类型的数据指针,每个数据指针(和资源指针不同)都会记录在内部的pointer_list列表中,不在该列表中的指针都是无效的数据指针
 * 第二个参数ptr_data_len必须是整数类型,表示需要将该指针所指向的多少字节的数据给显示出来,每个数据指针所指向的数据都有一个尺寸,超出尺寸的数据不会被显示出来
 * 第三个参数format也必须是整数类型,表示以什么格式来显示二进制数据
 *  - 当format为0时,表示以十进制整数显示出来,可能是负数
 *  - 当format为1时,表示以十进制无符号整数显示出来,没有负数
 *  - 当format为2时,表示以十六进制格式显示出来
 *  - 当format为3时,表示以ASCII字符形式显示出来
 *  - 当format为4时,表示以八进制格式显示出来
 *
 * 例如:
	use builtin;
	def DUMP_HEX 2;

	........................ // 省略中间代码

	bltReadFile('private_enc.data', &file_data, &file_size, &file_data_ptr);
	print file_name + ' - size:' + file_size;
	print file_name + ' - data:' + bltDumpPtrData(file_data_ptr, file_size, DUMP_HEX);

	上面代码片段,将文件数据读取出来,并将file_data_ptr设置为指向这些数据的指针,最后通过bltDumpPtrData根据file_data_ptr指针,将这些数据以十六进制格式显示出来

	以上代码片段的执行结果类似如下所示:

	private_enc.data - size:1024
	private_enc.data - data:C4 CC 02 82 F3 2D 83 F6 B7 40 4F EC 38 03 82 54 65 63 AD FE 0C 8D AF 82 98 A7 7C 79 EE ......................
 */
ZL_EXP_VOID module_builtin_dump_ptr_data(ZL_EXP_VOID * VM_ARG, ZL_EXP_INT argcount)
{
	ZENGL_EXPORT_MOD_FUN_ARG arg = {ZL_EXP_FAT_NONE,{0}};
	if(argcount < 3)
		zenglApi_Exit(VM_ARG,"usage: bltDumpPtrData(ptr, ptr_data_len, format): string");
	zenglApi_GetFunArg(VM_ARG,1,&arg);
	if(arg.type != ZL_EXP_FAT_INT && arg.type != ZL_EXP_FAT_STR) {
		zenglApi_Exit(VM_ARG,"the first argument [ptr] of bltDumpPtrData must be integer or string");
	}
	unsigned char * ptr = NULL;
	ZL_EXP_BOOL is_ptr_str = ZL_EXP_FALSE;
	if(arg.type == ZL_EXP_FAT_INT)
		ptr = (unsigned char *)arg.val.integer;
	else {
		ptr = (unsigned char *)arg.val.str;
		is_ptr_str = ZL_EXP_TRUE;
	}
	int ptr_size = 0;
	if(!is_ptr_str) {
		MAIN_DATA * my_data = zenglApi_GetExtraData(VM_ARG, "my_data");
		int ptr_idx = pointer_list_get_ptr_idx(&(my_data->pointer_list), ptr);
		if(ptr_idx < 0) {
			zenglApi_Exit(VM_ARG,"runtime error: the first argument [ptr] of bltDumpPtrData is invalid pointer");
		}
		ptr_size = my_data->pointer_list.list[ptr_idx].ptr_size;
	}
	zenglApi_GetFunArg(VM_ARG,2,&arg);
	if(arg.type != ZL_EXP_FAT_INT) {
		zenglApi_Exit(VM_ARG,"the second argument [ptr_data_len] of bltDumpPtrData must be integer");
	}
	int ptr_data_len = (int)arg.val.integer;
	if(ptr_data_len < 0)
		ptr_data_len = 0;
	if(is_ptr_str) {
		if(ptr_data_len > strlen((char *)ptr))
			ptr_data_len = strlen((char *)ptr);
	}
	else if(ptr_size > 0 && ptr_data_len > ptr_size) {
		ptr_data_len = ptr_size;
	}
	zenglApi_GetFunArg(VM_ARG,3,&arg);
	if(arg.type != ZL_EXP_FAT_INT) {
		zenglApi_Exit(VM_ARG,"the third argument [format] of bltDumpPtrData must be integer");
	}
	int format = arg.val.integer;
	BUILTIN_INFO_STRING infoString = { 0 };
	int i;
	for(i = 0; i < ptr_data_len; i++) {
		switch (format) {
		case MODULE_BUILTIN_DUMP_INT:
			builtin_make_info_string(VM_ARG, &infoString, "%03d ", (int)ptr[i]);
			break;
		case MODULE_BUILTIN_DUMP_UINT:
			builtin_make_info_string(VM_ARG, &infoString, "%03u ", (unsigned int)ptr[i]);
			break;
		case MODULE_BUILTIN_DUMP_HEX:
			builtin_make_info_string(VM_ARG, &infoString, "%02X ", (unsigned int)ptr[i]);
			break;
		case MODULE_BUILTIN_DUMP_OCTAL:
			builtin_make_info_string(VM_ARG, &infoString, "%03o ", (unsigned int)ptr[i]);
			break;
		case MODULE_BUILTIN_DUMP_CHAR:
			builtin_make_info_string(VM_ARG, &infoString, "%c ", (unsigned char)ptr[i]);
			break;
		default:
			zenglApi_Exit(VM_ARG,"the third argument [format] of bltDumpPtrData is invalid number");
			break;
		}
	}
	if(infoString.str != NULL) {
		zenglApi_SetRetVal(VM_ARG, ZL_EXP_FAT_STR, infoString.str, 0, 0);
		zenglApi_FreeMem(VM_ARG, infoString.str);
	}
	else
		zenglApi_SetRetVal(VM_ARG, ZL_EXP_FAT_STR, "", 0, 0);
}

test_openssl.zl测试脚本:

    为了测试openssl相关的模块函数,当前版本在my_webroot目录中增加了v0_20_0的子目录,并在该目录中增加了test_openssl.zl的测试脚本,该脚本的代码如下:

use builtin,openssl;
def RSA_PUBLIC 1;
def RSA_PRIVATE 0;
def RSA_PKCS1_PADDING 0;

def RSA_SIGN_SHA1 1;

def TRUE 1;
def FALSE 0;

def NULL 0;

def DUMP_CHAR 3;
def DUMP_HEX 2;
def DUMP_OCTAL 4;

// 判断是命令行模式,还是普通的web模式,如果是普通的web模式,则将br设置为<br/>即html格式的换行标签
if(bltIsRunInCmd())
	bltSetImmediatePrint(TRUE);
	print 'now in cmd';
	is_cmd = TRUE;
	br = '';
else
	is_cmd = FALSE;
	br = '<br/>';
	print 'now in website' + br;
endif

// 退出脚本并打印相应的信息
fun exit(msg)
	global is_cmd,br;
	print msg + br;
	bltExit();
endfun

// 从文件中读取rsa密钥key,并返回密钥key相关的资源指针,is_public表示读取的是公钥还是私钥,password表示密钥密码(如果密钥经过了加密处理,则需要提供相关的密码)
fun read_rsa_key(file, is_public, password = '')
	global is_cmd,br;
	ret = bltReadFile(file, &key_content, &file_size);
	if(ret == 0)
		print file + ' file size: ' + file_size + br;
		if(password)
			key = opensslReadKey(key_content, is_public, password);
		else
			key = opensslReadKey(key_content, is_public);
		endif
		if(key == NULL)
			exit('read key "'+ file +'" failed: ' + opensslGetError());
		endif
		print 'key:' + key + br;
		return key;
	else
		exit('read '+file+' failed, maybe the file does not exists, or open failed.');
	endif
endfun

// 打印分隔符
fun print_header()
	global is_cmd,br;
	if(is_cmd)
		print '\n=======================================\n';
	else
		print br + '=======================================' + br + br;
	endif
endfun

// 当pub_pri为public时,执行公钥加密,私钥解密,否则执行私钥加密,公钥解密
fun encrypt_and_decrypt(pub_pri, str, key, p_key, decrypt_to_str = TRUE, use_block = FALSE)
	global is_cmd,br;
	print_header();

	if(pub_pri == 'public')
		if(use_block)
			enc_len = opensslPublicEncrypt(str, -1, key, &enc, RSA_PKCS1_PADDING, FALSE, use_block);
		else
			enc_len = opensslPublicEncrypt(str, -1, key, &enc);
		endif
	else
		enc_len = opensslPrivateEncrypt(str, -1, p_key, &enc, RSA_PKCS1_PADDING, FALSE, use_block);
	endif	
	if(enc_len == -1)
		exit(pub_pri + ' encrypt failed: ' + opensslGetError());
	endif

	file_name = pub_pri + '_enc.data';
	bltWriteFile(file_name, enc, enc_len);
	bltReadFile(file_name, &file_data, &file_size, &file_data_ptr);
	print file_name + ' - size:' + file_size + br;
	print file_name + ' - data:' + bltDumpPtrData(file_data_ptr, file_size, DUMP_HEX) + br;

	if(pub_pri == 'public')
		dec_len = opensslPrivateDecrypt(file_data_ptr, file_size, p_key, &dec, RSA_PKCS1_PADDING, decrypt_to_str, use_block);
	else
		dec_len = opensslPublicDecrypt(file_data_ptr, file_size, key, &dec, RSA_PKCS1_PADDING, decrypt_to_str, use_block);
	endif

	if(dec_len == -1)
		exit(pub_pri + ' decrypt failed: ' + opensslGetError());
	endif
	print 'decrypt_to_str: ' + decrypt_to_str + br;
	print 'dec_len:' + dec_len + br;
	if(decrypt_to_str)
		print 'dec:' + dec + br;
	else
		print 'dec ptr:' + dec + br;
		print 'dec ptr data:' + bltDumpPtrData(dec, dec_len, DUMP_CHAR) + br;
		bltFree(dec);
	endif

	bltFree(enc);
endfun

// 执行RSA签名和验签操作
fun sign_verify(str, p_key, verify_str, key, print_sign = TRUE, sign_type = RSA_SIGN_SHA1)
	global is_cmd,br;
	if(print_sign)
		print_header();
	endif

	ret = opensslSign(str, -1, p_key, &sign, &sign_len, sign_type);
	if(!ret)
		exit('sign failed: ' + opensslGetError());
	endif

	if(print_sign)
		print 'sign len: ' + sign_len + br;
		print 'sign data: ' + bltDumpPtrData(sign, sign_len, DUMP_HEX) + br;
	endif

	ret = opensslVerify(verify_str, -1, key, sign, sign_len, sign_type);
	print verify_str + ' - verify :' + (ret ? 'True' : 'False') + br;

	bltFree(sign);
endfun

// 下面读取公钥key,私钥key以及加密的私钥key
key = read_rsa_key('rsa_public.key', RSA_PUBLIC);
p_key = read_rsa_key('rsa_private.key', RSA_PRIVATE);
p_aes_key = read_rsa_key('rsa_aes_private.key', RSA_PRIVATE, '111111');

// 下面通过encrypt_and_decrypt测试RSA加密解密

encrypt_and_decrypt('public', 'hello world!', key, p_key);

encrypt_and_decrypt('private', '!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!', key, p_aes_key, TRUE, TRUE);

encrypt_and_decrypt('public', 'hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!', key, p_key, TRUE, TRUE);

encrypt_and_decrypt('private', '!!! hello world! other test!!!', key, p_aes_key);
encrypt_and_decrypt('private2', '!!! hello world! hahaha ~~~', key, p_aes_key, FALSE);

// 下面通过sign_verify测试RSA签名和验签
sign_str = "hello world test sign!";
sign_verify(sign_str, p_key, "hello world test sign!", key);
sign_verify(sign_str, p_key, "hello world!", key, FALSE);

// 释放掉密钥key
opensslFreeKey(key, p_key, p_aes_key);

    该脚本在命令行中的执行结果,类似如下所示:

[root@localhost zenglServer]# ./zenglServer -r "/v0_20_0/test_openssl.zl"
now in cmd
rsa_public.key file size: 451
key:10498016
rsa_private.key file size: 1679
key:10499792
rsa_aes_private.key file size: 1766
key:10394208

=======================================

public_enc.data - size:256
public_enc.data - data:40 96 29 B5 84 6F D6 0F E1 71 BB CA 64 64 83 71 58 92 AC 4D B7 DE 2C 9F 41 3A 88 F1 94 D4 54 68 13 99 CB 31 E4 D8 45 C9 92 BC B3 31 5B 7D 18 10 F0 69 3C F6 9E 7B F5 7B E1 2F 07 97 01 3D 7B E7 6F BA 2A FC EE 8F B5 02 E0 92 A6 D4 26 A3 E6 E9 53 F6 FA 5D DB 81 4D 46 2E 0F BA DD 08 DB 9F F9 30 0D 5F 90 8E 28 79 86 FA 44 3A 28 EA EE D0 87 8C 88 D4 79 63 1B 68 E0 89 2C 38 B0 49 BF 12 3D EE 77 49 94 62 93 1A A0 3E 8C 00 2A 4F 4D 20 04 1F D6 76 38 F7 BF 69 52 07 86 B3 E7 67 AE 03 37 8F 8C 1B 48 23 83 A8 F6 4F 50 D3 BD 28 39 44 35 44 98 7F BE 50 96 74 DD A2 18 49 A0 1F F1 90 E3 F3 1F 88 65 44 1D 7A 79 15 A5 56 DA C6 87 35 7A 90 9A AF 81 13 E1 69 C3 A9 90 16 19 90 8C 72 AA F8 DF 65 C3 14 79 DF C7 1A 92 59 71 1E 8B 5C CB 0D 14 1E CE 9C 24 9A D4 62 60 3C CA 3E BF 21 98 
decrypt_to_str: 1
dec_len:12
dec:hello world!

=======================================

private_enc.data - size:1024
private_enc.data - data:C4 CC 02 82 F3 2D 83 F6 B7 40 4F EC 38 03 82 54 65 63 AD FE 0C 8D AF 82 98 A7 7C 79 EE 2E 4B 63 49 9F 86 68 DC CB 86 0C B2 7B 46 77 E4 FA 54 1A 16 73 43 9A 35 87 89 38 6A 5B 4B C5 85 01 79 91 BE 91 11 1E 59 F1 C5 F8 B1 2D B8 6C 3E CF DB BB 8F 34 3B 15 C3 8B 18 95 E4 E9 9C 1B 83 42 95 6C D9 4F BD A2 B7 49 68 3E 5D 5F 63 B7 0B C8 95 E6 57 31 60 0E D8 3A E0 B6 2A E9 76 D0 57 E6 C3 0F 2F 9C A2 47 88 31 D0 53 93 B8 85 C4 2E 2B 86 6E 44 D2 88 97 C6 51 54 AA C9 11 6B 92 25 44 98 65 7E 69 89 18 4F 1B 60 6C 7D 15 FB 99 A0 07 56 75 46 62 A1 5C 43 78 46 19 A1 48 CD 21 9C B9 8F A0 C7 59 18 19 EA 9E EB 4A BB 1D C4 62 7A 89 C9 0B D3 41 D3 64 99 84 B5 CB 01 B9 BA BD C5 3D A0 D6 0A 5F F5 3B 16 FE 23 1B 31 82 0C 05 6E EA 8A DC 12 FE FE 83 33 97 70 D8 66 2C 32 FB A5 BC 96 43 2D 7F 8E 16 0B FD EE E2 E4 67 01 F7 99 0B A7 B2 15 21 74 B5 AC 6C D5 38 80 2B 26 DB 71 BA 8A 7A C7 D8 1B 75 CC 19 22 B4 12 83 9D EA D7 4D 8B 4D 9A 34 10 9B 0E B6 B2 DB 4A 2F 54 78 06 5A B6 0B 39 8B 5F 7C 1C A6 A1 62 64 41 42 91 E8 00 91 31 1C 21 D0 0B E8 1C B9 50 21 04 E9 CD B3 66 F3 F8 31 27 D8 1D 8A 56 A5 6D 7A 7C B9 FB 9B 85 48 E9 DC 75 A7 2E A6 4D 87 11 B0 44 78 CA D9 4E D0 38 30 94 5F 3D 52 46 ED A2 E2 1D 21 5E 09 1E 1C 32 2B 3E 41 B5 0E 3E 77 BE C2 69 19 3B 2C 43 9F D4 60 EA 7B DE FE 58 C9 8D 11 41 2B 9B A0 49 13 FD 7A E4 25 89 79 00 11 0B 70 5D CC 52 F0 1A F4 C7 AB A2 31 F6 A6 7F D4 99 B3 A8 92 DE 8E B8 EC 38 47 C4 4C D9 23 1A 4C F8 3E DC 9D 0C 6D 11 16 98 7E 7B 97 3A 56 62 A7 60 A7 31 46 CA 29 95 AE A9 F7 55 89 9E 1D 45 14 A7 83 5B 05 E7 08 B0 E3 E7 87 9C 4F 76 36 AD 62 10 94 B8 D2 ED 02 7F 08 A5 A8 E4 5F 6B 42 2E 09 3E 9B 7E 5A BA A6 BC 50 D5 70 48 E2 2E 84 C2 03 B2 1E 37 1C 64 A4 7B BE 80 01 E0 76 15 1A F7 BD D1 8E 17 6F D0 EC 23 7E 8D 6F 8B D9 D3 16 AC F4 67 B6 B7 5F F2 22 19 B6 C8 E1 56 52 A4 3C E9 20 F3 94 F3 63 6F C6 48 FA A2 CF FF 21 85 C3 32 72 91 9A DC 98 93 33 BA A4 E2 00 35 AD EB BE 74 E8 F2 21 41 47 83 B8 FD 6D DE 21 58 88 B9 37 3F 33 85 52 FE E6 05 96 B1 D5 08 1D 0C 77 FE C0 64 3D 02 6B E1 3E AE 76 E4 5B 63 16 1F E4 24 46 0A 2A 57 90 29 B0 26 6D CC 5B 63 F1 42 F5 28 C2 5D 36 69 34 67 CA 2D AC 8C 7A 7D A6 2E 86 DA D1 B3 BD B7 5A C5 9A 7C 23 B0 09 35 FC 0E 17 51 F2 F4 F6 A8 0D 3F 1A 51 B3 2E CB F0 5B D9 73 EC F6 31 8E 8B A4 7C C8 21 DA B2 05 1A FC 2C D6 A5 D8 51 B1 C6 B4 E1 9F A2 C4 2A DD DA 32 80 BB 11 E4 B5 61 2B D9 DA 8D 78 AC B8 73 BE 26 08 5E 70 D4 C3 90 5F 9E 8A E3 C9 99 E7 40 E7 92 B7 2C B9 DA 06 64 92 F8 F8 91 86 08 25 91 2B ED 48 FF 7B 33 F6 93 C6 F2 31 BC 1F DC D2 96 A8 21 8F F4 A0 E1 42 90 CC 80 AD CD EE 70 BC D5 66 C5 A4 09 47 4C 07 DB E6 38 0A 2B B4 FD 08 A0 75 15 2C 32 D8 98 05 75 8E E9 99 C8 BB 6F 8D 41 D2 10 5A 0F 8B 15 DA 42 F4 0C 86 50 32 DC 2E A1 D2 4A B3 53 86 78 5E E5 5A C7 16 7E E4 8C 66 73 5F F9 CB E1 41 33 AF 41 CF 35 C3 31 86 32 9D 4C 78 69 14 43 25 A6 1E 96 9E D8 FF E3 7D 7E 94 08 73 C1 0F 05 DD 28 3A E4 D4 D8 70 3A 8D E0 70 45 A3 73 09 C8 7B B4 72 94 18 25 07 B3 DA F7 E6 CE D9 B1 58 2E AA F0 D7 FC 42 A7 C8 94 4A EB DB F5 59 0B A0 86 4D 86 61 26 43 11 CF AC 26 94 23 EA 97 EC 4A B9 BE 21 19 85 06 9D BA 38 BB E4 A8 AC 27 
decrypt_to_str: 1
dec_len:750
dec:!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!!!! hello world! other test!!!

=======================================

public_enc.data - size:512
public_enc.data - data:89 0A 19 E7 59 04 AC B8 3C 75 4E DA 10 65 A2 7A 48 C3 98 EA FA EF 52 D0 1A 83 50 26 33 62 4A 20 7F 13 45 06 DA D4 64 C5 A1 BA 6D E6 F2 74 80 57 C7 7D 20 E3 E8 E5 FF 5B 3C 2F 35 BB 6F 2B 84 C0 03 D8 E2 6E E3 92 E9 34 2A E1 5D 92 C5 C3 07 2B 45 14 BD DC BC 75 B7 D4 55 54 85 B0 06 71 28 50 E4 68 5F E6 96 E5 F7 BE 1C 7D 8F 65 C2 58 D4 DC E4 02 7C 94 3C 01 33 F7 48 1F 57 84 89 27 51 E8 F8 B2 E6 89 82 02 66 00 02 8A 3A 09 1B A5 49 C5 2B 15 82 2D 24 45 B9 31 E9 65 07 7E D1 E4 6B C2 26 B4 BD FA 5D 4A 85 1F A2 01 F6 B1 A0 5C 71 73 7A 02 60 2C C1 9E 76 C5 89 8F 3F 7D 6C 0F B9 EB F4 41 B2 11 E4 F4 8C E2 E4 E3 9A BE 24 6A 76 83 FA 0E 76 AD 30 DE F6 46 E4 8D 0B 4B AF 1B 31 4D 91 83 15 3D 28 3A 3C CB 2E 44 19 B3 FB 28 7B 3E 55 0F 09 03 7E 27 42 84 74 B6 E9 A6 C8 41 D6 2E 57 26 6E 7E C2 93 9C 7E 3D EC 50 95 70 91 32 B1 20 E7 11 1C C3 61 D0 3F 92 FC E9 24 6E D2 33 F3 45 74 E0 C9 6A A0 40 F9 D5 2A A8 D3 D7 E4 8E 0E 66 E1 41 5A 10 8E D3 AC 58 31 E1 76 24 53 B6 41 47 96 73 CF 43 9A 18 D9 E9 8B 27 F2 A3 A2 7E FF 8E 32 D4 F9 00 E1 24 22 1E 54 75 49 B8 69 CC 6E 7A 31 8C D7 1D 2F 5F 9D 41 CF D6 F1 28 33 70 BD 53 12 03 2B 91 61 CD 65 91 59 D2 55 32 17 4B B9 12 94 8B EA 5A C6 A8 87 36 4B 46 E1 E7 E2 50 47 F7 97 1D A4 57 34 80 1A CC 1E 69 EE FA 85 C3 14 AC 05 F9 B1 86 6C 0A 9F 57 33 8F 91 4A 8E 0C 27 DA 15 FC 69 8D EA 68 A1 B2 86 9E F6 28 19 9A A6 9A 75 FD 64 F6 E9 B4 B9 5B DD 88 ED DB B5 DA BF 83 D5 53 83 25 EB 4A DC E0 07 2F B6 24 A7 3E B7 73 FF 92 9F 5C 5E 11 6F 9F 4D 8B 15 B5 CC B7 40 22 6B E1 99 67 B9 2D 7E EA AE AB 74 60 2A EF 84 
decrypt_to_str: 1
dec_len:372
dec:hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!hello world!

=======================================

private_enc.data - size:256
private_enc.data - data:29 C3 F5 11 92 AD C9 8E 07 2F 3E F6 8C FE 93 F9 3E D2 86 13 F4 51 78 24 CD D2 01 74 53 F9 E0 22 FE 34 1B 5C 14 E4 1C 97 0F F2 13 8F 19 DC FE A7 75 C6 40 FC C7 48 A7 F0 E0 51 79 61 A9 7D 96 0F 4A C3 20 D6 A5 1F 78 1B A0 CD AF AB 9F 34 29 BD 86 39 6E 2C 5F C6 D0 EB 22 01 84 05 46 BB 29 67 62 DC 5F 22 8E 2E 5C C3 76 30 71 D0 90 45 03 07 A9 AA 3F 8C 7F 23 07 8D CF 2A 66 D7 ED F8 CF 5D CC 60 C8 0A 86 92 68 63 F9 48 A3 9A 79 09 53 21 9D C9 51 94 01 C6 14 A0 3B 6D DB CE D9 CE 3F AE 5C DC 73 DF BE 08 1A D3 9E 04 6F E2 9C B7 10 CC F4 39 FC 99 51 91 81 E6 EE C8 5D A5 A5 39 74 79 BB CD 2B 85 E8 C4 A8 C2 E4 37 2C ED 76 B8 BD 4D 01 F6 D7 B8 47 DE 61 5B 8F CB E7 78 18 41 9A CA 3A 75 4D 66 5B 5B 45 39 B8 5F BB A6 4A DB 07 F1 2D 0F 19 B8 30 E2 E1 84 1A F9 8C BC 69 F1 0B 87 
decrypt_to_str: 1
dec_len:30
dec:!!! hello world! other test!!!

=======================================

private2_enc.data - size:256
private2_enc.data - data:1C 7A FB 80 2D AE 74 5E DC 6E 6E C4 1C 9D 7F EB 14 42 82 63 2D AF CC E7 BF BC 33 7D C6 FA BE 97 63 99 86 A1 77 D3 B0 AB 9C 7E 92 03 F2 7B 0F 1C FF 13 86 5B 02 C9 C0 52 53 38 10 0B CD CB 77 7B 22 93 8D AE 56 D8 F0 E1 17 CF 46 8C 75 C5 0E 94 1E FC BE 4B 49 2D 69 3A CE A9 9B D7 C4 AF C8 B2 C4 C5 66 CD FA B2 00 69 06 13 53 C4 90 CD E2 7D F3 48 90 4A 8E 75 1B FA E5 78 D5 97 09 5B CF 65 4C 56 29 C4 C6 62 59 08 DD 65 FB 3B 49 44 F4 DD 45 9D 22 6F 57 E5 A4 BC B6 5F A2 DE F4 D3 CF 50 48 65 A1 6A F2 71 1C 8B D0 AB C3 6B 32 69 CA 99 E7 44 DD C7 1D 29 4D A8 63 4F 37 98 9A 88 DD E5 5D E5 75 2A 7A BF E7 2C 6C 8F 10 57 13 9A 97 3A 9E 21 3A DC 2F C1 B8 4D 04 CD 6B BF 9F E1 F6 07 68 8E FB 48 A8 B9 C6 40 A8 EF 9F 41 05 98 97 F6 C9 01 9C 2A 8A C1 E6 1C 20 E7 D1 DF 71 6D 48 C4 
decrypt_to_str: 0
dec_len:27
dec ptr:10495520
dec ptr data:! ! !   h e l l o   w o r l d !   h a h a h a   ~ ~ ~ 

=======================================

sign len: 256
sign data: 90 6C CA F0 94 EA D9 FA 84 13 64 89 C1 EA A6 03 3C 27 DB 39 0D 6A A6 92 C6 DC 9E 74 77 37 D6 5E 60 5A 5E 0F 7A CA A2 7C A7 3B 42 3C 99 A9 32 6C 89 2F 38 65 CD 28 AE F4 BA EE 4C FA 8D F3 EE B0 FA 1A 76 37 D2 95 B2 C3 73 0F 3E 69 7B 5A C6 B0 42 E5 DC 64 3B 59 22 6E 86 32 81 A2 C0 15 02 4C C2 D6 DE 46 1B 96 43 AE CD F1 65 25 8D 61 69 63 98 49 2C 36 06 96 A4 6D 7C 30 2B 8D C0 E7 0F AE 88 7D 52 83 14 A7 61 E5 98 0E 16 6E 2D C1 93 90 9D FF 7E 54 11 14 52 A2 0E FE 75 CE DF 7C 13 77 BC FE DB DE C6 AF 23 C1 50 9B A1 A2 00 2B 45 4D 9C 0C 57 DC 59 3D B5 21 0A DA C1 18 40 09 33 AE 72 57 7C 27 CC 56 0B 72 57 BB 6D 54 AB 05 3A 09 58 98 45 80 EC C1 61 08 19 0B 22 7F 5A 5B BB F0 75 BA 08 3C E0 B5 29 9C 0B AC A7 62 1F 91 64 EA D0 28 42 8B 86 02 A5 42 B9 3B E0 1B EE 92 DE 2B 
hello world test sign! - verify :True
hello world! - verify :False
[root@localhost zenglServer]# 

结束语:

    你以为挑起生活的担子是勇气,其实去过自己真正想要的生活才更需要勇气。

—— 萨姆门德斯

 

上下篇

下一篇: zenglServer v0.21.0 增加base64编解码相关的内建模块函数

上一篇: zenglServer v0.19.0 增加redis缓存相关的模块

相关文章

zenglServer v0.18.0 直接在命令行中执行脚本

zenglServer v0.22.0 增加支付宝支付测试脚本,增加bltUrlEncode等模块函数

zenglServer v0.21.0 增加base64编解码相关的内建模块函数

zenglServer v0.23.0 使用v1.8.3版本的zengl语言,增加bltTrim等模块函数,支持中文url路径等

zenglServer v0.6.0 session会话

zenglServer v0.25.0 使用v1.9.0版本的zengl语言库,增加backlog及timezone配置,增加bltSetTimeZone模块函数