Skip to content

Instantly share code, notes, and snippets.

@johnd0e
Created December 9, 2024 16:52
Show Gist options
  • Save johnd0e/135e03b4d3f1044bb94a4c563d84507a to your computer and use it in GitHub Desktop.
Save johnd0e/135e03b4d3f1044bb94a4c563d84507a to your computer and use it in GitHub Desktop.
LuaJIT module: HMAC functions from OpenSSL (w/o LuaResty)
local ffi = require "ffi"
local ffi_new = ffi.new
local ffi_str = ffi.string
local ffi_gc = ffi.gc
local setmetatable = setmetatable
local _M = { _VERSION = '0.06' } --Source: https://github.com/jkeys089/lua-resty-hmac
local mt = { __index = _M }
local crypto = ffi.load("libcrypto-3.dll")
ffi.cdef [[
typedef struct engine_st ENGINE;
typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
typedef struct hmac_ctx_st HMAC_CTX;
//OpenSSL 1.1
HMAC_CTX *HMAC_CTX_new(void);
void HMAC_CTX_free(HMAC_CTX *ctx);
typedef struct evp_md_ctx_st EVP_MD_CTX;
typedef struct evp_md_st EVP_MD;
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_sha384(void);
const EVP_MD *EVP_sha512(void);
]]
local hashes = {
MD5 = crypto.EVP_md5(),
SHA1 = crypto.EVP_sha1(),
SHA256 = crypto.EVP_sha256(),
SHA384 = crypto.EVP_sha384(),
SHA512 = crypto.EVP_sha512()
}
_M.ALGOS = hashes
function _M.new(self, key, hash_algo)
local ctx = crypto.HMAC_CTX_new()
local _hash_algo = hash_algo or hashes.MD5
if crypto.HMAC_Init_ex(ctx, key, #key, _hash_algo, nil) == 0 then
return nil
end
ffi_gc(ctx, crypto.HMAC_CTX_free)
return setmetatable({ _ctx = ctx }, mt)
end
function _M.update(self, s)
return crypto.HMAC_Update(self._ctx, s, #s) == 1
end
local function to_hex (s)
local hex = {}
for i=1,#s do
hex[i] = string.format("%02x", string.byte(string.sub(s,i,i)))
end
return table.concat(hex)
end
local buf = ffi_new("unsigned char[64]")
local res_len = ffi_new("unsigned int[1]")
function _M.final(self, s, hex_output)
if s ~= nil then
if crypto.HMAC_Update(self._ctx, s, #s) == 0 then
return nil
end
end
if crypto.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 crypto.HMAC_Init_ex(self._ctx, nil, 0, nil, nil) == 1
end
return _M
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment