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.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)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_generichashAPI. - The libsodium
crypto_secretstreamAPI.
Details on what functions were implemented can be found under the Version 1.2.0 Milestone.
Version 1.3
- The libsodium
crypto_shorthashAPI. - The libsodium
crypto_pwhashAPI.
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_aeadAPI.
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.
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 luasodiumOPM
An FFI-only version is available on OPM
opm install jprjr/luasodiumArch 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 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.
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.