Skip to content

Instantly share code, notes, and snippets.

@siddontang
Created May 18, 2013 09:24
Show Gist options
  • Save siddontang/5603849 to your computer and use it in GitHub Desktop.
Save siddontang/5603849 to your computer and use it in GitHub Desktop.
openresty string hmac implementation
local ffi = require "ffi"
local sha512 = require "resty.sha512"
local aes = require "resty.aes"
local ffi_new = ffi.new
local ffi_str = ffi.string
local C = ffi.C
local setmetatable = setmetatable
local error = error
module(...)
_VERSION = '0.01'
local mt = { __index = _M }
ffi.cdef[[
typedef struct HMACstate_st
{
SHA512_CTX shactx;
unsigned char k_opad[128];
} HMAC_CTX;
void HMAC_CTX_init(HMAC_CTX *ctx);
int HMAC_Init_ex(HMAC_CTX *ctx, const void* key, int key_len, const EVP_MD *md, ENGINE *imple);
int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, int len);
int HMAC_Final(HMAC_CTX *ct, unsigned char *md, unsigned int *len);
void HMAC_CTX_cleanup(HMAC_CTX *ctx);
]]
--[[
Support openssl version >= 1.0.0
HMAC_Init_ex(), HMAC_Update() and HMAC_Final() did not return values in versions of OpenSSL before 1.0.0. You may change ffi hmac definition if your version is below 1.0.0.
--]]
local ctx_ptr_type = ffi.typeof("HMAC_CTX[1]")
hash = {
md5 = C.EVP_md5(),
sha1 = C.EVP_sha1(),
sha224 = C.EVP_sha224(),
sha256 = C.EVP_sha256(),
sha384 = C.EVP_sha384(),
sha512 = C.EVP_sha512()
}
local buf = ffi_new("unsigned char[64]")
function new(self, key, _hash)
local ctx = ffi_new(ctx_ptr_type)
C.HMAC_CTX_init(ctx)
local md = _hash or hash.md5
if C.HMAC_Init_ex(ctx, key, #key, md, nil) == 0 then
return nil
end
return setmetatable({ _ctx = ctx }, mt)
end
function update(self, s)
return C.HMAC_Update(self._ctx, s, #s) == 1
end
function final(self)
local out_len = ffi_new("unsigned int[1]")
if C.HMAC_Final(self._ctx, buf, out_len) == 1 then
return ffi_str(buf, out_len[0])
end
return nil
end
function reset(self)
C.HMAC_Init_ex(self._ctx, nil, 0, nil, nil)
end
function cleanup(self)
C.HMAC_CTX_cleanup(self._ctx)
end
local class_mt = {
-- to prevent use of casual module global variables
__newindex = function (table, key, val)
error('attempt to write to undeclared variable "' .. key .. '"')
end
}
setmetatable(_M, class_mt)
@chaoaero
Copy link

chaoaero commented Oct 9, 2015

Very Useful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment