├── .gitignore ├── LICENSE ├── Makefile ├── README.md └── lib └── resty └── random.lua /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Aapo Talvensaari 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | OPENRESTY_PREFIX=/usr/local/openresty 2 | 3 | PREFIX ?= /usr/local 4 | LUA_INCLUDE_DIR ?= $(PREFIX)/include 5 | LUA_LIB_DIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION) 6 | INSTALL ?= install 7 | 8 | .PHONY: all install 9 | 10 | all: ; 11 | 12 | install: all 13 | $(INSTALL) -d $(DESTDIR)/$(LUA_LIB_DIR)/resty 14 | $(INSTALL) lib/resty/*.lua $(DESTDIR)/$(LUA_LIB_DIR)/resty 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | lua-resty-random 2 | ================ 3 | 4 | **lua-resty-random** is a random library for OpenResty. 5 | 6 | This library works only in OpenResty (or Nginx with Lua module) that has OpenSSL support. 7 | 8 | ## Hello World with lua-resty-random 9 | 10 | ```lua 11 | local random = require "resty.random" 12 | -- Get two random bytes 13 | local bytes = random.bytes(2) 14 | -- Get two random bytes hexadecimal encoded 15 | local hxbts = random.bytes(2, 'hex') 16 | -- Get random number 17 | local numbr = random.number(1, 10) 18 | -- Get random token (by default uses A-Z, a-z, and 0-9 chars) 19 | local token = random.token(10) 20 | ``` 21 | 22 | ## About The Internals 23 | 24 | For random bytes `lua-resty-random` uses OpenSSL `RAND_bytes` that is included in OpenResty (or Nginx) when compiled with OpenSSL. For random numbers the library uses Lua's `math.random`, and `math.randomseed`. You should note that on LuaJIT environment, LuaJIT uses a Tausworthe PRNG with period 2^223 to implement `math.random` and `math.randomseed`. Hexadecimal dumps are implemented using `ngx_hex_dump`. 25 | 26 | ## Lua API 27 | #### string random.bytes(len, format) 28 | 29 | Returns `len` number of random bytes using OpenSSL `RAND_bytes`. You may optionally pass `"hex"` as format argument if you want random bytes hexadecimal encoded. 30 | 31 | ##### Example 32 | 33 | ```lua 34 | local random = require "resty.random" 35 | print(random.bytes(10)) 36 | print(random.bytes(10, "hex") 37 | ``` 38 | 39 | #### number random.number(min, max, reseed) 40 | 41 | Returns random number between `min` and `max` (including `min` and `max`). You may optionally pass `true` as reseed argument if you want to reseend random number generator (normally not needed, and random number generator is seeded once when you do `require "resty.random"`. 42 | 43 | ##### Example 44 | 45 | ```lua 46 | local random = require "resty.random" 47 | print(random.number(1, 10)) 48 | print(random.number(1, 10, true)) 49 | ``` 50 | 51 | #### string random.token(len, chars, sep) 52 | 53 | Returns random token consisting of chars (by default it uses A-Z, a-z, and 0-9 as chars). You may also pass a string as a separator with `sep` argument. 54 | 55 | ##### Example 56 | 57 | ```lua 58 | local random = require "resty.random" 59 | print(random.token(10)) 60 | print(random.token(10, "ABCD")) 61 | print(random.token(10, { "A", "B", "C", "D" })) 62 | print(random.token(10, { "Ford", "Audi", "Mustang", "A6" }, " ")) 63 | ``` 64 | 65 | ## License 66 | 67 | `lua-resty-random` uses two clause BSD license. 68 | 69 | ``` 70 | Copyright (c) 2013, Aapo Talvensaari 71 | All rights reserved. 72 | 73 | Redistribution and use in source and binary forms, with or without modification, 74 | are permitted provided that the following conditions are met: 75 | 76 | * Redistributions of source code must retain the above copyright notice, this 77 | list of conditions and the following disclaimer. 78 | 79 | * Redistributions in binary form must reproduce the above copyright notice, this 80 | list of conditions and the following disclaimer in the documentation and/or 81 | other materials provided with the distribution. 82 | 83 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 84 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 85 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 86 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 87 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 88 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 89 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 90 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 91 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 92 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 93 | ``` 94 | -------------------------------------------------------------------------------- /lib/resty/random.lua: -------------------------------------------------------------------------------- 1 | local require = require 2 | local ffi = require "ffi" 3 | local ffi_cdef = ffi.cdef 4 | local ffi_new = ffi.new 5 | local ffi_str = ffi.string 6 | local ffi_typeof = ffi.typeof 7 | local C = ffi.C 8 | local type = type 9 | local random = math.random 10 | local randomseed = math.randomseed 11 | local concat = table.concat 12 | local tostring = tostring 13 | local pcall = pcall 14 | 15 | ffi_cdef[[ 16 | typedef unsigned char u_char; 17 | u_char * ngx_hex_dump(u_char *dst, const u_char *src, size_t len); 18 | int RAND_bytes(u_char *buf, int num); 19 | ]] 20 | 21 | local ok, new_tab = pcall(require, "table.new") 22 | if not ok then 23 | new_tab = function () return {} end 24 | end 25 | 26 | local alnum = { 27 | 'A','B','C','D','E','F','G','H','I','J','K','L','M', 28 | 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', 29 | 'a','b','c','d','e','f','g','h','i','j','k','l','m', 30 | 'n','o','p','q','r','s','t','u','v','w','x','y','z', 31 | '0','1','2','3','4','5','6','7','8','9' 32 | } 33 | 34 | local t = ffi_typeof "uint8_t[?]" 35 | 36 | local function bytes(len, format) 37 | local s = ffi_new(t, len) 38 | C.RAND_bytes(s, len) 39 | if not s then return nil end 40 | if format == "hex" then 41 | local b = ffi_new(t, len * 2) 42 | C.ngx_hex_dump(b, s, len) 43 | return ffi_str(b, len * 2), true 44 | else 45 | return ffi_str(s, len), true 46 | end 47 | end 48 | 49 | local function seed() 50 | local a,b,c,d = bytes(4):byte(1, 4) 51 | return randomseed(a * 0x1000000 + b * 0x10000 + c * 0x100 + d) 52 | end 53 | 54 | local function number(min, max, reseed) 55 | if reseed then seed() end 56 | if min and max then return random(min, max) 57 | elseif min then return random(min) 58 | else return random() end 59 | end 60 | 61 | local function token(len, chars, sep) 62 | chars = chars or alnum 63 | local count 64 | local token = new_tab(len, 0) 65 | if type(chars) ~= "table" then 66 | chars = tostring(chars) 67 | count = #chars 68 | local n 69 | for i=1,len do 70 | n = number(1, count) 71 | token[i] = chars:sub(n, n) 72 | end 73 | else 74 | count = #chars 75 | for i=1,len do token[i] = chars[number(1, count)] end 76 | end 77 | return concat(token, sep) 78 | end 79 | 80 | seed() 81 | 82 | return { 83 | bytes = bytes, 84 | number = number, 85 | token = token 86 | } 87 | --------------------------------------------------------------------------------