des加密 lua_对基于Lua和Nginx的iOS应用数据的加密框架 | 学步园

预答辩归来,主管给了我一个新任务,这是实习以来的第三个任务了。任务仍然很简单,就是对ios应用中的一些重要数据进行DES加密。

iOS的界面通过Webview形式展示,在web页中通过JS调用lua脚本对重要数据进行读取和存放,所以加密模块的函数必须能够在lua脚本中调用。咋一看,将函数增加到“lua调用库”里是一个直接的方法。

第一种尝试:增加lua的C API

通过对lua(programming with lua中文版,新浪资料)的基本学习了解到,lua作为一种简单、高效执行、跨平台的嵌入式脚本语言,其主要由包括string、io等基本函数实现的标准库构成,全部代码均有C语言实现。lua语言的另外一个特点是其可扩展性,通过函数栈的形式可以和所有的主流语言进行交互,可以在lua脚本中调用其他语言构建的扩展库,也可以在其他语言中通过lua执行环境调用lua中的基本函数库。在这里,为了完成加密任务,我选择了基于Lua的C扩展库来完成。开始还有一种想法就是直接在lua中通过lua的自定义数据结构像基本库一样去实现加密模块,但是考虑到lua升级的维护性和时间安排,最终放弃了这种选择。目标确定之后,接下来就是开始编写基于Lua的DES扩展库,所有的辅助函数均可以用C语言实现,只需要稍微改变一下lua调用函数的形式即可。因为lua调用函数最终会在lua脚本中调用,所以其函数所有参数的获得都是从lua环境中获得,lua提供了一个lua环境,其所有的参数都在称作lua_State

*L的参数里,可以通过luaL_checkNumber(L, index), luaL_ChechString(L,index),分别读取函数参数,然后通过注册所有的lua调用函数,注册扩展库。这样关于DES的扩展库的代码工作就完成了。具体代码如下所示:

static int DES_Encrypt(lua_State *L);

static int DES_Decrypt(lua_State *L);

//加密文件

static int DES_Encrypt(lua_State *L){

const char * plainStr = luaL_checkstring(L, 1);

int len_plainStr = luaL_checknumber(L, 2);

const char * keyStr = DESKEY;

int len_cipherStr = (len_plainStr + 8 - len_plainStr % 8);

char *cipherStr = (char *)malloc(sizeof(char) * len_cipherStr);

ElemType plainBlock[8],cipherBlock[8],keyBlock[8];

ElemType bKey[64];

ElemType subKeys[16][48];

//设置密钥

memcpy(keyBlock,keyStr,8);

//将密钥转换为二进制流

Char8ToBit64(keyBlock,bKey);

//生成子密钥

DES_MakeSubKeys(bKey,subKeys);

int len_remain = len_plainStr;

while(len_remain > 0)

{

if(len_remain >= 8)

memcpy(plainBlock, plainStr+(len_plainStr-len_remain), 8);

else{

//读取剩下的字节,并补齐

memcpy(plainBlock, plainStr+(len_plainStr-len_remain), len_remain);

memset(plainBlock+len_remain, '\0', 8-len_remain);

plainBlock[7] = 8 - len_remain;

}

//加密每个block

DES_EncryptBlock(plainBlock,subKeys,cipherBlock);

//将生成的密文存入到一个数据结构中去

memcpy(cipherStr+(len_plainStr-len_remain), cipherBlock, 8);

len_remain = len_remain - 8;

}

lua_pushlstring(L, cipherStr, len_cipherStr);

free(cipherStr);

return 1;

}

//解密文件

//int DES_Decrypt(char *cipherFile, char *keyStr,char *plainFile){

static int DES_Decrypt(lua_State *L){

const char * cipherStr = luaL_checkstring(L, 1);

int len_cipherStr = luaL_checknumber(L, 2);

const char * keyStr = DESKEY;

//如果解密字符串不是8的倍数,说明该字符串未经过加密

int len_plainStr = len_cipherStr;

char *plainStr = (char *) malloc (sizeof(char) * len_plainStr);

ElemType plainBlock[8],cipherBlock[8],keyBlock[8];

ElemType bKey[64];

ElemType subKeys[16][48];

//设置密钥

memcpy(keyBlock,keyStr,8);

//将密钥转换为二进制流

Char8ToBit64(keyBlock,bKey);

//生成子密钥

DES_MakeSubKeys(bKey,subKeys);

int len_remain = len_cipherStr;

while(len_remain > 0){

//密文的字节数一定是8的整数倍

memcpy(cipherBlock, cipherStr+(len_cipherStr-len_remain), 8);

DES_DecryptBlock(cipherBlock,subKeys,plainBlock);

memcpy(plainStr+(len_cipherStr-len_remain), plainBlock, 8);

len_remain = len_remain - 8;

}

//判断末尾是否被填充

if(plainBlock[7] < 8){

len_plainStr = len_plainStr - plainBlock[7];

}

lua_pushlstring(L, plainStr, len_plainStr);

free(plainStr);

return 1;

}

