Skip to content

Commit 47c2f0a

Browse files
committed
+ initial commit into this new module ( extracted from api-gateway-core )
1 parent 1d0bbe4 commit 47c2f0a

File tree

6 files changed

+435
-0
lines changed

6 files changed

+435
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
target
2+
target/*

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "test/resources/test-nginx"]
2+
path = test/resources/test-nginx
3+
url = https://github.com/agentzh/test-nginx.git

Makefile

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# NOTE: Every line in a recipe must begin with a tab character.
2+
BUILD_DIR ?= target
3+
4+
PREFIX ?= /usr/local
5+
LUA_INCLUDE_DIR ?= $(PREFIX)/include
6+
LUA_LIB_DIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION)
7+
INSTALL ?= install
8+
9+
.PHONY: all clean test install
10+
11+
all: ;
12+
13+
install: all
14+
$(INSTALL) -d $(DESTDIR)/$(LUA_LIB_DIR)/api-gateway/resty/
15+
$(INSTALL) src/lua/api-gateway/resty/*.lua $(DESTDIR)/$(LUA_LIB_DIR)/api-gateway/resty/
16+
17+
test:
18+
echo "running tests ..."
19+
# cp -r test/resources/api-gateway $(BUILD_DIR)
20+
mkdir -p $(BUILD_DIR)/
21+
PATH=/usr/local/sbin:$$PATH TEST_NGINX_SERVROOT=`pwd`/$(BUILD_DIR)/servroot TEST_NGINX_PORT=1989 prove -I ./test/resources/test-nginx/lib -r ./test/perl
22+
23+
package:
24+
git archive --format=tar --prefix=api-gateway-hmac-1.0/ -o api-gateway-hmac-1.0.tar.gz -v HEAD
25+
26+
clean: all
27+
rm -rf $(BUILD_DIR)/servroot

README.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,116 @@ api-gateway-hmac
22
================
33

44
Adds HMAC support to Lua with multiple algorithms, via OpenSSL and FFI
5+
6+
Table of Contents
7+
=================
8+
9+
* [Status](#status)
10+
* [Description](#description)
11+
* [Synopsis](#synopsis)
12+
* [Developer Guide](#developer-guide)
13+
14+
15+
Status
16+
======
17+
18+
This library is considered production ready.
19+
20+
Description
21+
===========
22+
23+
This library requires an nginx build with OpenSSL,
24+
the [ngx_lua module](http://wiki.nginx.org/HttpLuaModule), and [LuaJIT 2.0](http://luajit.org/luajit.html).
25+
26+
27+
Synopsis
28+
========
29+
30+
```lua
31+
# nginx.conf:
32+
33+
lua_package_path "/path/to/lua-resty-string/lib/?.lua;;";
34+
35+
server {
36+
location = /test {
37+
content_by_lua_file conf/test.lua;
38+
}
39+
}
40+
41+
-- conf/test.lua:
42+
43+
-- HMAC-SHA-1
44+
local resty_hmac_sha1 = require "api-gateway.resty.hmac"
45+
local hmac_sha1 = resty_hmac_sha1:new()
46+
47+
local digest = hmac_sha1:digest("sha1","secret-key","Hello world")
48+
ngx.say("hmac_sha1: ", digest)
49+
50+
-- HMAC-SHA-224
51+
local resty_hmac_sha224 = require "api-gateway.resty.hmac"
52+
local hmac_sha224 = resty_hmac_sha224:new()
53+
54+
local digest = hmac_sha224:digest("sha224","secret-key","Hello world")
55+
ngx.say("hmac_sha224: ", digest)
56+
57+
-- HMAC-SHA-226
58+
local resty_hmac_sha256 = require "api-gateway.resty.hmac"
59+
local hmac_sha256 = resty_hmac_sha256:new()
60+
61+
local digest = hmac_sha256:digest("sha256","secret-key","Hello world")
62+
ngx.say("hmac_sha256: ", digest)
63+
64+
-- HMAC-SHA-384
65+
local resty_hmac_sha384 = require "api-gateway.resty.hmac"
66+
local hmac_sha384 = resty_hmac_sha384:new()
67+
68+
local digest = hmac_sha384:digest("sha384","secret-key","Hello world")
69+
ngx.say("hmac_sha384: ", digest)
70+
71+
-- HMAC-SHA-512
72+
local resty_hmac_sha512 = require "api-gateway.resty.hmac"
73+
local hmac_sha512 = resty_hmac_sha512:new()
74+
75+
local digest = hmac_sha512:digest("sha512","secret-key","Hello world")
76+
ngx.say("hmac_sha512: ", digest)
77+
78+
79+
80+
```
81+
[Back to TOC](#table-of-contents)
82+
83+
Developer guide
84+
===============
85+
86+
## Install the api-gateway first
87+
Since this module is running inside the `api-gateway`, make sure the api-gateway binary is installed under `/usr/local/sbin`.
88+
You should have 2 binaries in there: `api-gateway` and `nginx`, the latter being only a symbolik link.
89+
90+
## Update git submodules
91+
```
92+
git submodule update --init --recursive
93+
```
94+
95+
## Running the tests
96+
The tests are based on the `test-nginx` library.
97+
This library is added a git submodule under `test/resources/test-nginx/` folder, from `https://github.com/agentzh/test-nginx`.
98+
99+
Test files are located in `test/perl`.
100+
The other libraries such as `Redis`, `test-nginx` are located in `test/resources/`.
101+
Other files used when running the test are also located in `test/resources`.
102+
103+
## Build locally
104+
```
105+
sudo LUA_LIB_DIR=/usr/local/api-gateway/lualib make install
106+
```
107+
108+
To execute the test issue the following command:
109+
```
110+
make test
111+
```
112+
113+
If you want to run a single test, the following command helps:
114+
```
115+
PATH=/usr/local/sbin:$PATH TEST_NGINX_SERVROOT=`pwd`/target/servroot TEST_NGINX_PORT=1989 prove -I ./test/resources/test-nginx/lib -r ./test/perl/hmac.t
116+
```
117+
This command only executes the test `awsv4signature.t`.

src/lua/api-gateway/resty/hmac.lua

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

0 commit comments

Comments
 (0)