PBKDF2最常见的用途是用来加密用户的密码.
在lua中并没有原生的加密库, openresty中也没有提供较好的keyhash功能或者库, 我们只好自己手动去包装一个.
我们可以借助luajit的FFI模块我们可以快速将动态库包装成lua模块使用.
gun/nettle是一个加密库,下面是他的介绍:
Nettle is a cryptographic library that is designed to fit easily in more or less
any context: In crypto toolkits for object-oriented languages (C++, Python, Pike, ...),
in applications like LSH or GNUPG, or even in kernel space.
nettle中提供了很多常用的hash,cipher,key_hash函数. 详细列表见nettle文档: http://www.lysator.liu.se/~nisse/nettle/nettle.html
这里是一个将libnettle包装成模块使用的例子:
首先安装gnu/nettle. 可以直接在 http://ftp.gnu.org/gnu/nettle/ 下载. 然后执行./configure 并 make 就可以了.
然后将编译出来的libnettle.so放在你需要的位置,并且将下文中libnettle.so的位置改成放置位置.
编译过程需要m4, 如果没有的话 make 会报错.
接下来是lua模块:
--[[ pbkdf2.lua @version 160818:1 @author karminski <> @changelogs 160818:1 INIT version. ]]-- local ffi = require "ffi" local ffi_new = ffi.new local ffi_str = ffi.string local C = ffi.C local _M = { _VERSION = '0.0.1' } ffi.cdef[[ void nettle_pbkdf2_hmac_sha1(size_t key_length, const uint8_t *key, unsigned iterations, size_t salt_length, const uint8_t *salt, size_t length, uint8_t *dst); void nettle_pbkdf2_hmac_sha256(size_t key_length, const uint8_t *key, unsigned iterations, size_t salt_length, const uint8_t *salt, size_t length, uint8_t *dst); ]] local nettle = ffi.load("/lib/libnettle.so") -- change this path when needed. local uint8t = ffi.typeof("uint8_t[?]") -- hmac_sha1() -- @param string key -- @param number iterations -- @param string salt -- @param number len -- @return string sha1 function _M.hmac_sha1(key, iterations, salt, len) local buf = ffi_new(uint8t, len) nettle.nettle_pbkdf2_hmac_sha1(#key, key, iterations, #salt, salt, len, buf) return ffi_str(buf, len) end -- hmac_sha256() -- @param string key -- @param number iterations -- @param string salt -- @param number len -- @return string sha256 function _M.hmac_sha256(key, iterations, salt, len) local buf = ffi_new(uint8t, len) nettle.nettle_pbkdf2_hmac_sha256(#key, key, iterations, #salt, salt, len, buf) return ffi_str(buf, len) end return _M
需要注意的是, 在编写依赖ffi的lua模块时,一定要将 require "ffi" 以及 ffi.load 放在代码最底层, 否则会出现table overflow的情况.
另外可以直接使用这个项目, 该项目直接将nettle的所有函数全部包装了: https://github.com/bungle/lua-resty-nettle/
以上.