Current section

Files

Jump to
libsodium README.md
Raw

README.md

<!--
DO NOT EDIT: this file was generated by 'just codegen'
@generated SignedSource<<89512dd689f4a587106c61b6d283f91f>>
-->
# libsodium

[![CI](https://github.com/potatosalad/erlang-libsodium/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/potatosalad/erlang-libsodium/actions)
[![Hex.pm](https://img.shields.io/hexpm/v/libsodium.svg)](https://hex.pm/packages/libsodium)
[![HexDocs](https://img.shields.io/badge/docs-hexdocs-blue.svg)](https://hexdocs.pm/libsodium)

[libsodium](https://libsodium.org) 1.0.22 bindings for Erlang and Elixir,
implemented as a NIF.

Every libsodium namespace has its own module, named after its C prefix:
`crypto_secretbox_easy()` is `libsodium_crypto_secretbox:easy/3`. Functions
take and return binaries and integers, raise `badarg` for arguments of the wrong
type or length, and return libsodium's status code (`-1`) when decryption or
verification fails. Streaming hashes, MACs, signatures, and encrypted streams
use opaque native states: each operation returns a new state and leaves its
argument unchanged.

Work that processes more than 64 KiB runs on a dirty CPU scheduler,
password hashing always does, and streaming updates (`update/2` on hash, MAC, and
signature states) yield whenever their timeslice is exhausted.

[API reference](https://hexdocs.pm/libsodium) · [Migrating to 3.0](guides/migrating-to-3.0.md) ·
[Development](guides/development.md) · [Changelog](CHANGELOG.md)

## Installation

Add `libsodium` to your project's dependencies in `mix.exs`:

```elixir
defp deps do
  [
    {:libsodium, "~> 3.0"}
  ]
end
```

Or in `rebar.config`:

```erlang-config
{deps, [
    {libsodium, "~> 3.0"}
]}.
```

Building requires a C compiler, `make`, and Erlang/OTP 27 or later. The
vendored libsodium sources are compiled into the NIF; no system library is
needed.

## Examples

Keys and nonces below are fixed so the outputs are reproducible; real
applications should use each module's `keygen/0` or `keypair/0` and
`libsodium_randombytes:buf/1` for nonces.

### Secret-key authenticated encryption

```erlang
Key = binary:copy(<<1>>, libsodium_crypto_secretbox:keybytes()),
Nonce = binary:copy(<<2>>, libsodium_crypto_secretbox:noncebytes()),
Ciphertext = libsodium_crypto_secretbox:easy(<<"hello">>, Nonce, Key),
<<"691178A0A6E933CF40579C1446303BC59500B29111">> = binary:encode_hex(Ciphertext),
<<"hello">> = libsodium_crypto_secretbox:open_easy(Ciphertext, Nonce, Key),
-1 = libsodium_crypto_secretbox:open_easy(<<Ciphertext/binary, 0>>, Nonce, Key).
```

### Authenticated encryption with additional data

```erlang
Key = binary:copy(<<3>>, libsodium_crypto_aead_xchacha20poly1305:ietf_keybytes()),
Nonce = binary:copy(<<4>>, libsodium_crypto_aead_xchacha20poly1305:ietf_npubbytes()),
Ciphertext = libsodium_crypto_aead_xchacha20poly1305:ietf_encrypt(<<"hello">>, <<"header">>, Nonce, Key),
<<"hello">> = libsodium_crypto_aead_xchacha20poly1305:ietf_decrypt(Ciphertext, <<"header">>, Nonce, Key).
```

### Public-key authenticated encryption

```erlang
{AlicePK, AliceSK} = libsodium_crypto_box:seed_keypair(binary:copy(<<5>>, 32)),
{BobPK, BobSK} = libsodium_crypto_box:seed_keypair(binary:copy(<<6>>, 32)),
Nonce = binary:copy(<<7>>, libsodium_crypto_box:noncebytes()),
Ciphertext = libsodium_crypto_box:easy(<<"hello">>, Nonce, BobPK, AliceSK),
<<"hello">> = libsodium_crypto_box:open_easy(Ciphertext, Nonce, AlicePK, BobSK),
Sealed = libsodium_crypto_box:seal(<<"anonymous">>, BobPK),
<<"anonymous">> = libsodium_crypto_box:seal_open(Sealed, BobPK, BobSK).
```

### Post-quantum key encapsulation

`libsodium_crypto_kem` uses the `xwing` primitive (X-Wing), a hybrid of
ML-KEM-768 and X25519 that stays secure if either one is broken.

```erlang
{PK, SK} = libsodium_crypto_kem:keypair(),
{Ciphertext, SharedSecret} = libsodium_crypto_kem:enc(PK),
SharedSecret = libsodium_crypto_kem:dec(Ciphertext, SK).
```

### Signatures

```erlang
{PK, SK} = libsodium_crypto_sign_ed25519:seed_keypair(binary:copy(<<8>>, 32)),
<<"1398F62C6D1A457C51BA6A4B5F3DBD2F69FCA93216218DC8997E416BD17D93CA">> = binary:encode_hex(PK),
Signature = libsodium_crypto_sign_ed25519:detached(<<"message">>, SK),
0 = libsodium_crypto_sign_ed25519:verify_detached(Signature, <<"message">>, PK),
-1 = libsodium_crypto_sign_ed25519:verify_detached(Signature, <<"forged">>, PK).
```

### Hashing

```erlang
<<"BDDD813C634239723171EF3FEE98579B94964E3BB1CB3E427262C8C068D52319">> =
    binary:encode_hex(libsodium_crypto_generichash:crypto_generichash(<<"abc">>)),
State0 = libsodium_crypto_generichash:init(),
State1 = libsodium_crypto_generichash:update(State0, <<"a">>),
State2 = libsodium_crypto_generichash:update(State1, <<"bc">>),
Digest = libsodium_crypto_generichash:final(State2),
Digest = libsodium_crypto_generichash:crypto_generichash(<<"abc">>).
```

### Extendable output

```erlang
<<"483366601360A8771C6863080CC4114D">> =
    binary:encode_hex(libsodium_crypto_xof_shake256:crypto_xof_shake256(16, <<"abc">>)),
State0 = libsodium_crypto_xof_shake256:update(libsodium_crypto_xof_shake256:init(), <<"abc">>),
{State1, First} = libsodium_crypto_xof_shake256:squeeze(State0, 8),
{_State2, Second} = libsodium_crypto_xof_shake256:squeeze(State1, 8),
Output = libsodium_crypto_xof_shake256:crypto_xof_shake256(16, <<"abc">>),
Output = <<First/binary, Second/binary>>.
```

### Password hashing

```erlang
Hash = libsodium_crypto_pwhash:str(
    <<"correct horse battery staple">>,
    libsodium_crypto_pwhash:opslimit_interactive(),
    libsodium_crypto_pwhash:memlimit_interactive()
),
0 = libsodium_crypto_pwhash:str_verify(Hash, <<"correct horse battery staple">>),
-1 = libsodium_crypto_pwhash:str_verify(Hash, <<"wrong">>).
```

### Key derivation and exchange

```erlang
MasterKey = binary:copy(<<9>>, libsodium_crypto_kdf:keybytes()),
SubKey1 = libsodium_crypto_kdf:derive_from_key(32, 1, <<"Examples">>, MasterKey),
SubKey2 = libsodium_crypto_kdf:derive_from_key(32, 2, <<"Examples">>, MasterKey),
true = SubKey1 =/= SubKey2,
{ClientPK, ClientSK} = libsodium_crypto_kx:seed_keypair(binary:copy(<<10>>, 32)),
{ServerPK, ServerSK} = libsodium_crypto_kx:seed_keypair(binary:copy(<<11>>, 32)),
{ClientRx, ClientTx} = libsodium_crypto_kx:client_session_keys(ClientPK, ClientSK, ServerPK),
{ServerRx, ServerTx} = libsodium_crypto_kx:server_session_keys(ServerPK, ServerSK, ClientPK),
{ClientRx, ClientTx} = {ServerTx, ServerRx}.
```

## Modules

### Secret-key cryptography

| Module | Description | Functions |
| ------ | ----------- | --------: |
| [`libsodium_crypto_aead_aegis128l`](https://hexdocs.pm/libsodium/libsodium_crypto_aead_aegis128l.html) | AEGIS-128L | 14 |
| [`libsodium_crypto_aead_aegis256`](https://hexdocs.pm/libsodium/libsodium_crypto_aead_aegis256.html) | AEGIS-256 | 14 |
| [`libsodium_crypto_aead_aes256gcm`](https://hexdocs.pm/libsodium/libsodium_crypto_aead_aes256gcm.html) | AES256-GCM | 25 |
| [`libsodium_crypto_aead_chacha20poly1305`](https://hexdocs.pm/libsodium/libsodium_crypto_aead_chacha20poly1305.html) | ChaCha20-Poly1305 | 28 |
| [`libsodium_crypto_aead_xchacha20poly1305`](https://hexdocs.pm/libsodium/libsodium_crypto_aead_xchacha20poly1305.html) | XChaCha20-Poly1305 | 14 |
| [`libsodium_crypto_auth`](https://hexdocs.pm/libsodium/libsodium_crypto_auth.html) | Secret-key authentication | 6 |
| [`libsodium_crypto_auth_hmacsha256`](https://hexdocs.pm/libsodium/libsodium_crypto_auth_hmacsha256.html) | HMAC-SHA-256 | 9 |
| [`libsodium_crypto_auth_hmacsha512`](https://hexdocs.pm/libsodium/libsodium_crypto_auth_hmacsha512.html) | HMAC-SHA-512 | 9 |
| [`libsodium_crypto_auth_hmacsha512256`](https://hexdocs.pm/libsodium/libsodium_crypto_auth_hmacsha512256.html) | HMAC-SHA-512-256 | 9 |
| [`libsodium_crypto_ipcrypt`](https://hexdocs.pm/libsodium/libsodium_crypto_ipcrypt.html) | IP address encryption | 26 |
| [`libsodium_crypto_secretbox`](https://hexdocs.pm/libsodium/libsodium_crypto_secretbox.html) | Secret-key authenticated encryption | 14 |
| [`libsodium_crypto_secretbox_xchacha20poly1305`](https://hexdocs.pm/libsodium/libsodium_crypto_secretbox_xchacha20poly1305.html) | XChaCha20-Poly1305 secret box | 8 |
| [`libsodium_crypto_secretbox_xsalsa20poly1305`](https://hexdocs.pm/libsodium/libsodium_crypto_secretbox_xsalsa20poly1305.html) | XSalsa20-Poly1305 secret box | 9 |
| [`libsodium_crypto_secretstream_xchacha20poly1305`](https://hexdocs.pm/libsodium/libsodium_crypto_secretstream_xchacha20poly1305.html) | Encrypted streams | 15 |

### Public-key cryptography

| Module | Description | Functions |
| ------ | ----------- | --------: |
| [`libsodium_crypto_box`](https://hexdocs.pm/libsodium/libsodium_crypto_box.html) | Public-key authenticated encryption | 28 |
| [`libsodium_crypto_box_curve25519xchacha20poly1305`](https://hexdocs.pm/libsodium/libsodium_crypto_box_curve25519xchacha20poly1305.html) | X25519-XChaCha20-Poly1305 box | 21 |
| [`libsodium_crypto_box_curve25519xsalsa20poly1305`](https://hexdocs.pm/libsodium/libsodium_crypto_box_curve25519xsalsa20poly1305.html) | X25519-XSalsa20-Poly1305 box | 16 |
| [`libsodium_crypto_kem`](https://hexdocs.pm/libsodium/libsodium_crypto_kem.html) | Key encapsulation | 10 |
| [`libsodium_crypto_kem_mlkem768`](https://hexdocs.pm/libsodium/libsodium_crypto_kem_mlkem768.html) | ML-KEM-768 key encapsulation | 10 |
| [`libsodium_crypto_kem_xwing`](https://hexdocs.pm/libsodium/libsodium_crypto_kem_xwing.html) | X-Wing key encapsulation | 10 |
| [`libsodium_crypto_kx`](https://hexdocs.pm/libsodium/libsodium_crypto_kx.html) | Key exchange | 9 |
| [`libsodium_crypto_sign`](https://hexdocs.pm/libsodium/libsodium_crypto_sign.html) | Public-key signatures | 17 |
| [`libsodium_crypto_sign_ed25519`](https://hexdocs.pm/libsodium/libsodium_crypto_sign_ed25519.html) | Ed25519 signatures | 20 |
| [`libsodium_crypto_sign_ed25519ph`](https://hexdocs.pm/libsodium/libsodium_crypto_sign_ed25519ph.html) | Ed25519ph signatures | 5 |

### Hashing

| Module | Description | Functions |
| ------ | ----------- | --------: |
| [`libsodium_crypto_generichash`](https://hexdocs.pm/libsodium/libsodium_crypto_generichash.html) | Generic hashing | 18 |
| [`libsodium_crypto_generichash_blake2b`](https://hexdocs.pm/libsodium/libsodium_crypto_generichash_blake2b.html) | BLAKE2b | 25 |
| [`libsodium_crypto_hash`](https://hexdocs.pm/libsodium/libsodium_crypto_hash.html) | Hashing (SHA-512) | 3 |
| [`libsodium_crypto_hash_sha256`](https://hexdocs.pm/libsodium/libsodium_crypto_hash_sha256.html) | SHA-256 | 6 |
| [`libsodium_crypto_hash_sha3256`](https://hexdocs.pm/libsodium/libsodium_crypto_hash_sha3256.html) | SHA3-256 | 6 |
| [`libsodium_crypto_hash_sha3512`](https://hexdocs.pm/libsodium/libsodium_crypto_hash_sha3512.html) | SHA3-512 | 6 |
| [`libsodium_crypto_hash_sha512`](https://hexdocs.pm/libsodium/libsodium_crypto_hash_sha512.html) | SHA-512 | 6 |
| [`libsodium_crypto_shorthash`](https://hexdocs.pm/libsodium/libsodium_crypto_shorthash.html) | Short-input hashing | 5 |
| [`libsodium_crypto_shorthash_siphash24`](https://hexdocs.pm/libsodium/libsodium_crypto_shorthash_siphash24.html) | SipHash-2-4 | 3 |
| [`libsodium_crypto_shorthash_siphashx24`](https://hexdocs.pm/libsodium/libsodium_crypto_shorthash_siphashx24.html) | SipHash-2-4 (128-bit) | 3 |
| [`libsodium_crypto_xof_shake128`](https://hexdocs.pm/libsodium/libsodium_crypto_xof_shake128.html) | SHAKE128 extendable-output function | 8 |
| [`libsodium_crypto_xof_shake256`](https://hexdocs.pm/libsodium/libsodium_crypto_xof_shake256.html) | SHAKE256 extendable-output function | 8 |
| [`libsodium_crypto_xof_turboshake128`](https://hexdocs.pm/libsodium/libsodium_crypto_xof_turboshake128.html) | TurboSHAKE128 extendable-output function | 8 |
| [`libsodium_crypto_xof_turboshake256`](https://hexdocs.pm/libsodium/libsodium_crypto_xof_turboshake256.html) | TurboSHAKE256 extendable-output function | 8 |

### Password hashing

| Module | Description | Functions |
| ------ | ----------- | --------: |
| [`libsodium_crypto_pwhash`](https://hexdocs.pm/libsodium/libsodium_crypto_pwhash.html) | Password hashing | 26 |
| [`libsodium_crypto_pwhash_argon2i`](https://hexdocs.pm/libsodium/libsodium_crypto_pwhash_argon2i.html) | Argon2i password hashing | 22 |
| [`libsodium_crypto_pwhash_argon2id`](https://hexdocs.pm/libsodium/libsodium_crypto_pwhash_argon2id.html) | Argon2id password hashing | 22 |
| [`libsodium_crypto_pwhash_scryptsalsa208sha256`](https://hexdocs.pm/libsodium/libsodium_crypto_pwhash_scryptsalsa208sha256.html) | Scrypt password hashing | 20 |

### Key derivation

| Module | Description | Functions |
| ------ | ----------- | --------: |
| [`libsodium_crypto_kdf`](https://hexdocs.pm/libsodium/libsodium_crypto_kdf.html) | Key derivation | 7 |
| [`libsodium_crypto_kdf_blake2b`](https://hexdocs.pm/libsodium/libsodium_crypto_kdf_blake2b.html) | BLAKE2b key derivation | 5 |
| [`libsodium_crypto_kdf_hkdf_sha256`](https://hexdocs.pm/libsodium/libsodium_crypto_kdf_hkdf_sha256.html) | HKDF-SHA-256 | 13 |
| [`libsodium_crypto_kdf_hkdf_sha512`](https://hexdocs.pm/libsodium/libsodium_crypto_kdf_hkdf_sha512.html) | HKDF-SHA-512 | 13 |

### Advanced

| Module | Description | Functions |
| ------ | ----------- | --------: |
| [`libsodium_crypto_core_ed25519`](https://hexdocs.pm/libsodium/libsodium_crypto_core_ed25519.html) | Edwards25519 arithmetic | 19 |
| [`libsodium_crypto_core_hchacha20`](https://hexdocs.pm/libsodium/libsodium_crypto_core_hchacha20.html) | HChaCha20 core | 5 |
| [`libsodium_crypto_core_hsalsa20`](https://hexdocs.pm/libsodium/libsodium_crypto_core_hsalsa20.html) | HSalsa20 core | 5 |
| [`libsodium_crypto_core_keccak1600`](https://hexdocs.pm/libsodium/libsodium_crypto_core_keccak1600.html) | Keccak-f[1600] permutation | 6 |
| [`libsodium_crypto_core_ristretto255`](https://hexdocs.pm/libsodium/libsodium_crypto_core_ristretto255.html) | Ristretto255 arithmetic | 17 |
| [`libsodium_crypto_core_salsa20`](https://hexdocs.pm/libsodium/libsodium_crypto_core_salsa20.html) | Salsa20 core | 5 |
| [`libsodium_crypto_core_salsa2012`](https://hexdocs.pm/libsodium/libsodium_crypto_core_salsa2012.html) | Salsa20/12 core | 5 |
| [`libsodium_crypto_onetimeauth`](https://hexdocs.pm/libsodium/libsodium_crypto_onetimeauth.html) | One-time authentication | 10 |
| [`libsodium_crypto_onetimeauth_poly1305`](https://hexdocs.pm/libsodium/libsodium_crypto_onetimeauth_poly1305.html) | Poly1305 | 9 |
| [`libsodium_crypto_scalarmult`](https://hexdocs.pm/libsodium/libsodium_crypto_scalarmult.html) | Point multiplication | 5 |
| [`libsodium_crypto_scalarmult_curve25519`](https://hexdocs.pm/libsodium/libsodium_crypto_scalarmult_curve25519.html) | X25519 point multiplication | 4 |
| [`libsodium_crypto_scalarmult_ed25519`](https://hexdocs.pm/libsodium/libsodium_crypto_scalarmult_ed25519.html) | Ed25519 point multiplication | 6 |
| [`libsodium_crypto_scalarmult_ristretto255`](https://hexdocs.pm/libsodium/libsodium_crypto_scalarmult_ristretto255.html) | Ristretto255 point multiplication | 4 |
| [`libsodium_crypto_stream`](https://hexdocs.pm/libsodium/libsodium_crypto_stream.html) | Stream cipher | 7 |
| [`libsodium_crypto_stream_chacha20`](https://hexdocs.pm/libsodium/libsodium_crypto_stream_chacha20.html) | ChaCha20 stream cipher | 14 |
| [`libsodium_crypto_stream_salsa20`](https://hexdocs.pm/libsodium/libsodium_crypto_stream_salsa20.html) | Salsa20 stream cipher | 7 |
| [`libsodium_crypto_stream_salsa2012`](https://hexdocs.pm/libsodium/libsodium_crypto_stream_salsa2012.html) | Salsa20/12 stream cipher | 6 |
| [`libsodium_crypto_stream_xchacha20`](https://hexdocs.pm/libsodium/libsodium_crypto_stream_xchacha20.html) | XChaCha20 stream cipher | 7 |
| [`libsodium_crypto_stream_xsalsa20`](https://hexdocs.pm/libsodium/libsodium_crypto_stream_xsalsa20.html) | XSalsa20 stream cipher | 7 |
| [`libsodium_crypto_verify_16`](https://hexdocs.pm/libsodium/libsodium_crypto_verify_16.html) | 16-byte comparison | 2 |
| [`libsodium_crypto_verify_32`](https://hexdocs.pm/libsodium/libsodium_crypto_verify_32.html) | 32-byte comparison | 2 |
| [`libsodium_crypto_verify_64`](https://hexdocs.pm/libsodium/libsodium_crypto_verify_64.html) | 64-byte comparison | 2 |

### Helpers

| Module | Description | Functions |
| ------ | ----------- | --------: |
| [`libsodium_randombytes`](https://hexdocs.pm/libsodium/libsodium_randombytes.html) | Random data | 10 |
| [`libsodium_runtime`](https://hexdocs.pm/libsodium/libsodium_runtime.html) | CPU features | 12 |
| [`libsodium_utils`](https://hexdocs.pm/libsodium/libsodium_utils.html) | Helpers | 20 |
| [`libsodium_version`](https://hexdocs.pm/libsodium/libsodium_version.html) | Library version | 4 |

`libsodium_nif` exposes all 732 native functions directly, named
`<namespace>_<function>`.

## Development

The native sources, the Erlang modules, the generated tests, and this README
are generated from the YAML definitions in [`codegen/`](codegen/README.md):

```sh
just codegen          # or `just docker-codegen` to run in a Linux container
gmake tests           # Common Test suites
gmake lint            # formatting, Dialyzer, Eqwalizer, and xref
just bench            # Benchee comparisons with OTP crypto; see bench/README.md
```

Generated files carry a signature; edit the definitions or templates and
regenerate rather than changing them by hand.

## License

[MIT](LICENSE.md). libsodium is distributed under the [ISC license](https://github.com/jedisct1/libsodium/blob/master/LICENSE).