//将定义的函数名集成到一个结构数组中去,建立 lua 中使用的方法名与 C 的函数名的对应关系

static const struct luaL_reg luades [] = {

{"lsin", l_sin},

{"lDesEncode", DES_Encrypt},

{"lDesDecode", DES_Decrypt},

{NULL, NULL} /* 必须以NULL结尾 */

};

//库打开时的执行函数(相当于这个库的 main 函数),执行完这个函数后, lua 中就可以加载这个 so 库了

int luaopen_luades (lua_State *L)

{

luaL_openlib(L, "myLuaDes", luades, 0);

return 1;

}

接下来就是编译,首先编译了一个mac版本的动态库。就是通过将基于lua的des函数编译成动态库(.so形式),然后在lua的解释器中加载lua_des扩展库,通过自定义的扩展库别名,调用自定义的函数别名进行调用。加密解密后的内容正确,说明函数功能完成。

gcc lDes.c -fPIC -W -Waggregate-return -Wcast-align -Wmissing-prototypes -Wnested-externs -Wshadow -Wwrite-strings -pedantic -I /Users/whaty/Desktop/LIBLUA/LIBLUA -L/Users/whaty/Desktop/LIBLUA/LIBLUA -shared -o libLuaDes.so -llua

package.loadlib("/Users/whaty/Desktop/LuaDes/LuaDes/libLuaDes.so", "luaopen_luades")()

print(mylib1.lsin(10))

但是现在的目标是需要在ipad应用中加载这个库,这个.so形式的扩展库肯定不能用,需要编译一个ipad版本的动态库。在ios中,动态库是基于.dylib后缀名形式,如何将一个c文件编译成ipad动态库的形式,这是一个思路,但是当前ios应用已有的一个架构是将lua标准库编译到Nginx中的库里,通过熟悉Nginx中的模块化思路我采取下面一种思路。

另一种尝试:增加Nginx中Lua模块的库函数功能

Nginx作为一种高性能的开源web服务器,采用了模块化框架,所有模块都是通过静态编译,当启动nginx时,会自动加载所有模块。其中Nginx_Lua模块提供了配置指令和Nginx API,配置指令是在nginx中使用,Nginx API是用来在Lua脚本中访问Nginx中的变量和函数。现在我们的目标是如何在Nginx中lua模块中加入一个新的Nginx API函数。

下面我们先来关注一下Nginx中Lua模块的运行机制。Nginx中的每个Worker进程使用一个lua虚拟机,工作进程中的所有协程共享虚拟机。将Nginx中的lua API封装好之后注入到lua的VM中就可以在lua代码中进行访问了。我没有直接新开辟一个nginx api模块,而是在原来nginx.req API中加入一个DES模块。加密函数仍然不变,只是改变了以下注册函数,注册函数如下:

void

ngx_http_lua_inject_req_args_api(lua_State *L)

{

lua_pushcfunction(L, ngx_http_lua_ngx_req_set_uri_args);

lua_setfield(L, -2, "set_uri_args");

lua_pushcfunction(L, ngx_http_lua_ngx_req_get_uri_args);

lua_setfield(L, -2, "get_uri_args");

lua_pushcfunction(L, ngx_http_lua_ngx_req_get_uri_args);

lua_setfield(L, -2, "get_query_args"); /* deprecated */

lua_pushcfunction(L, ngx_http_lua_ngx_req_get_post_args);

lua_setfield(L, -2, "get_post_args");

lua_pushcfunction(L, DES_Encrypt);

lua_setfield(L, -2, "lDesEncode");

lua_pushcfunction(L, DES_Decrypt);

lua_setfield(L, -2, "lDesDecode");

//ngx.req.get_uri_args

}

注册完毕之后,就可以在lua脚本中通过ngx.req.lDesEncode() 和 ngx.req.lDesDecode()两个函数进行加密和解密了。

上面只是本人对lua和nginx的初步了解,欢迎指教。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值