aboutsummaryrefslogtreecommitdiffstats
path: root/server/resty/hmac.lua
diff options
context:
space:
mode:
Diffstat (limited to 'server/resty/hmac.lua')
-rw-r--r--server/resty/hmac.lua167
1 files changed, 167 insertions, 0 deletions
diff --git a/server/resty/hmac.lua b/server/resty/hmac.lua
new file mode 100644
index 0000000..8d94a8b
--- /dev/null
+++ b/server/resty/hmac.lua
@@ -0,0 +1,167 @@
+
+local str_util = require "resty.string"
+local to_hex = str_util.to_hex
+local ffi = require "ffi"
+local ffi_new = ffi.new
+local ffi_str = ffi.string
+local ffi_gc = ffi.gc
+local ffi_typeof = ffi.typeof
+local C = ffi.C
+local setmetatable = setmetatable
+local error = error
+
+
+local _M = { _VERSION = '0.04' }
+
+local mt = { __index = _M }
+
+
+ffi.cdef[[
+typedef struct engine_st ENGINE;
+typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
+typedef struct evp_md_ctx_st EVP_MD_CTX;
+typedef struct evp_md_st EVP_MD;
+typedef struct hmac_ctx_st HMAC_CTX;
+
+//OpenSSL 1.0
+void HMAC_CTX_init(HMAC_CTX *ctx);
+void HMAC_CTX_cleanup(HMAC_CTX *ctx);
+
+//OpenSSL 1.1
+HMAC_CTX *HMAC_CTX_new(void);
+void HMAC_CTX_free(HMAC_CTX *ctx);
+
+int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md, ENGINE *impl);
+int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len);
+int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len);
+
+const EVP_MD *EVP_md5(void);
+const EVP_MD *EVP_sha1(void);
+const EVP_MD *EVP_sha256(void);
+const EVP_MD *EVP_sha512(void);
+]]
+
+local buf = ffi_new("unsigned char[64]")
+local res_len = ffi_new("unsigned int[1]")
+local hashes = {
+ MD5 = C.EVP_md5(),
+ SHA1 = C.EVP_sha1(),
+ SHA256 = C.EVP_sha256(),
+ SHA512 = C.EVP_sha512()
+}
+
+local ctx_new, ctx_free
+local openssl11, e = pcall(function ()
+ local ctx = C.HMAC_CTX_new()
+ C.HMAC_CTX_free(ctx)
+end)
+if openssl11 then
+ ctx_new = function ()
+ return C.HMAC_CTX_new()
+ end
+ ctx_free = function (ctx)
+ C.HMAC_CTX_free(ctx)
+ end
+else
+ ffi.cdef [[
+ struct evp_md_ctx_st
+ {
+ const EVP_MD *digest;
+ ENGINE *engine;
+ unsigned long flags;
+ void *md_data;
+ EVP_PKEY_CTX *pctx;
+ int (*update)(EVP_MD_CTX *ctx,const void *data,size_t count);
+ };
+
+ struct evp_md_st
+ {
+ int type;
+ int pkey_type;
+ int md_size;
+ unsigned long flags;
+ int (*init)(EVP_MD_CTX *ctx);
+ int (*update)(EVP_MD_CTX *ctx,const void *data,size_t count);
+ int (*final)(EVP_MD_CTX *ctx,unsigned char *md);
+ int (*copy)(EVP_MD_CTX *to,const EVP_MD_CTX *from);
+ int (*cleanup)(EVP_MD_CTX *ctx);
+
+ int (*sign)(int type, const unsigned char *m, unsigned int m_length, unsigned char *sigret, unsigned int *siglen, void *key);
+ int (*verify)(int type, const unsigned char *m, unsigned int m_length, const unsigned char *sigbuf, unsigned int siglen, void *key);
+ int required_pkey_type[5];
+ int block_size;
+ int ctx_size;
+ int (*md_ctrl)(EVP_MD_CTX *ctx, int cmd, int p1, void *p2);
+ };
+
+ struct hmac_ctx_st
+ {
+ const EVP_MD *md;
+ EVP_MD_CTX md_ctx;
+ EVP_MD_CTX i_ctx;
+ EVP_MD_CTX o_ctx;
+ unsigned int key_length;
+ unsigned char key[128];
+ };
+ ]]
+
+ local ctx_ptr_type = ffi_typeof("HMAC_CTX[1]")
+
+ ctx_new = function ()
+ local ctx = ffi_new(ctx_ptr_type)
+ C.HMAC_CTX_init(ctx)
+ return ctx
+ end
+ ctx_free = function (ctx)
+ C.HMAC_CTX_cleanup(ctx)
+ end
+end
+
+
+_M.ALGOS = hashes
+
+
+function _M.new(self, key, hash_algo)
+ local ctx = ctx_new()
+
+ local _hash_algo = hash_algo or hashes.MD5
+
+ if C.HMAC_Init_ex(ctx, key, #key, _hash_algo, nil) == 0 then
+ return nil
+ end
+
+ ffi_gc(ctx, ctx_free)
+
+ return setmetatable({ _ctx = ctx }, mt)
+end
+
+
+function _M.update(self, s)
+ return C.HMAC_Update(self._ctx, s, #s) == 1
+end
+
+
+function _M.final(self, s, hex_output)
+
+ if s ~= nil then
+ if C.HMAC_Update(self._ctx, s, #s) == 0 then
+ return nil
+ end
+ end
+
+ if C.HMAC_Final(self._ctx, buf, res_len) == 1 then
+ if hex_output == true then
+ return to_hex(ffi_str(buf, res_len[0]))
+ end
+ return ffi_str(buf, res_len[0])
+ end
+
+ return nil
+end
+
+
+function _M.reset(self)
+ return C.HMAC_Init_ex(self._ctx, nil, 0, nil, nil) == 1
+end
+
+return _M