Bindings to Libsodium, with support for the Lua C API as well as LuaJIT's FFI API.
There's basically three methods for loading the API, they're tried in this order:
- FFI API from a C module, with function pointers.
- Traditional C API
- FFI API, using
ffi.loadto loadlibsodiumat runtime.
If you'd like to load a specific version, you can append:
.ffi(to use FFI via pointers in a C module).core(to use the traditional C API)..pureffi(to use FFI and find/loadlibsodiumat runtime).
The .core and .ffi variants don't exist in the OpenResty
Package Manager version, since OPM doesn't support C
modules.
Example:
local luasodium = require'luasodium' -- tries to load FFI, fallback to C API
local luasodium_ffi = require'luasodium.ffi' -- uses the FFI API (in a C module)
local luasodium_c = require'luasodium.core' -- uses the C API
local luasodium_pureffi = require'luasodium.pureffi' -- uses the FFI API (without any C modules)As of version 1.0.0, this module covers:
- All original, high-level functions from NaCl (crypto_box, crypto_secretbox, and so on).
- All of libsodium's additions to NaCl's high-level functions (crypto_box_easy, crypto_secretbox_easy).
- All of libsodium's utility functions and random data generating functions.
It does not yet cover the entire libsodium API.
Details on what functions were implemented can be found under the Version 1.0.0 Milestone.
- All original lower-level functions from NaCl (crypto_box_curve25519xsalsa20poly1305, crypto_secretbox_xsalsa20poly1305). This means version 1.1 has 100% NaCl coverage.
- The libsodium
crypto_generichashAPI. - The libsodium
crypto_secretstreamAPI.
Details on what functions were implemented can be found under the Version 1.2.0 Milestone.
- The libsodium
crypto_shorthashAPI. - The libsodium
crypto_pwhashAPI.
Details on what functions were implemented can be found under the Version 1.3.0 Milestone.
No functional changes, but an API change. libsodium errors no
longer throw errors, they return nil and an error message.
- The libsodium
crypto_aeadAPI.
Details on what functions were implemented can be found under the Version 2.1.0 Milestone.
This version no longer uses malloc/free and instead uses sodium_malloc
and sodium_free, for data allocations that require alignment. This
simplifies the FFI version somewhat - it no longer needs to load
the C library's malloc/free, and no longer needs wrappers to call
sodium_memzero when structures are garbage collected, since
sodium_free will take care of that.
This version also adds the scrypt pwhash functions.
This version removes the use of sodium_malloc and sodium_free
introduced in version 2.2. Per the libsodium docs:
These are not general-purpose allocation functions. In particular, they are slower than malloc() and friends and require 3 or 4 extra pages of virtual memory.
I experienced segfaults, etc from running out of memory.
Rather than revert to the FFI version requiring malloc and free,
it instead uses LuaJIT's own memory management, with wrappers
to call sodium_memzero when garbage-collected.
This version also adds the crypto_kx functions.
libsodium includes functions for secure programming, like allocating
memory that avoids swapping, securely zeroing out memory, clearing
the stack, and so on.
I'm not sure how possible it is to implement these kinds of functions
in Lua. In Lua, I allocate memory using lua_newuserdata or LuaJIT's
ffi.new(), so that Lua can keep track of it and garbage collect it.
Before releasing temporary memory back to the garbage collector, I do
call sodium_memzero to wipe it - but this only applies to scratch
memory.
If you're concerned with making absolutely sure memory is cleared
out, you should likely code your secure portions in C and use
libsodium's secure memory functions, or forego the standard
Lua interpreter and write something with a custom allocator
that uses sodium_malloc and sodium_free.
Available on luarocks:
luarocks install luasodiumAn FFI-only version is available on OPM
opm install jprjr/luasodiumAvailable on the AUR: lua-luasodium.
Builds packages for lua, lua-5.1, lua-5.2, and lua-5.3.
Currently migrating to a CMake build system. Building and installing the library with cmake works, I have not yet moved running tests, generating release tarballs, etc into cmake.
If you'd like to build from source, grab one of the release tarballs, and then build with cmake:
wget https://github.com/jprjr/luasodium/releases/download/v1.3.0/luasodium-1.3.0.tar.gz
tar xf luasodium-1.3.0.tar.gz
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr ../luasodium-1.3.0
make
make installCMake should find libsodium and Lua automatically. Or you can specify some flags:
-DLUA_VERSION=5.1(or whichever version of Lua you want to build against.-DLIBSODIUM_INCLUDEDIR=/path/to/includedir -DLIBSODIUM_LIBRARIES=/path/to/libsodium.so-DLUA_INCLUDEDIR=/path/to/includedir
If you set LUA_INCLUDEDIR, you'll need to also set LUA_VERSION. If you're building with
any version of LuaJIT, set it to 5.1.
MIT License (see file LICENSE).
This is meant to follow the Libsodium API closely, with a few idioms.
All functions and constants use their original, full name from libsodium.
If a function is missing a parameter or has a wrong parameter type, a Lua error is thrown.
If a call into libsodium returns an error value (example, a message
fails to decrypt), then nil is returned.
If a libsodium function writes data into a buffer,
this library will automatically allocate and return
a string.
The original NaCl library requires the user to have padding before messages and ciphertexts.
If a libsodium function requires padding, this library
will take care of it for you, you'll never need to add padding.
If a libsodium function changes a buffer, this
library will instead make a copy, make changes
in that, and return the copy.
If a libsodium function accepts a buffer and a buffer
length, the Lua version will just accept a Lua string, you
can use string.sub if you need to call a function with
a substring.
In libsodium, converting a string to hex is:
sodium_bin2hex(char * const hex, const size_t hex_maxlen,
const unsgined char *const bin, const size_t bin_len);Since this library will automatically allocate hex, and
uses your string's length, the Lua version is simply:
local string = luasodium.sodium_bin2hex(some_other_string)In libsodium, you can perform addition, subtraction, etc
on large integers, these operations are performed on the
buffer directly, such as:
char buf[4] = { 0, 0, 0, 0};
sodium_increment(buf,4);
/* buf is now { 1, 0 , 0, 0 } */In Lua, we instead create a new buffer, copy it, increment, and return that.
local buf = string.rep('\0',4)
local incremented = luasodium.sodium_increment(buf)
-- buf is still '\0\0\0\0', incremented is '\1\0\0\0'Luasodium is broken into submodules, though these are mostly used
for testing and verification - the recommended approach is to
just require luasodium. This will return a module with
all functions and constants from the submodules in a single
table.
Documentation on modules is available in the wiki.