Code Monkey home page Code Monkey logo

enacl's Introduction

Erlang bindings for NaCl/libsodium

This library provides bindings for the libsodium cryptographic library for Erlang. Originally called NaCl by Bernstein, Lange and Schwabe[0], Frank Denis took the source and made it far more portable in the libsodium library. The enacl project is somewhat misnamed, as it uses libsodium as the underlying driver.

INSTALL/Requirements

  • New-ish Erlang installation. Tested back to version 22.3, but version 21 may work as well.
  • Requires the libsodium library, and has been tested with version 1.0.18. Lower versions might work, or they might fail to compile, due to missing functionality. In particular, this means your libsodium installation must be fairly recent as well.

Note: If installing on systems which cuts packages into subpackages, make sure you also get the "-dev" package containing the header files necessary in order to compile software linking to libsodium.

To build the software execute:

make

or

rebar compile

To build and run licensed eqc test execute:

make eqc_run

To build and run eqc-mini version of test execute:

make eqc_mini_run

Features

  • Complete NaCl library, implementing all default functionality.
  • Implements a large set of additional functionality from libsodium. Most notably access to a proper CSPRNG random source
  • Tests created by aggressive use of Erlang QuickCheck.
  • NaCl is a very fast cryptographic library. That is, crypto-operations runs quickly on modern CPUs, with ample security margins. This makes it highly useful on the server-side, where simultaneous concurrent load on the system means encryption can have a considerable overhead.
  • Is tested on Linux, FreeBSD and Illumos (Omnios)

This package draws heavy inspiration from "erlang-nacl" by Tony Garnock-Jones, and started its life with a gently nod in that direction. However, it is a rewrite and it alters lots of code from Tony's original work.

In addition, I would like to thank Steve Vinoski, Rickard Green, and Sverker Eriksson for providing the Dirty Scheduler API in the first place.

Usage

In general, consult the libsodium documentation at Libsodium documentation

The original NaCl documentation is nowadays largely superceded by the libsodium documentation, but it is still worth a visit NaCl website

but also note that our interface has full Edoc documentation, generated by executing

rebar3 doc

Hints

In general, the primitives provided by NaCl are intermediate-level primitives. Rather than you having to select a cipher suite, it is selected for you, and primitives are provided at a higher level. However, their correct use is still needed in order to be secure:

  • Always make sure you obey the scheme of nonce values. If you ever reuse a nonce, and an attacker figures this out, the system will leak the XOR difference of messages sent with the same nonce. Given enough guessing, this can in turn leak the encryption stream of bits and every message hereafter, sent on the same keypair combination and reusing that nonce, will be trivially breakable.
  • Use the beforenm/afternm primitives if using the box public-key encryption scheme. Precomputing the Curve25519 operations yields much faster operation in practice for a stream. Consult the bench directory for benchmarks in order to see how much faster it is for your system. The authors Core i7-4900MQ can process roughly 32 Kilobyte data on the stream in the time it takes to do the Curve25519 computations. While NaCl is fast, this can make it even faster in practice.
  • Encrypting very large blocks of data, several megabytes for instance, is problematic for two reasons. First, while the library attempts to avoid being a memory hog, you need at least a from-space and a to-space for the data, meaning you need at least double the memory for the operation. Furthermore, while such large blocks are executed on the dirty schedulers, they will never yield the DS for another piece of work. This means you end up blocking the dirty schedulers in turn. It is often better to build a framing scheme and encrypt data in smaller chunks, say 64 or 128 kilobytes at a time. In any case, it is important to measure. Especially for latency.
  • The library should provide correct success type specifications. This means you can use the dialyzer on your code and get hints for incorrect usage of the library.
  • Note that every "large" input to the library accepts iodata() rather than binary() data. The library itself will convert iodata() to binaries internally, so you don't have to do it at your end. It often yields simpler code since you can just build up an iolist of your data and shove it to the library. Key material, nonces and the like are generally not accepted as iodata() however but requires you to input binary data. This is a deliberate choice since most such material is not supposed to be broken up and constructed ever (except perhaps for the Nonce construction).
  • The enacl:randombytes/1 function provides portable access to the CSPRNG of your kernel. It is an excellent source of CSPRNG random data. If you need PRNG data with a seed for testing purposes, use the rand module of Erlang. The other alternative is the crypto module, which are bindings to OpenSSL with all its blessings and/or curses.
  • Beware of timing attacks against your code! A typical area is string comparison, where the comparator function exits early. In that case, an attacker can time the response in order to guess at how many bytes where matched. This in turn enables some attacks where you use a foreign system as an oracle in order to learn the structure of a string, breaking the cryptograhic system in the process.

Versions

See CHANGELOG.md

Overview

The NaCl cryptographic library provides a number of different cryptographic primitives. In the following, we split up the different generic primitives and explain them briefly.

A note on Nonces: The crypto API makes use of "cryptographic nonces", that is arbitrary numbers which are used only once. For these primitives to be secure it is important to consult the NaCl documentation on their choice. They are large values so generating them randomly ensures security, provided the random number generator uses a sufficiently large period. If you end up using, say, the nonce 7 every time in communication while using the same keys, then the security falls.

The reason you can pick the nonce values is because some uses are better off using a nonce-construction based on monotonically increasing numbers, while other uses do not. The advantage of a sequence is that it can be used to reject older messages in the stream and protect against replay attacks. So the correct use is up to the application in many cases.

Public Key cryptography

This implements standard Public/Secret key cryptography. The implementation roughly consists of two major sections:

  • Authenticated encryption: provides a box primitive which encrypts and then also authenticates a message. The reciever is only able to open the sealed box if they posses the secret key and the authentication from the sender is correct.
  • Signatures: allows one party to sign a message (not encrypting it) so another party can verify the message has the right origin.

Secret key cryptography

This implements cryptography where there is a shared secret key between parties.

  • Authenticated encryption: provides a secret box primitive in which we can encrypt a message with a shared key k. The box also authenticates the message, so a message with an invalid key will be rejected as well. This protects against the application obtaining garbage data.
  • Encryption: provides streams of bytes based on a Key and a Nonce. These streams can be used to XOR with a message to encrypt it. No authentication is provided. The API allows for the system to XOR the message for you while producing the stream.
  • Authentication: Provides an implementation of a Message Authentication Code (MAC).
  • One Time Authentication: Authenticate a message, but do so one-time. That is, a sender may never authenticate several messages under the same key. Otherwise an attacker can forge authenticators with enough time. The primitive is simpler and faster than the MAC authenticator however, so it is useful in some situations.

Low-level functions

  • Hashing: Cryptographically secure hashing
  • String comparison: Implements guaranteed constant-time string comparisons to protect against timing attacks.

Rationale

Doing crypto right in Erlang is not that easy. For one, the crypto system has to be rather fast, which rules out Erlang as the main vehicle. Second, cryptographic systems must be void of timing attacks. This mandates we write the code in a language where we can avoid such timing attacks, which leaves only C as a contender, more or less. The obvious way to handle this is by the use of NIF implementations, but most C code will run to its conclusion once set off for processing. This is a major problem for a system which needs to keep its latency in check. The solution taken by this library is to use the new Dirty Scheduler API of Erlang in order to provide a safe way to handle the long-running cryptographic processing. It keeps the cryptographic primitives on the dirty schedulers and thus it avoids the major problem.

Focus has first and foremost been on the correct use of dirty schedulers, without any regard for speed. The plan is to extend the underlying implementation, while keeping the API stable. We can precompute keys for some operations for instance, which will yield a speedup.

Also, while the standard crypto bindings in Erlang does a great job at providing cryptographic primitives, these are based on OpenSSL, which is known to be highly problematic in many ways. It is not as easy to use the OpenSSL library correctly as it is with these bindings. Rather than providing a low-level cipher suite, NaCl provides intermediate level primitives constructed as to protect the user against typical low-level cryptographic gotchas and problems.

Scheduler handling

To avoid long running NIFs, the library switches to the use of dirty schedulers for large encryption tasks. We investigated the Dirty Scheduler switch overhead with DTrace on FreeBSD and found it to be roughly 5μs in typical cases. Thus, we target calls taking at least 35μs is being easier to run directly on the dirty scheduler, as the overhead for switching is thus going to be less than 15%. This means very small operations are run directly on the BEAM scheduler, but as soon as the operation takes a little longer, the switch overhead is not large enough to warrant the current schedulers involvement.

In turn, some operations are always run on the dirty scheduler because they take a long time in every case. This setup is far simpler for most operations, unless the operation is performance sensitive and allows small messages.

The tests were conducted on a Core 2 Duo machine, with newer machines perhaps being able to switch faster. There are plans to rerun these tests on OSX and Illumos as well, in order to investigate the numbers on more platforms.

Testing

Every primitive has been stress-tested through the use of Erlang QuickCheck with both positive and negative testing. This has been used to check against memory leaks as well as correct invocation. Please report any error so we can extend the test cases to include a randomized test which captures the problem so we generically catch every problem in a given class of errors.

Positive and negative testing refers to Type I and Type II errors in statistical testing. This means false positives—given a valid input the function rejects it; as well as false negatives—given an invalid input the functions fails to reject that input.

The problem however, is that while we are testing the API level, we can't really test the strength of the cryptographic primitives. We can verify their correctness by trying different standard correctness tests for the primitives, verifying that the output matches the expected one given a specific input. But there is no way we can show that the cryptographic primitive has the strength we want. Thus, we opted to mostly test the API and its invocation for stability.

Also, in addition to correctness, testing the system like this makes sure we have no memory leaks as they will show themselves under the extensive QuickCheck test cases we run. It has been verified there are no leaks in the code.

Notes

[0] Other people have worked on bits and pieces of NaCl. These are just the 3 main authors. Please see the page NaCl for the full list of authors.

enacl's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

enacl's Issues

Fails at runtime in `nix develop` / `direnv` with `use flake`

Not sure if this is an enacl issue, but with the following minimal flake.nix:

{
    inputs = {
        nixpkgs.url = "github:nixos/nixpkgs";
    };

    outputs = {self, nixpkgs}:
        let pkgs = nixpkgs.legacyPackages.x86_64-linux;
        in {
            defaultPackage.x86_64-linux = pkgs.hello;

            devShell.x86_64-linux =
                pkgs.mkShell { buildInputs = [
                    pkgs.elixir
                    pkgs.erlang
                    pkgs.libsodium
                ]; };
        };
}

trying to use an enacl function fails with:

21:21:01.386 [warn]  The on_load function for module enacl_nif returned:
{:error,
 {:load_failed,
  'Failed to load NIF library /home/sweater/github/cluster/_build/test/lib/enacl/priv/enacl_nif: \'libsodium.so.23: cannot open shared object file: No such file or directory\''}}

enacl:pwhash() doesn't work as expected on Windows x64

There's an issue with enacl:pwhash() when Ops|Mem limits are specified only on Windows amd64.
The issue is that Ops|Mem limits are parsed using enif_get_ulong().

unsigned long on Windows is 4-bytes wide even on 64-bit systems.

enacl:pwhash() doesn't behave as expected even for 4-byte integers that are supplied for Ops|Mem limits.
Why?

The parsed result is stored in a size_t 8-byte wide (uninitialized) integer r.
The uninitialized 4 bytes contain random bits and other 4 bytes contain the parsed unsigned long returned by enif_get_ulong.
As a result depending on the contents of the uninitialized 4 bytes, the resultant r that is returned for limit may cross
crypto_pwhash_OPSLIMIT_MAX|crypto_pwhash_MEMLIMIT_MAX

This can be fixed by using enacl_get_uint64() when sizeof(size_t) == 8 and enacl_get_uint() when sizeof(size_t) == 4.
This bug is to track the issue.

problems compiling enacl

Hi there!

I've been trying for a while now, I initially thought the issue was that I didn't have libsodium installed (compiler couldn't find the header file sodium.h, but I fixed that and now I'm getting this new set of errors. Any chance I could be pointed in the right direction? Thank you!

cc -I/usr/local/opt/openssl/include -I/usr/local/include -I/usr/local/opt/expat/include -fPIC -I /usr/local/Cellar/erlang@22/22.3.4.12/lib/erlang/erts-10.7.2.5/include/ -I /usr/local/Cellar/erlang@22/22.3.4.12/lib/erlang/lib/erl_interface-3.13.2/include -I/usr/local/opt/openssl/include/ -I/usr/local/include -I/usr/local/opt/expat/include -c -o /Users/test-user/test/testejabberd/deps/enacl/c_src/enacl_nif.o /Users/test-user/test/testejabberd/deps/enacl/c_src/enacl_nif.c
cc /Users/test-user/test/testejabberd/deps/enacl/c_src/enacl_nif.o -L/usr/local/opt/openssl/lib -L/usr/local/lib -L/usr/local/opt/expat/lib -shared -L /usr/local/Cellar/erlang@22/22.3.4.12/lib/erlang/lib/erl_interface-3.13.2/lib -lerl_interface -lei -lsodium -o /Users/test-user/test/testejabberd/deps/enacl/c_src/../priv/enacl_nif.so
Undefined symbols for architecture x86_64:
  "_enif_alloc_binary", referenced from:
      _enif_crypto_box_keypair in enacl_nif.o
      _enif_crypto_box in enacl_nif.o
      _enif_crypto_box_open in enacl_nif.o
      _enif_crypto_box_beforenm in enacl_nif.o
      _enif_crypto_box_afternm in enacl_nif.o
      _enif_crypto_box_open_afternm in enacl_nif.o
      _enif_crypto_sign_keypair in enacl_nif.o
      ...
  "_enif_alloc_resource", referenced from:
      _enif_crypto_generichash_init in enacl_nif.o
  "_enif_get_resource", referenced from:
      _enif_crypto_generichash_update in enacl_nif.o
      _enif_crypto_generichash_final in enacl_nif.o
  "_enif_get_uint", referenced from:
      _enif_randombytes in enacl_nif.o
      _enif_crypto_generichash in enacl_nif.o
      _enif_crypto_generichash_init in enacl_nif.o
      _enif_crypto_generichash_update in enacl_nif.o
      _enif_crypto_generichash_final in enacl_nif.o
  "_enif_get_ulong", referenced from:
      _enif_crypto_stream_chacha20 in enacl_nif.o
      _enif_crypto_stream in enacl_nif.o
  "_enif_inspect_binary", referenced from:
      _enif_crypto_box in enacl_nif.o
      _enif_crypto_box_open in enacl_nif.o
      _enif_crypto_box_beforenm in enacl_nif.o
      _enif_crypto_box_afternm in enacl_nif.o
      _enif_crypto_box_open_afternm in enacl_nif.o
      _enif_crypto_sign in enacl_nif.o
      _enif_crypto_sign_open in enacl_nif.o
      ...
  "_enif_inspect_iolist_as_binary", referenced from:
      _enif_crypto_box in enacl_nif.o
      _enif_crypto_box_open in enacl_nif.o
      _enif_crypto_box_afternm in enacl_nif.o
      _enif_crypto_box_open_afternm in enacl_nif.o
      _enif_crypto_sign in enacl_nif.o
      _enif_crypto_sign_open in enacl_nif.o
      _enif_crypto_sign_detached in enacl_nif.o
      ...
  "_enif_make_atom", referenced from:
      _enif_crypto_sign_verify_detached in enacl_nif.o
      _enif_crypto_auth_verify in enacl_nif.o
      _enif_crypto_onetimeauth_verify in enacl_nif.o
      _enif_crypto_verify_16 in enacl_nif.o
      _enif_crypto_verify_32 in enacl_nif.o
      _enif_sodium_memzero in enacl_nif.o
      _enif_crypto_pwhash in enacl_nif.o
      ...
  "_enif_make_badarg", referenced from:
      _enif_crypto_box_keypair in enacl_nif.o
      _enif_crypto_box in enacl_nif.o
      _enif_crypto_box_open in enacl_nif.o
      _enif_crypto_box_beforenm in enacl_nif.o
      _enif_crypto_box_afternm in enacl_nif.o
      _enif_crypto_box_open_afternm in enacl_nif.o
      _enif_crypto_sign_keypair in enacl_nif.o
      ...
  "_enif_make_binary", referenced from:
      _enif_crypto_box_keypair in enacl_nif.o
      _enif_crypto_box in enacl_nif.o
      _enif_crypto_box_open in enacl_nif.o
      _enif_crypto_box_beforenm in enacl_nif.o
      _enif_crypto_box_afternm in enacl_nif.o
      _enif_crypto_box_open_afternm in enacl_nif.o
      _enif_crypto_sign_keypair in enacl_nif.o
      ...
  "_enif_make_long", referenced from:
      _enif_crypto_box_NONCEBYTES in enacl_nif.o
      _enif_crypto_box_ZEROBYTES in enacl_nif.o
      _enif_crypto_box_BOXZEROBYTES in enacl_nif.o
      _enif_crypto_box_PUBLICKEYBYTES in enacl_nif.o
      _enif_crypto_box_SECRETKEYBYTES in enacl_nif.o
      _enif_crypto_box_BEFORENMBYTES in enacl_nif.o
      _enif_crypto_sign_PUBLICKEYBYTES in enacl_nif.o
      ...
  "_enif_make_resource", referenced from:
      _enif_crypto_generichash_init in enacl_nif.o
      _enif_crypto_generichash_update in enacl_nif.o
  "_enif_make_sub_binary", referenced from:
      _enif_crypto_box in enacl_nif.o
      _enif_crypto_box_open in enacl_nif.o
      _enif_crypto_box_afternm in enacl_nif.o
      _enif_crypto_box_open_afternm in enacl_nif.o
      _enif_crypto_sign in enacl_nif.o
      _enif_crypto_sign_open in enacl_nif.o
      _enif_crypto_secretbox in enacl_nif.o
      ...
  "_enif_make_tuple", referenced from:
      _enif_make_tuple2 in enacl_nif.o
      _enif_make_tuple3 in enacl_nif.o
  "_enif_open_resource_type", referenced from:
      _enif_crypto_load in enacl_nif.o
  "_enif_release_binary", referenced from:
      _enif_crypto_box_open in enacl_nif.o
      _enif_crypto_box_open_afternm in enacl_nif.o
      _enif_crypto_sign_open in enacl_nif.o
      _enif_crypto_box_seal_open in enacl_nif.o
      _enif_crypto_secretbox_open in enacl_nif.o
      _enif_crypto_pwhash in enacl_nif.o
      _enif_crypto_pwhash_str in enacl_nif.o
      ...
  "_enif_release_resource", referenced from:
      _enif_crypto_generichash_init in enacl_nif.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [/Users/test-user/test/testejabberd/deps/enacl/c_src/../priv/enacl_nif.so] Error 1
ERROR: Command [compile] failed!
make: *** [deps/.built] Error 1

Makefile for NIFs on Apple M1 processor is incorrect

the Makefile options for compiling enacl fail for the arm-64 darwin architectures. See upstream in rebar where the -arch x86 flag is no longer specified (erlang/rebar3#2655). The very hacky way I got around this to build was after doing:

brew install libsodium

Latest stable at this point in time being 1.0.18_1, then altering the rebar.config to:

{"darwin", "CFLAGS", "$CFLAGS -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes -I /opt/homebrew/Cellar/libsodium/1.0.18_1/include"},
{"darwin", "CXXFLAGS", "$CXXFLAGS -O3 -finline-functions -Wall"},
{"darwin", "LDFLAGS", "$LDFLAGS -flat_namespace -undefined suppress -L /opt/homebrew/lib -lsodium"},

generichash type spec?

Hi,

I was debating writing a PR but I'm still not sure if this is just me reading this wrong. The typespec on enacl:generichash/2 is:

-spec generichash(iodata(), binary()) -> {ok, binary()} | {error, term()}.

The function itself has the definition:

generichash(HashSize, Message) ->

As far as I can see, the only input that works for HashSize is pos_integer. I've tried a series of variations of iolists and binaries and you can see the results below.

2> enacl:generichash(32, <<"tewst">>).
{ok,<<61,208,165,16,24,163,189,182,68,236,61,135,221,169,
      129,62,180,117,146,23,205,60,77,113,172,116,49,...>>}
3> enacl:generichash([32], <<"tewst">>).
** exception error: bad argument
     in function  enacl_nif:crypto_generichash/3
        called as enacl_nif:crypto_generichash(" ",<<"tewst">>,<<>>)
4> enacl:generichash("32", <<"tewst">>).
** exception error: bad argument
     in function  enacl_nif:crypto_generichash/3
        called as enacl_nif:crypto_generichash("32",<<"tewst">>,<<>>)
5> enacl:generichash(<<"32">>, <<"tewst">>).
** exception error: bad argument
     in function  enacl_nif:crypto_generichash/3
        called as enacl_nif:crypto_generichash(<<"32">>,<<"tewst">>,<<>>)

There are defines for ?CRYPTO_GENERICHASH_BYTES which do appear to be merely integers. Based on this spec, using a constant "work" but makes dialyzer mad:

The call enacl:generichash(32, binary()) breaks the contract (iodata(), binary()) -> {'ok',binary()} | {'error',term()}

I suppose the related question would be, is there a way of accessing these constants from an application using the library?

Typespec for `generichash` advertises `iodata`, but seemingly doesn't work

Steps to reproduce

  1. Use 1.2.1
iex(doma@redacted A> :enacl.generichash(32, ["hello", "world"], "")
** (ArgumentError) argument error
    (enacl 1.2.1) :enacl_nif.crypto_generichash(32, ["hello", "world"], "")
iex(doma@redacted B> :enacl.generichash(32, "helloworld", "")
<<60, 34, 131, 6, 85, 33, 119, 245, 163, 4, 203, 18, 165, 181, 230, 8, 151, 242,
  244, 134, 182, 70, 113, 175, 220, 207, 15, 141, 217, 65, 12, 189>>

Expected behaviour

Outputs A and B are the same.

Erlang dirty schedulers are not actually being used in many cases (if not in all the cases)

The following macro in enacl_nif.c determines if dirty schedulers are to be used or not:

#ifdef ERL_NIF_DIRTY_JOB_CPU_BOUND
#define erl_nif_dirty_job_cpu_bound_macro(a, b, c)                             \
  { a, b, c, ERL_NIF_DIRTY_JOB_CPU_BOUND }
#else
#define erl_nif_dirty_job_cpu_bound_macro(a, b, c)                             \
  { a, b, c }
#endif

The problem with that code is that ERL_NIF_DIRTY_JOB_CPU_BOUND is not actually defined.
ERL_NIF_DIRTY_JOB_CPU_BOUND has always been a enum, so "ifdef" can't be used for checking it.
This leads to the fact that the #else branch works all the time, and dirty schedulers are not actually being used for functions like pwhash where it is absolutely necessary.

Please consider the following PR to fix that problem: #70

Detached ``verify'' verifies attached signatures

Steps to reproduce:

Call enacl:verify_detached on a signature produced by enacl:sign.

Observed behaviour

The signature is successfully verified.

Expected output

Fail with "invalid signature size".

rebar3 compile fails on ubuntu

image

===> Verifying dependencies...
===> Compiling enacl
make: Entering directory '/home/dmann/workspace/enacl/c_src'
cc -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes -fPIC -I /home/dmann/.asdf/installs/erlang/21.0.5/erts-10.0.5/include/ -I /home/dmann/.asdf/installs/erlang/21.0.5/lib/erl_interface-3.10.3/include  -c -o /home/dmann/workspace/enacl/c_src/enacl_nif.o /home/dmann/workspace/enacl/c_src/enacl_nif.c
/home/dmann/workspace/enacl/c_src/enacl_nif.c: In function 'enif_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX':
/home/dmann/workspace/enacl/c_src/enacl_nif.c:1364:31: error: 'crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX' undeclared (first use in this function)
   return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX);
                               ^
/home/dmann/workspace/enacl/c_src/enacl_nif.c:1364:31: note: each undeclared identifier is reported only once for each function it appears in
/home/dmann/workspace/enacl/c_src/enacl_nif.c:1365:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
Makefile:63: recipe for target '/home/dmann/workspace/enacl/c_src/enacl_nif.o' failed
make: *** [/home/dmann/workspace/enacl/c_src/enacl_nif.o] Error 1
make: Leaving directory '/home/dmann/workspace/enacl/c_src'
===> Hook for compile failed!

I have the sodium lib installed on my ubuntu machine using

sudo apt-get install libsodium-dev -y

using

elixir         1.7.2   (set by /home/dmann/.tool-versions)
erlang         21.0.5  (set by /home/dmann/.tool-versions)
nodejs         9.8.0   (set by /home/dmann/.tool-versions)

problem compiling and running with Apple Silicon processor

Hello,

I have erlang compiled on macOS Big Sur with arm64 arch:

Erlang/OTP 23 [erts-11.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [dtrace]

Interactive Elixir (1.11.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :erlang.system_info :system_version
'Erlang/OTP 23 [erts-11.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [dtrace]\n'
iex(2)> :erlang.system_info :system_architecture
'arm-apple-darwin20.1.0'

I changed the rebar.config file to take into account the CFLAGS/CXXFLAGS/LDFLAGS which i think were adapted to Apple Silicon framework:

{"apple-darwin-arm", "CFLAGS", "$CFLAGS -m64 -arch arm64 -fPIC -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes"},
{"apple-darwin-arm", "CXXFLAGS", "$CXXFLAGS -m64 -arch arm64 -fPIC -O3 -finline-functions -Wall"},
{"apple-darwin-arm", "LDFLAGS", "$LDFLAGS -m64 -flat_namespace -undefined suppress -lsodium"},

I checked that the file is compiled for the arm64 with the following:

lipo _build/dev/lib/enacl/priv/enacl_nif.so -info
Non-fat file: _build/dev/lib/enacl/priv/enacl_nif.so is architecture: arm64

I tried to call the sign_detached function as an example to see if it is working, getting the following warn/error message:

12:17:43.957 [warn]  The on_load function for module enacl_nif returned:
{:error,
 {:bad_lib,
  'Failed to find library init function: \'dlsym(0x134e18090, _nif_init): symbol not found\''}}
iex(3)> Sign.hello
** (UndefinedFunctionError) function :enacl_nif.crypto_sign_detached/2 is undefined (module :enacl_nif is not available)
iex(4)> Application.loaded_applications
[
  {:crypto, 'CRYPTO', '4.8'},
  {:logger, 'logger', '1.11.2'},
  {:stdlib, 'ERTS  CXC 138 10', '3.13.2'},
  {:sign, 'sign', '0.1.0'},
  {:iex, 'iex', '1.11.2'},
  {:enacl, 'Erlang libsodium (NaCl) bindings', '1.1.1'},
  {:hex, 'hex', '0.20.6'},
  {:compiler, 'ERTS  CXC 138 10', '7.6.5'},
  {:mix, 'mix', '1.11.2'},
  {:ssl, 'Erlang/OTP SSL application', '10.1'},
  {:inets, 'INETS  CXC 138 49', '7.3'},
  {:ex_unit, 'ex_unit', '1.11.2'},
  {:public_key, 'Public key infrastructure', '1.9.1'},
  {:kernel, 'ERTS  CXC 138 10', '7.1'},
  {:elixir, 'elixir', '1.11.2'},
  {:asn1, 'The Erlang ASN1 compiler version 5.0.14', '5.0.14'}
]

I don't know if i missed some fields in the compile arguments or if it is simply not compatible at the moment.

Thanks for your help

Erratic results using pwhash_str_verify/1 when supplying printable bitstring

When supplying a printable bitstring to pwhash_str_verify/1 the return is sometimes true and sometimes false. Can not replicate this behavior using the binary as returned by pwhash_str/1.

Example:

Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.6.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :enacl.pwhash_str_verify("$argon2id$v=19$m=65536,t=2,p=1$39gbxAJq7dxSB8ycRRwZKg$2x5eXfGN0uSh2ywUe7pU9eb6wKAykhY3Ewu4LrSwt7Y", "foo")
true
iex(2)> :enacl.pwhash_str_verify("$argon2id$v=19$m=65536,t=2,p=1$39gbxAJq7dxSB8ycRRwZKg$2x5eXfGN0uSh2ywUe7pU9eb6wKAykhY3Ewu4LrSwt7Y", "foo")
false
iex(3)> :enacl.pwhash_str_verify("$argon2id$v=19$m=65536,t=2,p=1$39gbxAJq7dxSB8ycRRwZKg$2x5eXfGN0uSh2ywUe7pU9eb6wKAykhY3Ewu4LrSwt7Y", "foo")
true
iex(4)> :enacl.pwhash_str_verify("$argon2id$v=19$m=65536,t=2,p=1$39gbxAJq7dxSB8ycRRwZKg$2x5eXfGN0uSh2ywUe7pU9eb6wKAykhY3Ewu4LrSwt7Y", "foo")
false
iex(5)>

trouble compiling on centos6 (libsodium-16 & libsodium-16-devel installed)

Hi, I am trying to compile this (release 0.17.2 and 0.16.0 tried) on centos 6 with OTP 22. The sodium.h is installed in /usr/include and points to files in /usr/include/sodium (both of which I checked to make sure).

`Erlang/OTP 22 [erts-10.6.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Eshell V10.6.3 (abort with ^G)
1>
`

I keep getting this error:

make: Entering directory /home/xxx/core/_build/default/lib/enacl/c_src'
cc -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes -fPIC -I /usr/lib/erlang/erts-10.6.3/include/ -I /usr/lib/erlang/lib/erl_interface-3.13.1/include -c -o /home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.o /home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c: In function ‘enif_crypto_load’:
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:16: warning: ignoring return value of ‘sodium_init’, declared with attribute warn_unused_result
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c: In function ‘enif_crypto_box’:
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:285: warning: ignoring return value of ‘crypto_box’, declared with attribute warn_unused_result
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c: In function ‘enif_crypto_box_beforenm’:
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:350: warning: ignoring return value of ‘crypto_box_beforenm’, declared with attribute warn_unused_result
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c: In function ‘enif_crypto_kx_SECRETKEYBYTES’:
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1035: error: ‘crypto_kx_SECRETKEYBYTES’ undeclared (first use in this function)
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1035: error: (Each undeclared identifier is reported only once
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1035: error: for each function it appears in.)
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c: In function ‘enif_crypto_kx_PUBLICKEYBYTES’:
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1040: error: ‘crypto_kx_PUBLICKEYBYTES’ undeclared (first use in this function)
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c: In function ‘enif_crypto_kx_SESSIONKEYBYTES’:
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1045: error: ‘crypto_kx_SESSIONKEYBYTES’ undeclared (first use in this function)
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c: In function ‘enif_crypto_kx_keypair’:
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1057: error: ‘crypto_kx_PUBLICKEYBYTES’ undeclared (first use in this function)
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1061: error: ‘crypto_kx_SECRETKEYBYTES’ undeclared (first use in this function)
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1065: warning: implicit declaration of function ‘crypto_kx_keypair’
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c: In function ‘enif_crypto_kx_server_session_keys’:
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1079: error: ‘crypto_kx_PUBLICKEYBYTES’ undeclared (first use in this function)
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1080: error: ‘crypto_kx_SECRETKEYBYTES’ undeclared (first use in this function)
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1085: error: ‘crypto_kx_SESSIONKEYBYTES’ undeclared (first use in this function)
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1093: warning: implicit declaration of function ‘crypto_kx_server_session_keys’
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c: In function ‘enif_crypto_kx_client_session_keys’:
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1107: error: ‘crypto_kx_PUBLICKEYBYTES’ undeclared (first use in this function)
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1108: error: ‘crypto_kx_SECRETKEYBYTES’ undeclared (first use in this function)
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1113: error: ‘crypto_kx_SESSIONKEYBYTES’ undeclared (first use in this function)
/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.c:1121: warning: implicit declaration of function ‘crypto_kx_client_session_keys’
make: *** [/home/xxx/core/_build/default/lib/enacl/c_src/enacl_nif.o] Error 1
make: Leaving directory /home/xxx/core/_build/default/lib/enacl/c_src'

I don't know what I could be doing wrong.

Mixed tabs and spaces inside of files

@jlouis, I'm adding some functions to nif currently(for key exchange) and found what your sources have mixed spaces and tabs inside of the erl and c sources.

Which one style do you prefer? I think it would make sense to add .editorconfig file to this library, so contributors could use it?

on_load_function_failed

Hello,

I am new to Erlang so this is not likely a bug. I have cross compiled this to enacl_nif.so, after having cross compiled libsodium-1.0.18.

The generated lib references libsodium:

$ readelf -a priv/enacl_nif.so |grep NEEDED
 0x00000001 (NEEDED)                     Shared library: [libsodium.so.18]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]

which is available on the target:

# ll /usr/lib/libsodium.so*
-rwxr-xr-x    1 root     root      346.7K Dec 22 22:51 /usr/lib/libsodium.so
-rwxr-xr-x    1 root     root      346.7K Dec 22 22:51 /usr/lib/libsodium.so.18
-rwxr-xr-x    1 root     root      346.7K Dec 22 22:51 /usr/lib/libsodium.so.18.1.1

However when I run my erlang app that uses enacl, here's what I get:

Kernel pid terminated (application_controller) ({application_start_failure,kernel,{{shutdown,{failed_to_start_child,kernel_safe_sup,{on_load_function_failed,enacl_nif}}},{kernel,start,[normal,[]]}}})

It seems it fails to load enacl_nif. Does that ring a bell? Did I do something wrong?

Build machine: x86_64 (linux, ubuntu, elementary os)
Target machine: armv7hf (linux, busybox)

Missed file: sodium.h

Tried to compile project:
make
got error message:

nacl/c_src/aead.c:1:10: fatal error: sodium.h: No such file or directory
#include <sodium.h>
^~~~~~~~~~
compilation terminated.

edoc not working

Hi, I can't create documentation using rebar3 edoc. Tried on two machines, which have a working vsn of Rebar3 and edoc works on other projects.
===> Verifying dependencies...
===> Compiling enacl
make: Entering directory '/home/rrabinovich/prj/eNaCl/enacl/c_src'
make: '/home/rrabinovich/prj/eNaCl/enacl/c_src/../priv/enacl_nif.so' is up to date.
make: Leaving directory '/home/rrabinovich/prj/eNaCl/enacl/c_src'
===> Running edoc for enacl
edoc: skipping source file '/home/rrabinovich/prj/eNaCl/enacl/src/enacl.erl': {'EXIT',
{{badmatch,
{atom,
287,
'?CRYPTO_GENERICHASH_BYTES_MIN'}},
[{edoc_specs,
d2e,
2,
[{file,
"edoc_specs.erl"},
{line,
347}]},
{edoc_specs,
type,
2,
[{file,
"edoc_specs.erl"},
{line,
67}]},
{edoc_extract,
'-get_tags/6-lc$^0/1-0-',
2,
[{file,
[...]},
{line,...}]},
{edoc_extract,
get_tags,
6,
[{file,...},
{...}]},
{edoc_extract,
get_tags,
6,
[{...}|...]},
{edoc_extract,
source1,
5,
[...]},
{edoc_doclet,
source,
9,...},
{lists,
foldl,...}]}}.
edoc: error in doclet 'edoc_doclet': {'EXIT',error}.
===> Failed to generate documentation for app 'enacl'

Exposing specific libsodium algorithms

Would you be open to pull requests that expose specific algorithms for enacl functions? I'm specifically interested in crypto_auth_hmacsha256 and crypto_secretbox_xsalsa20poly1305.

I use these algorithms in kzemek/macaroons for compatibility with rescrv/libmacaroons (and other macaroons implementations, as libmacaroons is the de facto standard). For this, I rolled my own enacl fork (kzemek/enacl_p), but I'd much rather use upstream version than maintain my own code that has to be synchronized.

aead_chacha20poly1305_* argument divergence

The aead_chacha20poly1305_* funcs in terms of parameter order are backwards... The idiom in libsodium is (Message, AdditionalData, Nonce, Key). The current implementation is the opposite (Key, Nonce, AdditonalData, Message).

In addition The do {} while(0) usage in these functions while surely harmless is confusing and IMHO of no use. It is assumed that the author was aiming for single entry/single exit, but it doesn't read well.

I will gladly do a PR for this and include some additional tests (i.e, 1 failure test where there should be 3 to 4).

This would be a breaking change, so wanted to get your thoughts before pushing something up.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.