应项目需求,需要一套xsalsa20实现的加密算法。如果直接用lua实现一套,既浪费精力,又影响性能,总所周知直接使用LuaJIT的FFI方式,可直接调用c语言实现的函数。
经过网上调研,可直接调用libsodium中内置的加密算法,具体c语言实现的开源代码链接如下:https://github.com/jedisct1/libsodium/tree/master/src/libsodium;还有一个lua语言开源的项目:https://github.com/luapower/libsodium。
其中c语言的项目中,有现成的makefile文件,直接make && make install 生成.so动态语言库即可。然后可根据自己的项目需求,找到对应的算法直接调用即可。下面附上部分项目代码:
local ffi = require "ffi"
local lib = ffi.load("/usr/local/project/libsodium.so")
ffi.cdef [[
size_t crypto_secretbox_xsalsa20poly1305_keybytes(void);
size_t crypto_secretbox_xsalsa20poly1305_noncebytes(void);
size_t crypto_secretbox_xsalsa20poly1305_zerobytes(void);
size_t crypto_secretbox_xsalsa20poly1305_boxzerobytes(void);
const char * crypto_secretbox_xsalsa20poly1305_primitive(void);
int crypto_secretbox_xsalsa20poly1305(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
int crypto_secretbox_xsalsa20poly1305_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
size_t crypto_secretbox_keybytes(void);
size_t crypto_secretbox_noncebytes(void);
size_t crypto_secretbox_zerobytes(void);
size_t crypto_secretbox_boxzerobytes(void);
const char *crypto_secretbox_primitive(void);
int crypto_secretbox(unsigned char *c, const unsigned char *m,
unsigned long long mlen, const unsigned char *n,
const unsigned char *k);
int crypto_secretbox_open(unsigned char *m, const unsigned char *c,
unsigned long long clen, const unsigned char *n,
const unsigned char *k);
]]
local _M = { }
_M.keybytes = function() return tonumber(lib.crypto_secretbox_keybytes()) end
_M.noncebytes = function() return tonumber(lib.crypto_secretbox_noncebytes()) end
_M.zerobytes = function() return tonumber(lib.crypto_secretbox_zerobytes()) end
_M.boxzerobytes = function() return tonumber(lib.crypto_secretbox_boxzerobytes()) end
_M.primitive = function() return ffi.string(lib.crypto_secretbox_primitive()) end
_M.secretbox = function(c, m, mlen, n, k)
mlen = mlen or #m
c = c or ffi.new("unsigned char[?]", mlen)
assert(lib.crypto_secretbox(c, m, mlen, n, k) == 0, "crypto_secretbox returned non-zero")
return c, mlen
end
_M.open = function(m, c, clen, n, k)
clen = clen or #c
m = m or ffi.new("unsigned char[?]", clen)
assert(lib.crypto_secretbox_open(m, c, clen, n, k) == 0, "crypto_secretbox_open returned non-zero")
return m, clen
end
return setmetatable ( _M , { __call = function(_M, ...) return _M.secretbox(...) end } )
local key ="password"
local nonce = "your_norce"
//strToByte()方法是字符串转char的方法,返回一个table
local key_table = strToByte(key)
local nonce_table = strToByte(nonce)
local str_key=string.char(unpack(key_table))
local str_nonce=string.char(unpack(nonce_table))
local param_table=strToByte(field_value)
local value_table = new_tab(32+#param_table,0)
for i=1,32 do
value_table[i]=0;
end
for i=1,#param_table do
value_table[32+i]=param_table[i]
end
local str_value=string.char(unpack(value_table))
local unsigned_char = ffi.typeof("unsigned char[?]")
local output = ffi.new(unsigned_char,32+#param_table)
crypto.secretbox(output,str_value, #str_value, str_nonce, str_key)
local result_table=new_tab(#str_value,0)
for i=16,#str_value-1 do
table.insert(result_table,string.format("%02x",output[i]))
end
//最后以十六进制的方式输出加密后的结果
local encryption_data = table.concat(result_table,"")