Awesome
luasodium
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.load
to loadlibsodium
at 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/loadlibsodium
at 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)
Status
Version 1.0
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.
Version 1.1
- All original lower-level functions from NaCl (crypto_box_curve25519xsalsa20poly1305, crypto_secretbox_xsalsa20poly1305). This means version 1.1 has 100% NaCl coverage.
Version 1.2
- The libsodium
crypto_generichash
API. - The libsodium
crypto_secretstream
API.
Details on what functions were implemented can be found under the Version 1.2.0 Milestone.
Version 1.3
- The libsodium
crypto_shorthash
API. - The libsodium
crypto_pwhash
API.
Details on what functions were implemented can be found under the Version 1.3.0 Milestone.
Version 2.0
No functional changes, but an API change. libsodium
errors no
longer throw errors, they return nil
and an error message.
Version 2.1
- The libsodium
crypto_aead
API.
Details on what functions were implemented can be found under the Version 2.1.0 Milestone.
Version 2.2
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.
Version 2.3
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.
Caveats
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
.
Installation
luarocks
Available on luarocks:
luarocks install luasodium
OPM
An FFI-only version is available on OPM
opm install jprjr/luasodium
Arch Linux
Available on the AUR: lua-luasodium.
Builds packages for lua, lua-5.1, lua-5.2, and lua-5.3.
Source
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 install
CMake 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
.
Licensing
MIT License (see file LICENSE
).
Idioms
This is meant to follow the Libsodium API closely, with a few idioms.
Idiom: Use original symbol names.
All functions and constants use their original, full name from libsodium
.
Idiom: Throw errors on programming errors
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.
Idiom: Auto-allocate strings/buffers.
If a libsodium
function writes data into a buffer,
this library will automatically allocate and return
a string.
Idiom: Handle zero-padding
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.
Idiom: strings are immutable.
If a libsodium
function changes a buffer, this
library will instead make a copy, make changes
in that, and return the copy.
Idiom: Use input string length.
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.
Idiom examples:
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'
Modules
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.