openresty通过ffi调用一个c编写的base64动态库

2022-07-27 11:38:23

base64编码的原理

  • base64不是加密,就是一种编码,将字符串的二进制按6个bit一组,每组的6个bit的形式转换一下。

  • 每组6个bit对应的字符是 有特定的映射表决定。

映射表:

字符序号
A-Z序号0-25
a-z序号26-51
0-9序号52-61
+序号62
/序号63
  • 都转成以上5种,目的是为了网络传输没有特殊字符。

  • 标准base64 不适合url中直接传输; safe_base64的做法是把最后那俩字符 +和/ 替换成 -_ 即可。解析的时候反向替换之后再base64解码。

  • 因为http传输,+号会被服务器解析成空格, 导致解析base64字符串失败。当然可以对传输的base64字符串进行url编码在传输, nginx会自动url解码。

  • c语言实现编码(3个byte拆分成4个byte):

  • 3个字节一次循环正好拆为4个字符,如果循环剩余1个字符,需要补2个=,如果剩余2个字符,需要补1个=。每个=是6位,凑成8位的倍数,因为网络传输是按8位一组传输的,所以必须是总bit数必须是8的倍数。

#include<stdio.h>#include<stdlib.h>#include<string.h>char*base64_encode(constchar*p,int length,char**output,int*dlen){staticconstchar base[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";int j=0;int flag=0;constchar*str= p;int insize= length;char* dst=*output;int i=0;while(i< insize){unsignedchar c1=(unsignedchar)*str++;
        i++;

        c1= c1&0xff;if(i== insize){snprintf(*output,5,"%c%c==",base[((c1&0xfc)>>2)], 
                                        base[((c1&0x03)<<4)]);*output+=4;break;}unsignedchar c2=(unsignedchar)*str++;
        i++;if(i== insize){snprintf(*output,5,"%c%c%c=",base[((c1&0xfc)>>2)], 
                                        base[(((c1&0x03)<<4)|((c2&0xf0)>>4))], 
                                        base[((c2&0x0f)<<2)]);*output+=4;break;}unsignedchar c3=(unsignedchar)*str++;
        i++;snprintf(*output,5,"%c%c%c%c",base[((c1&0xfc)>>2)], 
                                    base[(((c1&0x03)<<4)|((c2&0xf0)>>4))], 
                                    base[(((c2&0x0f)<<2)|((c3&0xc0)>>6))],
                                    base[(c3&0x3f)]);*output+=4;}**output='\0';*dlen=strlen(dst);return dst;}intfind_index(unsignedchar c){staticconstchar base[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";int i=0;int ret=0;for(i=0; i<64; i++){if(base[i]== c){
            ret= i;break;}}return ret;}char*base64_decode(constchar*src,int len,char**output,int*dlen){char*str=(char*)src;int i=0;char*dst=*output;while(i< len){int arr[4]={0};int k=0;while(k<4){char tmp=*str++;if(tmp!='='){
                arr[k]=find_index(tmp);}
            k++;}
        i+=4;//printf("%d, %d,%d,%d\n",arr[0],arr[1],arr[2],arr[3] );unsignedchar o1=((arr[0]<<2)|(arr[1]&0x30)>>4);unsignedchar o2=(((arr[1]&0x0f)<<4)|((arr[2]&0x3c)>>2));unsignedchar o3=(((arr[2]&0x03)<<6)| arr[3]);snprintf(*output,4,"%c%c%c", o1,o2,o3);//printf("%c,%c,%c\n", o1,o2,o3);*output+=3;}//printf("%s \n", base64);*dlen=strlen(dst);return dst;}intmain(int argc,char* argv[]){if(argc!=3){printf("提示: 输入加密选项-d或-e, 和待加密解密的参数");exit(-1);}if(!strcmp(argv[1],"-e")){int len=strlen(argv[2]);char*output=(char*)malloc(((len+2)/3)*4);char*encode_str= output;int dlen=0;base64_encode(argv[2], len,&output,&dlen);printf("字符串:%s\n", argv[2]);printf("base64编码: %s\n", encode_str);free(encode_str);}elseif(!strcmp(argv[1],"-d")){//const char * encode_str = "aGVsbG93b3JsZA=="; // helloworldchar*encode_str= argv[2];int len=strlen(encode_str);char*output=(char*)malloc(((len+3)/4)*3);char*decode_str= output;int dlen=0;base64_decode(encode_str, len,&output,&dlen);printf("base64解码: %s\n", decode_str);free(decode_str);}else{printf("命令选项错误: -[de]\n");}return0;}
  • lua ffi编译
cd /usr/local/openresty/lualib/base64
gcc -o base64.so -fpic -shared base64.c
  • openresty 接口调用
local ffi= require"ffi"local base64= ffi.load("/usr/local/openresty/lualib/base64/base64.so")

ffi.cdef[[
	int base64_encode(const char *p, int length, char **output, int *dlen);
	int base64_decode(const char *src, int len,  char **output, int *dlen);
]]local c_char= ffi.typeof("char[?]")local c_int= ffi.typeof("int[?]")localfunctionbase64_encode(s)local buf= ffi.new(c_char,((#s+2)/3)*4)local buf1= ffi.new("char *[1]", buf)-- 二级指针,如果不修改指针指向,用一级指针即可。local dlen= ffi.new(c_int,1)-- ffi.new("int[1]")local encode_str= base64.base64_encode(s,#s, buf1, dlen)return ffi.string(buf, dlen[0])endlocalfunctionbase64_decode(s)local buf= ffi.new(c_char,((#s+3)/4)*3)local buf1= ffi.new("char *[1]", buf)-- 二级指针,如果不修改指针指向,用一级指针即可。local dlen= ffi.new(c_int,1)-- ffi.new("int[1]")local encode_str= base64.base64_decode(s,#s, buf1, dlen)return ffi.string(buf, dlen[0])endlocal encode=base64_encode("真的很用容易去调用一个外部 C 库函数,示例代码")
ngx.say(encode)local decode=base64_decode(encode)
ngx.say(decode)--[[
output:
55yf55qE5b6I55So5a655piT5Y676LCD55So5LiA5Liq5aSW6YOoIEMg5bqT5Ye95pWw77yM56S65L6L5Luj56CB
真的很用容易去调用一个外部 C 库函数,示例代码
]]--
  • 作者:学而时习之2
  • 原文链接:https://blog.csdn.net/l_vim11/article/details/125783823
    更新时间:2022-07-27 11:38:23