Rust-Sodiumoxide: sodiumoxide — libsodium bindings


Crate Documentation Linux/OS X Windows Coverage Gitter Docs TravisCI AppveyorCI Coverage Status Gitter

NaCl (pronounced "salt") is a new easy-to-use high-speed software library for network communication, encryption, decryption, signatures, etc. NaCl's goal is to provide all of the core operations needed to build higher-level cryptographic tools. Of course, other libraries already exist for these core operations. NaCl advances the state of the art by improving security, by improving usability, and by improving speed.

Sodium is a portable, cross-compilable, installable, packageable fork of NaCl (based on the latest released upstream version nacl-20110221), with a compatible API.

This package aims to provide a type-safe and efficient Rust binding that's just as easy to use. Rust >= 1.36.0 is required because of mem::MaybeUninit.

Basic usage


git clone
cd sodiumoxide
git submodule update --init --recursive


cargo build


cargo test


cargo doc

Documentation will be generated in target/doc/...

Most documentation is taken from NaCl, with minor modification where the API differs between the C and Rust versions.


C compiler (cc, clang, ...) must be installed in order to build libsodium from source.

Extended usage

This project contains a snapshot of libsodium and builds it by default, favouring a statically-built, fixed version of the native library.

Although it is highly recommended to use the default way with the pinned version, there are several ways you may want to use this crate:

  • link it against the library installed on your system
  • link it against a precompiled library that you built on your own

You can do this by setting environment variables.

Name Description Example value Notes
SODIUM_LIB_DIR Where to find a precompiled library /usr/lib/x86_64-linux-gnu/ The value should be set to the directory containing .so,.a,.la,.dll or .lib
SODIUM_SHARED Tell rustc to link the library dynamically 1 Works only with SODIUM_LIB_DIR. We check only the presence
SODIUM_USE_PKG_CONFIG Tell to find system library using pkg-config or vcpkg 1 We check only the presence
SODIUM_DISABLE_PIE Build with --disable-pie 1 Certain situations may require building libsodium configured with --disable-pie. Useful for !Windows only and when building libsodium from source. We check only the presence
VCPKGRS_DYNAMIC Tell vcpkg to find libsodium 1 Usefull for Windows only with SODIUM_USE_PKG_CONFIG. More info:

Examples on *nix

Using pkg-config

(Ubuntu: apt install pkg-config, OSX: brew install pkg-config, ...)

cargo build

Using precompiled library


export SODIUM_LIB_DIR=/home/user/libsodium-1.0.18/release/lib/
cargo build

Examples on Windows

Using vcpkg


C:\Users\user\dev\vcpkg\vcpkg.exe install libsodium --triplet x64-windows
cargo build

Optional features

Several optional features are available:

  • std (default: enabled). When this feature is disabled, sodiumoxide builds using #![no_std]. Some functionality may be lost. Requires a nightly build of Rust.

  • serde (default: enabled). Allows serialization and deserialization of keys, authentication tags, etc. using the serde library.

  • benchmarks (default: disabled). Compile benchmark tests. Requires a nightly build of Rust.


Cross-Compiling for armv7-unknown-linux-gnueabihf

  1. Install dependencies and toolchain:
sudo apt update
sudo apt install build-essential gcc-arm-linux-gnueabihf libc6-armhf-cross libc6-dev-armhf-cross -y
rustup target add armv7-unknown-linux-gnueabihf
  1. Add the following to a .cargo/config file:
linker = "arm-linux-gnueabihf-gcc"
  1. Build by running:
cargo build --release --target armv7-unknown-linux-gnueabihf

Cross-Compiling for armv7-unknown-linux-musleabihf via docker

  1. cargo.config:
linker = "arm-buildroot-linux-musleabihf-gcc"
  1. Dockerfile:
FROM rust:1.36.0

ENV TARGET="armv7-unknown-linux-musleabihf"

ARG TOOLCHAIN_ARM7="armv7-eabihf--musl--stable-2018.02-2"

RUN rustup target add ${TARGET}
COPY cargo.config "${CARGO_HOME}/config"

RUN curl -o- ${TC_ARM7_URL} | tar -xjf -

ENV CC_armv7_unknown_linux_musleabihf=arm-buildroot-linux-musleabihf-gcc
ENV CXX_armv7_unknown_linux_musleabihf=arm-buildroot-linux-musleabihf-g++
ENV LD_armv7_unknown_linux_musleabihf=arm-buildroot-linux-musleabihf-ld

RUN git clone

WORKDIR /work/sodiumoxide
RUN cargo build --target=${TARGET}

Cross-Compiling for 32-bit Linux

  1. Install dependencies and toolchain:
sudo apt update
sudo apt install build-essential gcc-multilib -y
rustup target add i686-unknown-linux-gnu
  1. Build by running:
cargo build --release --target i686-unknown-linux-gnu



Platform Compatibiility

Sodiumoxide has been tested on:

  • Linux: Yes
  • Windows: Yes (MSVC)
  • Mac OS: Yes
  • Android: TODO

