当前版本,在内建模块中增加了和base64编解码相关的模块函数,从而可以实现和base64编解码相关的功能。

    页面导航:

项目下载地址:

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

zenglServer v0.21.0:

    当前版本,在内建模块中增加了和base64编解码相关的模块函数,从而可以实现和base64编解码相关的功能。

bltBase64Encode模块函数:

    bltBase64Encode模块函数,用于对数据进行base64解码,相关的C源码位于module_builtin.c文件中:

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

#include "base64.h"

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

/**
 * bltBase64Encode模块函数,对数据进行base64编码
 * 第一个参数data必须是字符串,或者是整数类型的数据指针
 * 第二个参数data_len是可选参数,当提供了该参数时,必须是整数类型,表示需要编码的data数据的尺寸大小,默认值是-1,表示自动检测data的尺寸大小
 * 返回值是将data数据经过了base64编码后的字符串
 * 例如:
	use builtin;
	def TRUE 1;

	encode_str = bltBase64Encode("hello world");
	print encode_str;

	上面脚本使用bltBase64Encode来对hello world字符串进行base64编码

	use builtin;
	def TRUE 1;

	encode_str = bltBase64Encode("hello world", 4);
	print encode_str;

	上面代码片段,在提供了第二个参数4后,就只会对hello world的前4个字符进行base64编码

	use builtin,openssl;

	def RSA_PUBLIC 1;
	def RSA_PRIVATE 0;

	def DUMP_HEX 2;

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

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

	print 'source string:' + (src_str = "hello world! I'm a programmer!") + br;
	enc_len = opensslPrivateEncrypt(src_str, -1, p_key, &enc);
	print 'encrypt: ' + bltDumpPtrData(enc, enc_len, DUMP_HEX) + br;
	print 'encrypt base64 encode: ' + (encode = bltBase64Encode(enc)) + br;

	以上代码片段,通过将数据指针enc传递给bltBase64Encode,从而对openssl加密后的二进制数据进行base64编码
 */
ZL_EXP_VOID module_builtin_base64_encode(ZL_EXP_VOID * VM_ARG, ZL_EXP_INT argcount)
{
	ZENGL_EXPORT_MOD_FUN_ARG arg = {ZL_EXP_FAT_NONE,{0}};
	const char * func_name = "bltBase64Encode";
	if(argcount < 1)
		zenglApi_Exit(VM_ARG,"usage: %s(data[, data_len = -1]): string", 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;
	}
	int data_len = -1;
	if(argcount > 1) {
		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);
		}
		data_len = (int)arg.val.integer;
	}
	if(data_len < 0) {
		if(is_data_str) {
			data_len = (int)strlen((char *)data);
		}
		else {
			data_len = data_ptr_size;
		}
	}
	if(data_ptr_size > 0 && data_len > data_ptr_size) {
		data_len = data_ptr_size;
	}
	if(data_len > 0) {
		unsigned int encode_len = b64e_size(data_len) + 1;
		unsigned char * encode_str = malloc((sizeof(char) * encode_len));
		encode_len = b64_encode(data, (unsigned int)data_len, encode_str);
		zenglApi_SetRetVal(VM_ARG, ZL_EXP_FAT_STR, (char *)encode_str, 0, 0);
		free(encode_str);
	}
	else {
		zenglApi_SetRetVal(VM_ARG, ZL_EXP_FAT_STR, "", 0, 0);
	}
}

bltBase64Decode模块函数:

    bltBase64Decode模块函数,用于对数据进行base64解码,相关的C源码也位于module_builtin.c文件中:

