From e59161ec204c7a95e4751b1c0e9a6bead7fcab39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophile=20Diot?= Date: Fri, 30 Jun 2023 15:38:49 -0400 Subject: [PATCH] Squashed 'src/deps/src/lua-resty-random/' content from commit 17b604f7f git-subtree-dir: src/deps/src/lua-resty-random git-subtree-split: 17b604f7f7dd217557ca548fc1a9a0d373386480 --- .gitignore | 3 ++ LICENSE | 23 +++++++++++ Makefile | 14 +++++++ README.md | 93 ++++++++++++++++++++++++++++++++++++++++++++ lib/resty/random.lua | 86 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 219 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 lib/resty/random.lua diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..08302ef77 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +.idea + diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..0fc93522c --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2013, Aapo Talvensaari +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..123937c2a --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +OPENRESTY_PREFIX=/usr/local/openresty + +PREFIX ?= /usr/local +LUA_INCLUDE_DIR ?= $(PREFIX)/include +LUA_LIB_DIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION) +INSTALL ?= install + +.PHONY: all install + +all: ; + +install: all + $(INSTALL) -d $(DESTDIR)/$(LUA_LIB_DIR)/resty + $(INSTALL) lib/resty/*.lua $(DESTDIR)/$(LUA_LIB_DIR)/resty diff --git a/README.md b/README.md new file mode 100644 index 000000000..b7811bd75 --- /dev/null +++ b/README.md @@ -0,0 +1,93 @@ +lua-resty-random +================ + +**lua-resty-random** is a random library for OpenResty. + +This library works only in OpenResty (or Nginx with Lua module) that has OpenSSL support. + +## Hello World with lua-resty-random + +```lua +local random = require "resty.random" +-- Get two random bytes +local bytes = random.bytes(2) +-- Get two random bytes hexadecimal encoded +local hxbts = random.bytes(2, 'hex') +-- Get random number +local numbr = random.number(1, 10) +-- Get random token (by default uses A-Z, a-z, and 0-9 chars) +local token = random.token(10) +``` + +## About The Internals + +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`. + +## Lua API +#### string random.bytes(len, format) + +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. + +##### Example + +```lua +local random = require "resty.random" +print(random.bytes(10)) +print(random.bytes(10, "hex") +``` + +#### number random.number(min, max, reseed) + +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"`. + +##### Example + +```lua +local random = require "resty.random" +print(random.number(1, 10)) +print(random.number(1, 10, true)) +``` + +#### string random.token(len, chars, sep) + +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. + +##### Example + +```lua +local random = require "resty.random" +print(random.token(10)) +print(random.token(10, "ABCD")) +print(random.token(10, { "A", "B", "C", "D" })) +print(random.token(10, { "Ford", "Audi", "Mustang", "A6" }, " ")) +``` + +## License + +`lua-resty-random` uses two clause BSD license. + +``` +Copyright (c) 2013, Aapo Talvensaari +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +``` diff --git a/lib/resty/random.lua b/lib/resty/random.lua new file mode 100644 index 000000000..f36ec6fff --- /dev/null +++ b/lib/resty/random.lua @@ -0,0 +1,86 @@ +local require = require +local ffi = require "ffi" +local ffi_cdef = ffi.cdef +local ffi_new = ffi.new +local ffi_str = ffi.string +local ffi_typeof = ffi.typeof +local C = ffi.C +local type = type +local random = math.random +local randomseed = math.randomseed +local concat = table.concat +local tostring = tostring +local pcall = pcall + +ffi_cdef[[ +typedef unsigned char u_char; +u_char * ngx_hex_dump(u_char *dst, const u_char *src, size_t len); +int RAND_bytes(u_char *buf, int num); +]] + +local ok, new_tab = pcall(require, "table.new") +if not ok then + new_tab = function () return {} end +end + +local alnum = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M', + 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', + 'a','b','c','d','e','f','g','h','i','j','k','l','m', + 'n','o','p','q','r','s','t','u','v','w','x','y','z', + '0','1','2','3','4','5','6','7','8','9' +} + +local t = ffi_typeof "uint8_t[?]" + +local function bytes(len, format) + local s = ffi_new(t, len) + C.RAND_bytes(s, len) + if not s then return nil end + if format == "hex" then + local b = ffi_new(t, len * 2) + C.ngx_hex_dump(b, s, len) + return ffi_str(b, len * 2), true + else + return ffi_str(s, len), true + end +end + +local function seed() + local a,b,c,d = bytes(4):byte(1, 4) + return randomseed(a * 0x1000000 + b * 0x10000 + c * 0x100 + d) +end + +local function number(min, max, reseed) + if reseed then seed() end + if min and max then return random(min, max) + elseif min then return random(min) + else return random() end +end + +local function token(len, chars, sep) + chars = chars or alnum + local count + local token = new_tab(len, 0) + if type(chars) ~= "table" then + chars = tostring(chars) + count = #chars + local n + for i=1,len do + n = number(1, count) + token[i] = chars:sub(n, n) + end + else + count = #chars + for i=1,len do token[i] = chars[number(1, count)] end + end + return concat(token, sep) +end + +seed() + +return { + bytes = bytes, + number = number, + token = token +}