Join in

File bugs in the issue tracker

Master git repository

git clone


Licensed under either of

at your option.


Go through the document to know more about how to contribute to this project.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Code of Conduct

We believe in creating an enabling community for developers and have laid out a general code of conduct. Please read and adopt it to help us achieve and maintain the desired community standards.


  • Expose libsodium's single-chunk generic hash routine
    Expose libsodium's single-chunk generic hash routine

    Nov 23, 2019

    Also exposes that libsodium provides a recommended minimum hash size (currently 256 bits) so that the user can be freed from having to come up with a reasonable hash size in many cases.

    The API change of State::new is of course breaking which could be avoided in various ways:

    • State just requires the user to supply a hash size and hash has a different API.
    • A separate State::rec_out_len constructor is provided that forwards to an internal generic constructor.
    • Expose the recommended digest length as a constant DIGEST_REC that the user must pass instead of None.

    Personally, I opted against that as the current 0.2.x crate version suggests that the API is still evolving and hence a clean API seems preferable to a compatible one.

  • RFC: Try to simplify build options for libsodium
    RFC: Try to simplify build options for libsodium

    Dec 7, 2019

    • Make sure we use the target when deciding on what to probe, link or build.
    • Make it easy to persistently enable pkg-config and vcpkg via feature flag.
    • Align environment variables with pkg-config and vcpkg bindings.

    Closes #377 Closes #359

    This is my first try that does not take any precautions w.r.t. backwards compatibility but sticks to the idea that the bundled build is the default while making it easy to persistently enable pkg-config or vcpkg usage. I also separated linking prebuilt libraries and building from source as this simplifies building from source a bit.

  • Confusing SODIUM_USE_PKG_CONFIG behavior on msvf
    Confusing SODIUM_USE_PKG_CONFIG behavior on msvf

    Jan 17, 2020

    SODIUM_USE_PKG_CONFIG secretly uses vcpkg if the MSVC toolchain is selected which is pretty counter intuitive looking at the name of this variable.

    cc @sdroege

  • Support selecting static builds for windows only
    Support selecting static builds for windows only

    Apr 4, 2020

    This change allows a project to link dynamically on all platforms except windows and optionally supports static builds on all systems with a feature.

    The reason static-windows is slightly awkward is due to, meaning if [target.'cfg(windows)'.dependencies] enables the sodiumoxide/static feature it would be enabled for all targets including linux, and the other way around if cfg(not(windows)) enables sodiumoxide/use-pkg-config it would be enabled for windows as well.

    The static feature is necessary because cargo features are strictly additive and it's impossible to express "default to dynamic linking and allow opting into static builds" without messing around with --no-default-features.


    This is what I currently do in my projects:

    default = ["dynamic-libsodium"]
    dynamic-libsodium = ["sodiumoxide/use-pkg-config"]

    | | Linux | MacOS | Windows | | --- | --- | --- | --- | | cargo build | dynamic | dynamic | error | | cargo build --no-default-features | static | static | static |


    Intended usage after this patch would look like this:

    static = ["sodiumoxide/static"]
    sodiumoxide = { version="0.2.5", features=["use-pkg-config, "static-windows"] }

    | | Linux | MacOS | Windows | | --- | --- | --- | --- | | cargo build | dynamic | dynamic | static | | cargo build --features static | static | static | static |

    This change is explicitly non-breaking but prepares for a future breaking change that would allow us to resolve #411 by simply making use-pkg-config the default behavior. Also relates to #359.

    Due to features being additive a library crate should never enable the static feature.

  • Data from box opens is not zeroed on drop
    Data from box opens is not zeroed on drop

    May 24, 2020

    sealedbox::open (and box_::open, secretbox::open) return a Vec<u8> on success, which is not a newtype like secretbox::Key etc., and therefore does not have the protection of being zeroed when being dropped (e.g. for secretbox::Key we have this Drop implementation)

    Would it be a good idea to add a newtype for decrypted data which implements this Drop safety feature?

    Alternatively we could mimic the C API by providing a buffer to be filled, with the consumer ensuring memory protection, like in the pwhash example.

  • Add support for the AES256-GCM AEAD construction
    Add support for the AES256-GCM AEAD construction

    May 30, 2020

    This commit adds support for AES256-GCM. NB: libsodium limits its support of AES256-GCM to x86/x86-64 processors with the AES-NI instruction set. Compile time feature flags are used to hide GCM functionality for targets lacking the requisite support. In the interest of maintaining parity with the libsodium API an is_available function mapping to crypto_aead_aes256gcm_is_available is unconditionally exported but shouldn't be required given the compile-time check.

    Signed-off-by: Kelly Littlepage [email protected]

  • Ship libsodium as a Git submodule
    Ship libsodium as a Git submodule

    Nov 20, 2019

    Avoid dev dependencies on tar and libflate by including libsodium as a Git submodule.

    Closes #392

  • Implement secretstream API
    Implement secretstream API

    Jul 13, 2018

    Supersedes #222. I couldn't request a review from you @dkulic, but please take a look.

  • Replace mem::uninitialized with MaybeUninit
    Replace mem::uninitialized with MaybeUninit

    Jul 17, 2019


  • Added support for Stream encryption/file encryption using xchacha20-poly1305
    Added support for Stream encryption/file encryption using xchacha20-poly1305

    Jun 18, 2018

    Signed-off-by: Darko Kulic [email protected]

    Wontfix: Superseded enhancement 
  • Call for maintainers
    Call for maintainers

    May 4, 2018

    Call for maintainers

    Since I haven't had time to maintain sodiumoxide lately, I think it is time for someone else to take the reins. There are some outstanding pull-requests and open issues and even though sodiumoxide is usable as is, I feel bad for everyone contributing when I don't have time to merge, or even look at, their changes.

    In this document I'll try to explain the background and philosophy of sodiumoxide and also what I'm looking for in a maintainer.


    When I started to learn rust (back in the 0.x days, when pointers still had sigils) I decided to implement a network service as my learner project. For that service I needed some cryptographic functionality, so I made some bindings to libsodium since the cryptographic ecosystem of rust was basically non-existent at the time.

    After a while I realized that good, and easy to use, cryptographic bindings were something that the whole rust community could make use of. Also, by making one of the first cryptographic libraries for rust consist of relatively safe primitives there was an opportunity to make other rust projects keep a higher cryptographic standard than in many other languages. This might sound far-fetched, but in my experience many developers unfamiliar with an API will read the documentation and experiment until they have something that seems to work. The main issue of course is that in cryptography something that seems to work can still fail in catastrophic ways. I believe the right solution for that is to make the APIs as fool-proof as possible, and NaCl/libsodium has done a lot of work in exposing those kinds of APIs.

    The main box/secretbox abstraction is a really nice one, and even though it doesn't protect against misuse of nonces, the abstraction protects against a lot of potential errors. This can be contrasted to just giving a programmer without cryptographic experience raw access to block ciphers, cipher modes, MACs, asymmetric cipher and hope that they will magically combine these primitives into something secure.

    By making it easy to use secure primitives in rust, my hope was that authors looking to use cryptography would default to using these primitives.

    A bindings library per-se isn't that big of an achievement, but I saw no need in reimplementing NaCl in rust at the time. This might be a fun future project idea though.


    The basic philosophy of sodiumoxide is the same as of NaCl. Expose secure and easy to use primitives by default. The main goal isn't to implement all possible cryptographic primitives or to be able to implement something like TLS using sodiumoxide.

    Another important part of the philosophy is to not add primitives and functionality that hasn't been proven secure (or isn't part of the cryptographic literature). An example of this is the key-conversion functionality between curve25519 and ed25519 keys that has been requested multiple times. Since there is no literature proving that dual-use of keys for both key derivation and signing is secure I haven't added that functionality.

    I prefer the maintainer to subscribe to the same philosophy. We can add functionality as long as we don't create new potential foot-guns for the users of the library.

    Tasks for a maintainer

    For all open issues and pull-requests: - For each issue, decide if it's something that should be added - Do a thorough code review of all changes - Make sure that the code follows the coding style in the project - Make sure that the code contains thorough tests - Merge the code into the master branch

    I'm also looking for someone that can communicate with the community.

    Future Directions

    Add new functionality from libsodium

    This is of course contingent on the functionality being compatible with our philosophy.

    Try to make sodiumoxide usable on embedded systems

    Make sure that the library can work without dynamic memory allocations, that we can build it with xargo and so on.

    Use bindgen to create libsodium-sys instead of handwriting it

    This hasn't been done yet since bindgen has an open bug where it messes up constness of pointers.

    Choice of static compilation of libsodium-sys

    There have been some pull-requests that automatically download and build libsodium as part of the build of sodiumoxide. This is something that would help a lot of users, but I have been concerned about verifying the authenticity of the libsodium download. This functionality is contingent on being able to solve the download issue in a secure way.

    Transition Plan

    1. First I will see if anyone wants to maintain the library at all, if not then it might be time to deprecate it.
    2. If I find someone suitable I will discuss the issue with them
    3. We will then decide if I should grant commit access to the repository of if they should fork the repository (effectively moving it).
    4. During a transition period the maintainer will need to ask me to make a new release
      • I will review the diff and discuss it with the maintainer
      • If I'm happy a new release will be pushed to
    5. After a transition period I will hand over access to to the new maintainer.


    Any questions about the search for a new maintainer are directed to this thread.

  • Add include & lib build metadata to libsodium-sys
    Add include & lib build metadata to libsodium-sys

    Jun 12, 2019

    Adds DEP_SODIUM_INCLUDE & DEP_SODIUM_LIB env variable to can be used by dependent crates. In my case, I use it to link against libsodium from a c++ library (libzmq) built via cargo.