/**
 * bltBase64Decode模块函数,对数据进行base64解码
 * 第一个参数data表示需要解码的base64编码,必须是字符串类型
 * 第二个参数result必须是引用类型,用于存储base64解码后的结果
 * 第三个参数decode_to_str是可选的,必须是整数类型,表示是否将第二个result参数转为字符串类型,默认为0表示不转为字符串,因此,默认情况下,result存储的会是整数类型的数据指针
 * 	如果decode_to_str的值为1则result存储的会是字符串类型的结果
 * 返回值表示result结果的字节长度
 * 例如:
	use builtin;
	def TRUE 1;

	encode_str = bltBase64Encode("hello world");
	print encode_str;

	decode_len = bltBase64Decode(encode_str, &decode, TRUE);
	print 'decode_len: ' + decode_len;
	print 'decode: ' + decode;

	上面代码片段先将hello world字符串进行base64编码,接着通过bltBase64Decode模块函数将编码的字符串进行解码,同时将解码的结果转为字符串类型(通过将第三个参数设置为1)

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

	def DUMP_HEX 2;

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

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

	print 'source string:' + (src_str = "hello world! I'm a programmer!") + br;
	enc_len = opensslPrivateEncrypt(src_str, -1, p_key, &enc);
	print 'encrypt: ' + bltDumpPtrData(enc, enc_len, DUMP_HEX) + br;
	print 'encrypt base64 encode: ' + (encode = bltBase64Encode(enc)) + br;

	decode_len = bltBase64Decode(encode, &decode);
	print 'decode_len: ' + decode_len + br;
	print 'decode: ' + bltDumpPtrData(decode, decode_len, DUMP_HEX) + br;

	dec_len = opensslPublicDecrypt(decode, decode_len, key, &dec, RSA_PKCS1_PADDING, TRUE);
	print 'decrypt string: ' + dec + br;

	以上代码片段先将openssl加密后的二进制数据进行base64编码,接着通过bltBase64Decode将编码数据进行解码,从而获取到原始的加密二进制数据,最后通过openssl模块函数
	将二进制数据解密为原始的字符串值
 */
