luasodium

libsodium 的 FFI 绑定。

$ opm get jprjr/luasodium

luasodium

[!codecov](https://codecov.io/gh/jprjr/luasodium)

绑定到 Libsodium,支持 Lua C API 和 LuaJIT 的 FFI API。

基本上有三种加载 API 的方法,按以下顺序尝试

  1. 来自 C 模块的 FFI API,使用函数指针。

  2. 传统的 C API

  3. FFI API,使用 ffi.load 在运行时加载 libsodium

如果您想加载特定版本,可以附加

  • .ffi(在 C 模块中通过指针使用 FFI)

  • .core(使用传统的 C API)。

  • .pureffi(使用 FFI 并查找/加载运行时的 libsodium)。

.core.ffi 变体在 OpenResty 包管理器版本中不存在,因为 OPM 不支持 C 模块。

示例

    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)

状态

版本 1.0

从版本 1.0.0 开始,此模块涵盖

  • 来自 NaCl 的所有原始高级函数(crypto\_box、crypto\_secretbox 等)。

  • libsodium 对 NaCl 高级函数的所有添加(crypto\_box\_easy、crypto\_secretbox\_easy)。

  • libsodium 的所有实用程序函数和随机数据生成函数。

它尚未涵盖整个 libsodium API。

已实现函数的详细信息可以在 版本 1.0.0 里程碑 中找到。

版本 1.1

  • 来自 NaCl 的所有原始低级函数(crypto\_box\_curve25519xsalsa20poly1305、crypto\_secretbox\_xsalsa20poly1305)。这意味着版本 1.1 对 NaCl 具有 100% 的覆盖率。

版本 1.2

  • libsodium 的 crypto_generichash API。

  • libsodium 的 crypto_secretstream API。

已实现函数的详细信息可以在 版本 1.2.0 里程碑 中找到。

版本 1.3

  • libsodium 的 crypto_shorthash API。

  • libsodium 的 crypto_pwhash API。

已实现函数的详细信息可以在 版本 1.3.0 里程碑 中找到。

版本 2.0

没有功能更改,但 API 发生了更改。libsodium 错误不再抛出错误,而是返回 nil 和错误消息。

版本 2.1

  • libsodium 的 crypto_aead API。

已实现函数的详细信息可以在 版本 2.1.0 里程碑 中找到。

版本 2.2

此版本不再使用 malloc/free,而是使用 sodium_mallocsodium_free,用于需要对齐的数据分配。这在某种程度上简化了 FFI 版本 - 它不再需要加载 C 库的 malloc/free,也不再需要包装器在结构被垃圾回收时调用 sodium_memzero,因为 sodium_free 将负责此操作。

此版本还添加了 scrypt pwhash 函数。

版本 2.3

此版本删除了 2.2 版中引入的 sodium_mallocsodium_free 的使用。根据 libsodium 文档

> 这些不是通用分配函数。特别是,它们比 malloc() 及其同类函数慢,并且需要 3 或 4 个额外的虚拟内存页。

我遇到过内存不足导致的段错误等问题。

与其恢复到需要 mallocfree 的 FFI 版本,它反而使用了 LuaJIT 自己的内存管理,并使用包装器在垃圾回收时调用 sodium_memzero

此版本还添加了 crypto_kx 函数。

注意事项

libsodium 包括用于安全编程的函数,例如分配避免交换的内存、安全地清零内存、清除堆栈等。

我不确定在 Lua 中实现这些类型的函数是否可行。在 Lua 中,我使用 lua_newuserdata 或 LuaJIT 的 ffi.new() 分配内存,以便 Lua 可以跟踪它并对其进行垃圾回收。在将临时内存释放回垃圾回收器之前,我确实会调用 sodium_memzero 来清除它 - 但这仅适用于临时内存。

如果您担心绝对确保内存被清除,则应在 C 中编写安全部分并使用 libsodium 的安全内存函数,或者放弃标准的 Lua 解释器并编写使用 sodium_mallocsodium_free 的自定义分配器的程序。

安装

luarocks

可在 luarocks 上获得

    luarocks install luasodium

OPM

仅 FFI 版本可在 OPM 上获得

    opm install jprjr/luasodium

Arch Linux

可在 AUR 上获得:lua-luasodium

为 lua、lua-5.1、lua-5.2 和 lua-5.3 构建软件包。

源代码

目前正在迁移到 CMake 构建系统。使用 cmake 构建和安装库可以工作,但我尚未将运行测试、生成发布版 tarball 等操作迁移到 cmake 中。

如果您想从源代码构建,请获取其中一个发布版 tarball,然后使用 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 应该会自动查找 libsodium 和 Lua。或者您可以指定一些标志

  • -DLUA_VERSION=5.1(或您想要构建的 Lua 版本)。

  • -DLIBSODIUM_INCLUDEDIR=/path/to/includedir -DLIBSODIUM_LIBRARIES=/path/to/libsodium.so

  • -DLUA_INCLUDEDIR=/path/to/includedir

如果您设置了 LUA_INCLUDEDIR,则还需要设置 LUA_VERSION。如果您使用任何版本的 LuaJIT 进行构建,请将其设置为 5.1

许可证

MIT 许可证(请参阅文件 LICENSE)。

习惯用法

这旨在紧密遵循 Libsodium API,并有一些习惯用法。

习惯用法:使用原始符号名称。

所有函数和常量都使用来自 libsodium 的原始完整名称。

习惯用法:在编程错误时抛出错误

如果某个函数缺少参数或参数类型错误,则会抛出 Lua 错误。

如果对 libsodium 的调用返回错误值(例如,消息解密失败),则返回 nil

习惯用法:自动分配字符串/缓冲区。

如果 libsodium 函数将数据写入缓冲区,则此库将自动分配并返回一个字符串。

习惯用法:处理零填充

原始 NaCl 库 要求用户在消息和密文之前进行填充。

如果 libsodium 函数需要填充,则此库将为您处理,您无需添加填充。

习惯用法:字符串是不可变的。

如果 libsodium 函数更改缓冲区,则此库将改为创建副本,在其中进行更改,并返回副本。

习惯用法:使用输入字符串长度。

如果 libsodium 函数接受缓冲区和缓冲区长度,则 Lua 版本将只接受 Lua 字符串,如果需要使用子字符串调用函数,则可以使用 string.sub

习惯用法示例

libsodium 中,将字符串转换为十六进制为

    sodium_bin2hex(char * const hex, const size_t hex_maxlen,
                   const unsgined char *const bin, const size_t bin_len);

由于此库将自动分配 hex 并使用字符串的长度,因此 Lua 版本仅为

    local string = luasodium.sodium_bin2hex(some_other_string)

libsodium 中,您可以对大整数执行加法、减法等操作,这些操作直接在缓冲区上执行,例如

    char buf[4] = { 0, 0, 0, 0};
    sodium_increment(buf,4);
    /* buf is now { 1, 0 , 0, 0 } */

在 Lua 中,我们改为创建一个新的缓冲区,复制它,递增并返回它。

    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 被分解成子模块,尽管这些子模块主要用于测试和验证 - 建议的方法是只要求 luasodium。这将返回一个模块,其中包含来自子模块的所有函数和常量在一个表中。

有关模块的文档可在 wiki 中找到。

作者

John Regan

许可证

mit

依赖项

luajit

版本