-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhmac.lua
94 lines (76 loc) · 2.76 KB
/
hmac.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
-- Adds HMAC support to Lua with multiple algorithms, via OpenSSL and FFI
--
-- Author: [email protected]
-- Date: 16/05/14
--
local ffi = require "ffi"
local ffi_new = ffi.new
local ffi_str = ffi.string
local C = ffi.C
local resty_string = require "resty.string"
local setmetatable = setmetatable
local error = error
local _M = { _VERSION = '0.09' }
local mt = { __index = _M }
--
-- EVP_MD is defined in openssl/evp.h
-- HMAC is defined in openssl/hmac.h
--
ffi.cdef[[
typedef struct env_md_st EVP_MD;
typedef struct env_md_ctx_st EVP_MD_CTX;
unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
const unsigned char *d, size_t n, unsigned char *md,
unsigned int *md_len);
const EVP_MD *EVP_sha1(void);
const EVP_MD *EVP_sha224(void);
const EVP_MD *EVP_sha256(void);
const EVP_MD *EVP_sha384(void);
const EVP_MD *EVP_sha512(void);
]]
-- table definind the available algorithms and the length of each digest
-- for more information @see: http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
local available_algorithms = {
sha1 = { alg = C.EVP_sha1(), length = 160/8 },
sha224 = { alg = C.EVP_sha224(), length = 224/8 },
sha256 = { alg = C.EVP_sha256(), length = 256/8 },
sha384 = { alg = C.EVP_sha384(), length = 384/8 },
sha512 = { alg = C.EVP_sha512(), length = 512/8 }
}
-- 64 is the max lenght and it covers up to sha512 algorithm
local digest_len = ffi_new("int[?]", 64)
local buf = ffi_new("char[?]", 64)
function _M.new(self)
return setmetatable({}, mt)
end
local function getDigestAlgorithm(dtype)
local md_name = available_algorithms[dtype]
if ( md_name == nil ) then
error("attempt to use unknown algorithm: '" .. dtype ..
"'.\n Available algorithms are: sha1,sha224,sha256,sha384,sha512")
end
return md_name.alg, md_name.length
end
---
-- Returns the HMAC digest. The hashing algorithm is defined by the dtype parameter.
-- The optional raw flag, defaulted to false, is a boolean indicating whether the output should be a direct binary
-- equivalent of the HMAC or formatted as a hexadecimal string (the default)
--
-- @param self
-- @param dtype The hashing algorithm to use is specified by dtype
-- @param key The secret
-- @param msg The message to be signed
-- @param raw When true, it returns the binary format, else, the hex format is returned
--
function _M.digest(self, dtype, key, msg, raw)
local evp_md, digest_length_int = getDigestAlgorithm(dtype)
if key == nil or msg == nil then
error("attempt to digest with a null key or message")
end
C.HMAC(evp_md, key, #key, msg, #msg, buf, digest_len)
if raw == true then
return ffi_str(buf,digest_length_int)
end
return resty_string.to_hex(ffi_str(buf,digest_length_int))
end
return _M