ZL_EXP_VOID module_builtin_base64_decode(ZL_EXP_VOID * VM_ARG, ZL_EXP_INT argcount)
{
	ZENGL_EXPORT_MOD_FUN_ARG arg = {ZL_EXP_FAT_NONE,{0}};
	const char * func_name = "bltBase64Decode";
	if(argcount < 2)
		zenglApi_Exit(VM_ARG,"usage: %s(data, &result[, decode_to_str = 0]): integer", func_name);
	zenglApi_GetFunArg(VM_ARG,1,&arg);
	if(arg.type != ZL_EXP_FAT_STR) {
		zenglApi_Exit(VM_ARG,"the first argument [data] of %s must be string", func_name);
	}
	unsigned char * data = (unsigned char *)arg.val.str;
	int data_len = (int)strlen((char *)data);
	if(data_len > 0) {
		st_detect_arg_is_address_type(VM_ARG, 2, &arg, "second argument [&result]", func_name);
		int result_size = b64d_size(data_len);
		unsigned char * result = (unsigned char *)zenglApi_AllocMem(VM_ARG, (sizeof(char) * result_size) +1);
		memset(result, 0, ((sizeof(char) * result_size) +1));
		int result_len = b64_decode(data, (unsigned int)data_len, result);
		int decode_to_str = 0;
		if(argcount > 2) {
			zenglApi_GetFunArg(VM_ARG,3,&arg);
			if(arg.type != ZL_EXP_FAT_INT) {
				zenglApi_Exit(VM_ARG,"the third argument [decode_to_str] of %s must be integer", func_name);
			}
			decode_to_str = (int)arg.val.integer;
		}
		if(decode_to_str) {
			st_set_arg_value(VM_ARG, 2, ZL_EXP_FAT_STR, (char *)result, 0);
			zenglApi_FreeMem(VM_ARG, result);
		}
		else {
			st_set_arg_value(VM_ARG, 2, ZL_EXP_FAT_INT, NULL, (ZL_EXP_LONG)result);
			MAIN_DATA * my_data = zenglApi_GetExtraData(VM_ARG, "my_data");
			int ret_set_ptr = pointer_list_set_member(&(my_data->pointer_list), result, result_len, module_builtin_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, result_len, 0);
	}
	else {
		st_set_arg_value(VM_ARG, 2, ZL_EXP_FAT_INT, NULL, 0);
		zenglApi_SetRetVal(VM_ARG, ZL_EXP_FAT_INT, ZL_EXP_NULL, 0, 0);
	}
}

base64.h和base64.c:

    当前版本增加了base64.h的头文件,以及base64.c的源码文件,之前介绍的bltBase64Encode和bltBase64Decode模块函数,都是通过base64.c文件中定义的b64_encode和b64_decode函数来完成具体的编解码操作的。

    base64.h头文件的代码如下:

/*
 * base64.h
 *
 *  Created on: May 21, 2020
 *      Author: zengl
 *
 *  以下代码来自github开源项目:https://github.com/joedf/base64.c
 */

/*
	base64.c - by Joe DF ([email protected])
	Released under the MIT License

	Revision: 2015-06-12 01:26:51

	Thank you for inspiration:
	http://www.codeproject.com/Tips/813146/Fast-base-functions-for-encode-decode
*/

#ifndef BASE64_H_
#define BASE64_H_

//Base64 char table function - used internally for decoding
unsigned int b64_int(unsigned int ch);

// in_size : the number bytes to be encoded.
// Returns the recommended memory size to be allocated for the output buffer excluding the null byte
unsigned int b64e_size(unsigned int in_size);

// in_size : the number bytes to be decoded.
// Returns the recommended memory size to be allocated for the output buffer
unsigned int b64d_size(unsigned int in_size);

// in : buffer of "raw" binary to be encoded.
// in_len : number of bytes to be encoded.
// out : pointer to buffer with enough memory, user is responsible for memory allocation, receives null-terminated string
// returns size of output including null byte
unsigned int b64_encode(const unsigned char* in, unsigned int in_len, unsigned char* out);

// in : buffer of base64 string to be decoded.
// in_len : number of bytes to be decoded.
// out : pointer to buffer with enough memory, user is responsible for memory allocation, receives "raw" binary
// returns size of output excluding null byte
unsigned int b64_decode(const unsigned char* in, unsigned int in_len, unsigned char* out);

#endif /* BASE64_H_ */

    base64.c文件的代码如下:

/*
 * base64.c
 *
 *  Created on: May 21, 2020
 *      Author: zengl
 *
 *  以下代码来自github开源项目:https://github.com/joedf/base64.c
 */

/*
	base64.c - by Joe DF ([email protected])
	Released under the MIT License

	See "base64.h", for more information.

	Thank you for inspiration:
	http://www.codeproject.com/Tips/813146/Fast-base-functions-for-encode-decode
*/

#include "base64.h"

//Base64 char table - used internally for encoding
unsigned char b64_chr[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

//Base64 char table function - used internally for decoding
unsigned int b64_int(unsigned int ch) {

	// ASCII to base64_int
	// 65-90  Upper Case  >>  0-25
	// 97-122 Lower Case  >>  26-51
	// 48-57  Numbers     >>  52-61
	// 43     Plus (+)    >>  62
	// 47     Slash (/)   >>  63
	// 61     Equal (=)   >>  64~
	if (ch==43)
	return 62;
	if (ch==47)
	return 63;
	if (ch==61)
	return 64;
	if ((ch>47) && (ch<58))
	return ch + 4;
	if ((ch>64) && (ch<91))
	return ch - 'A';
	if ((ch>96) && (ch<123))
	return (ch - 'a') + 26;
	return 0;
}

// in_size : the number bytes to be encoded.
// Returns the recommended memory size to be allocated for the output buffer excluding the null byte
unsigned int b64e_size(unsigned int in_size) {

	// size equals 4*floor((1/3)*(in_size+2));
	int i, j = 0;
	for (i=0;i<in_size;i++) {
		if (i % 3 == 0)
		j += 1;
	}
	return (4*j);
}

// in_size : the number bytes to be decoded.
// Returns the recommended memory size to be allocated for the output buffer
unsigned int b64d_size(unsigned int in_size) {

	return ((3*in_size)/4);
}

// in : buffer of "raw" binary to be encoded.
// in_len : number of bytes to be encoded.
// out : pointer to buffer with enough memory, user is responsible for memory allocation, receives null-terminated string
// returns size of output including null byte
unsigned int b64_encode(const unsigned char* in, unsigned int in_len, unsigned char* out) {

	unsigned int i=0, j=0, k=0, s[3];

	for (i=0;i<in_len;i++) {
		s[j++]=*(in+i);
		if (j==3) {
			out[k+0] = b64_chr[ (s[0]&255)>>2 ];
			out[k+1] = b64_chr[ ((s[0]&0x03)<<4)+((s[1]&0xF0)>>4) ];
			out[k+2] = b64_chr[ ((s[1]&0x0F)<<2)+((s[2]&0xC0)>>6) ];
			out[k+3] = b64_chr[ s[2]&0x3F ];
			j=0; k+=4;
		}
	}

	if (j) {
		if (j==1)
			s[1] = 0;
		out[k+0] = b64_chr[ (s[0]&255)>>2 ];
		out[k+1] = b64_chr[ ((s[0]&0x03)<<4)+((s[1]&0xF0)>>4) ];
		if (j==2)
			out[k+2] = b64_chr[ ((s[1]&0x0F)<<2) ];
		else
			out[k+2] = '=';
		out[k+3] = '=';
		k+=4;
	}

	out[k] = '\0';

	return k;
}

// in : buffer of base64 string to be decoded.
// in_len : number of bytes to be decoded.
// out : pointer to buffer with enough memory, user is responsible for memory allocation, receives "raw" binary
// returns size of output excluding null byte
unsigned int b64_decode(const unsigned char* in, unsigned int in_len, unsigned char* out) {

	unsigned int i=0, j=0, k=0, s[4];

	for (i=0;i<in_len;i++) {
		s[j++]=b64_int(*(in+i));
		if (j==4) {
			out[k+0] = ((s[0]&255)<<2)+((s[1]&0x30)>>4);
			if (s[2]!=64) {
				out[k+1] = ((s[1]&0x0F)<<4)+((s[2]&0x3C)>>2);
				if ((s[3]!=64)) {
					out[k+2] = ((s[2]&0x03)<<6)+(s[3]); k+=3;
				} else {
					k+=2;
				}
			} else {
				k+=1;
			}
			j=0;
		}
	}

	return k;
}

test_base64.zl测试脚本:

    当前版本在my_webroot目录中增加了v0_21_0的子目录,并在该目录中增加了test_base64.zl的测试脚本,用于测试对普通的字符串进行base64编解码的操作,test_base64.zl的代码如下:

use builtin;
def TRUE 1;

encode_str = bltBase64Encode("hello world");
print encode_str;

decode_len = bltBase64Decode(encode_str, &decode, TRUE);
print 'decode_len: ' + decode_len;
print 'decode: ' + decode;

    以上脚本的执行结果如下:

[root@localhost zenglServer]# ./zenglServer -r "/v0_21_0/test_base64.zl"
aGVsbG8gd29ybGQ=
decode_len: 11
decode: hello world
[root@localhost zenglServer]# 

test_base64_openssl.zl测试脚本:

    当前版本在my_webroot/v0_21_0目录中,还增加了test_base64_openssl.zl的测试脚本,用于测试对加密后的二进制数据进行base64编解码,该测试脚本的代码如下:

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;

if(bltIsRunInCmd())
	bltSetImmediatePrint(TRUE);
	print 'now in cmd';
	is_cmd = TRUE;
	br = '\n';
else
	is_cmd = FALSE;
	br = '<br/><br/>';
	print 'now in website' + br;
endif

fun exit(msg)
	global is_cmd,br;
	print msg + br;
	bltExit();
endfun

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

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

print 'source string:' + (src_str = "hello world! I'm a programmer!") + br;
enc_len = opensslPrivateEncrypt(src_str, -1, p_key, &enc);
print 'encrypt: ' + bltDumpPtrData(enc, enc_len, DUMP_HEX) + br;
print 'encrypt base64 encode: ' + (encode = bltBase64Encode(enc)) + br;

decode_len = bltBase64Decode(encode, &decode);
print 'decode_len: ' + decode_len + br;
print 'decode: ' + bltDumpPtrData(decode, decode_len, DUMP_HEX) + br;

dec_len = opensslPublicDecrypt(decode, decode_len, key, &dec, RSA_PKCS1_PADDING, TRUE);
print 'decrypt string: ' + dec + br;

    以上测试脚本的执行结果如下:

[root@localhost zenglServer]# ./zenglServer -r "/v0_21_0/test_base64_openssl.zl"
now in cmd
source string:hello world! I'm a programmer!

encrypt: 11 47 B0 0B BC E8 71 3D B2 95 6D 0E A7 C4 17 CB BB CD 86 20 E4 B2 D3 3B D2 DE C8 57 BA AE C8 1D B2 2D 42 BB 5C 33 08 6C EE DA 4D F4 4F 0D 94 0D 4A 12 46 B5 B1 AD 08 C4 A6 C6 5F DF 37 10 BE 5B 31 E7 CA 0D BE C7 31 6C 9C 4A 09 12 69 45 46 A4 FE C0 8E DA FC CC F4 FC 4B A6 95 E1 01 99 2A 73 22 55 44 ED B0 FA 7F D1 E0 EC F3 7E 54 43 E5 08 F7 51 73 65 E8 2B 5C FC C2 04 D3 C4 94 FB 78 35 8E 31 4B A9 4E A2 77 A6 78 34 12 71 DC 2E 59 69 D9 04 31 18 58 DE 2F 80 92 6C DA DD 18 4E 2B 78 93 74 D3 21 A4 73 E1 53 DC 82 69 8F 12 1C 1E 73 3E 09 28 59 0D 68 03 A0 2F 64 C3 66 F1 2B FA AF 8A C1 B6 57 00 FD 46 E2 0F AC 85 1C 8C 32 52 F7 73 CB B1 60 B9 6C 66 97 E7 F7 4B 8E ED 2F A4 23 2E C5 53 40 56 5A D1 C2 07 C4 74 84 CA 53 0D 33 C7 5D 15 A7 26 EB 43 2A D3 34 85 B6 6C 57 02 B2 

encrypt base64 encode: EUewC7zocT2ylW0Op8QXy7vNhiDkstM70t7IV7quyB2yLUK7XDMIbO7aTfRPDZQNShJGtbGtCMSmxl/fNxC+WzHnyg2+xzFsnEoJEmlFRqT+wI7a/Mz0/EumleEBmSpzIlVE7bD6f9Hg7PN+VEPlCPdRc2XoK1z8wgTTxJT7eDWOMUupTqJ3png0EnHcLllp2QQxGFjeL4CSbNrdGE4reJN00yGkc+FT3IJpjxIcHnM+CShZDWgDoC9kw2bxK/qvisG2VwD9RuIPrIUcjDJS93PLsWC5bGaX5/dLju0vpCMuxVNAVlrRwgfEdITKUw0zx10VpybrQyrTNIW2bFcCsg==

decode_len: 256

decode: 11 47 B0 0B BC E8 71 3D B2 95 6D 0E A7 C4 17 CB BB CD 86 20 E4 B2 D3 3B D2 DE C8 57 BA AE C8 1D B2 2D 42 BB 5C 33 08 6C EE DA 4D F4 4F 0D 94 0D 4A 12 46 B5 B1 AD 08 C4 A6 C6 5F DF 37 10 BE 5B 31 E7 CA 0D BE C7 31 6C 9C 4A 09 12 69 45 46 A4 FE C0 8E DA FC CC F4 FC 4B A6 95 E1 01 99 2A 73 22 55 44 ED B0 FA 7F D1 E0 EC F3 7E 54 43 E5 08 F7 51 73 65 E8 2B 5C FC C2 04 D3 C4 94 FB 78 35 8E 31 4B A9 4E A2 77 A6 78 34 12 71 DC 2E 59 69 D9 04 31 18 58 DE 2F 80 92 6C DA DD 18 4E 2B 78 93 74 D3 21 A4 73 E1 53 DC 82 69 8F 12 1C 1E 73 3E 09 28 59 0D 68 03 A0 2F 64 C3 66 F1 2B FA AF 8A C1 B6 57 00 FD 46 E2 0F AC 85 1C 8C 32 52 F7 73 CB B1 60 B9 6C 66 97 E7 F7 4B 8E ED 2F A4 23 2E C5 53 40 56 5A D1 C2 07 C4 74 84 CA 53 0D 33 C7 5D 15 A7 26 EB 43 2A D3 34 85 B6 6C 57 02 B2 

decrypt string: hello world! I'm a programmer!

[root@localhost zenglServer]# 

结束语:

    恋爱是容易的,成家是困难的

    相爱是容易的,相处是困难的

    决定是容易的,可是等待是困难的

—— 《爱情麻辣烫》

 

上下篇

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

上一篇: zenglServer v0.20.0 增加openssl加密解密相关的模块

相关文章

zenglServer v0.10.0 使用zengl脚本的编译缓存,跳过编译过程

zenglServer v0.17.0 设置精简日志模式,设置允许上传文件大小,日志分割等

zenglServer v0.6.0 session会话

zenglServer v0.14.0 正则表达式模块

zenglServer v0.4.0 daemon守护进程, epoll事件驱动

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