最近项目上需要对一段二进制串进行 base64编码、解码, base64编码、解码的算法并不复杂,自行实现也不会引入太大代价,不过既然openssl 有比较成熟的实现,直接调用库代码自然是比较明智的选择。
ØEVP_EncodeInit函数
原型:void EVP_EncodeInit(EVP_ENCODE_CTX *ctx);
功能:该函数初始化一个用来进行base64编码的结构,事实上,该函数只是简单设置了结构里面几个常量的长度。
参数:
ctx:base64设备上下文。
ØEVP_EncodeUpdate函数
原型:void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl,unsigned char *in,int inl);
功能:该函数将参数in里面的inl自己数据拷贝到结构体ctx里面,如果结构体里面有数据,就同时将结构体里面的数据进行BASE64编码并输出到参数out指向的缓存里面,输出数据的长度保存在outl里面。注意,在第一次调用本函数的时候,虽然往结构体里面拷贝数据了,但是结构体ctx里面开始是没有输入数据存在并且输入数据长度不超出ctx内部存储数据的最长限制,就不会有任何数据被进行BASE64编码,也就是说,不会有任何数据输出;但是如果输入数据长度比内部存储的数据长,那么就会输出部分经过BASE64编码的数据。数据输出总是在下一层输入前完成的。
参数:
ctx:base64设备上下文。
out:存放编码后的数据缓冲区。
outl:编码后的数据长度。
in:编码前的数据。
inl:编码前的数据长度。
ØEVP_EncodeFinal函数
原型:void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl);
功能:该函数将结构体ctx里面剩余数据进行BASE64编码并写入到参数out里面去,输出数据的长度保存在outl里面。
参数:
ctx:base64设备上下文。
out:存放编码后的数据。
outl:编码后的数据长度。
ØEVP_EncodeBlock函数
原型:int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int n);
功能:该函数将参数f里面的字符串里面的n个字节的字符串进行BASE64编码并输出到参数t里面。返回数据的字节长度。事实上,在函数EVP_EncodeUpdate和EVP_EncodeFinal里面就调用了该函数完成BASE64编码功能。
参数:
t:接收编码后的数据缓冲区。
f:编码前的数据。
n:编码前的数据长度。
原型:void EVP_DecodeInit(EVP_ENCODE_CTX *ctx);
功能:该函数初始化一个用来进行BASE64解码的数据结构。
参数:
ctx:base64设备上下文。
ØEVP_DecodeUpdate函数
原型:int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl,unsigned char *in, int inl);
功能:该函数将参数in里面inl字节的数据拷贝到结构体ctx里面。如果结构体里面已经有数据,那么这些数据就会先进行BASE64解码,然后输出到参数out指向的内存中,输出的字节数保存在参数outl里面。输入数据为满行的数据时,返回为1;如果输入数据是最后一行数据的时候,返回0;返回-1则表明出错了。
参数:
ctx:base64设备上下文。
out:存放解码后的数据缓冲区。
outl:解码后的数据长度。
in:解码前的数据。
inl:解码前的数据长度。
ØEVP_DecodeFinal函数
原型:int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl);
功能:该函数将结构体ctx里面剩余的数据进行BASE64解码并输出到参数out指向的内存中,输出数据长度为outl字节。成功返回1,否则返回-1。
参数:
ctx:base64设备上下文。
out:解码后的数据。
outl:解码后的数据长度。
ØEVP_DecodeBlock函数
原型:int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n);
功能:该函数将字符串f中的n字节数据进行BASE64解码,并输出到t指向的内存中,输出数据长度为outl。成功返回解码的数据长度,返回返回-1。
参数:
t:接收解码后的数据缓冲区。
f:解码前的数据。
//!< encode test
int src_str_size = 60;
unsigned char *src_str = (unsigned char *)malloc(src_str_size);
memset(src_str, '1', src_str_size);
unsigned char *encode_str = (unsigned char *)malloc( (src_str_size - 1) / 3 * 4 + 4);
int encode_str_size = EVP_EncodeBlock(encode_str, src_str, src_str_size);
printf("encode_str_size=%d encode_str:'%s'/n", encode_str_size, encode_str);
//!< decode test
EVP_ENCODE_CTX ctx;
EVP_DecodeInit(&ctx);
unsigned char *decode_str = (unsigned char *)malloc(src_str_size);
int decode_str_size = 0;
int len = 20; //!< 每次decode 的字节数
int decode_len = 0;
int offset = 0;
while(1)
{
if(offset + len > encode_str_size)
{
len = encode_str_size - offset;
}
int ret = EVP_DecodeUpdate(&ctx, decode_str + decode_str_size, &decode_len,
encode_str + offset, len);
if(ret == 0) break;
if(ret == -1)
{
printf("error.../n");
break;
}
offset += len;
decode_str_size += decode_len;
}
EVP_DecodeFinal(&ctx, decode_str, &decode_len);
decode_str_size += decode_len;
printf("decode_str:'%s' decode_str_len=%d/n",
decode_str, decode_str_size);