@ Loup's

Impossible? Like that would stop me.

Monocypher

Monocypher is an easy to use crypto library inspired by libsodium and TweetNaCl. Here are its main selling points:

Documentation

The Mighty Manual.

Source code

Here, shipped with a comprehensive test suite. Alternatively, you can fetch it from github.

Test suite

the test suite. Run thus:

$ tar -xzf monocypher-0.8.tar.gz
$ cd monocypher
$ make
$ ./test.sh

You can modify the makefile to run those tests under LLVM sanitisers (ASan, MSan, and UBSan). You can also check code coverage (which is near-perfect).

More thorough analysis is also possible with Frama-C and the TIS interpreter. See README.md for more details.

Customisation

By default, Monocypher signatures use EdDSA with curve25519 and Blake2b. This is in contrast to the more widespread Ed25519, which uses curve25519 and SHA-512.

Blake2b is faster, more flexible, and harder to misuse than SHA-512. Besides, Argon2i already uses it. Adding SHA-512 just for EdDSA would be inelegant, so I didn't —not by default anyway.

This divergence doesn't prevent future upgrades, nor rigorous testing: Floodyberry's very fast Donna implementation works with a custom hash, and this is used to test Monocypher.

If you want to stick to the official Ed25519 anyway, you can. You need to compile monocypher.c with the preprocessor option -DED25519_SHA512. You must then provide a SHA-512 implementation at link time. You can use Monocypher's own sha512.h and sha512.c.

Current state

Version 1.0. Ready for production.

The test suite is comprehensive. Code coverage has been checked with LLVM's code coverage tool, and is is near perfect. The tests have been run under Valgrind, ASan, MSan, and UBSan (all clean). The most important tests have been run under the TIS interpreter (all clean).

I think we have a crypto library.

speed

The last benchmark showed this on my machine (i5 Skylake laptop). Monocypher, Libsodium, and TweetNaCl are all compiled with GCC, using -O3 -march=native optimisation options.

Comparing with Libsodium
------------------------
Chacha20    : 2971 micro-secs,   14% slower than Libsodium
Poly1305    : 1099 micro-secs,   19% slower than Libsodium
Blake2b     : 2017 micro-secs,   20% slower than Libsodium
Argon2i     : 1911 micro-secs,   29% faster than Libsodium
x25519      :  127 micro-secs,   59% slower than Libsodium
ed25519(sig):  144 micro-secs,   64% slower than Libsodium
ed25519(chk):  279 micro-secs,   49% slower than Libsodium

(Note: the timings are for a 1 megabyte input for symmetric crypto, and a single operation for public key crypto. The timings were obtained by taking the best of 20 runs in each case. They rarely vary by more than 1%)

The comparison with TweetNaCl is simple: Monocypher is just faster.

Comparing with TweetNaCl (apple to orange comparisons are marked with a '!')
------------------------
! Chacha20    : 2970 micro-secs,   44% faster than TweetNaCl's Salsa20
  Poly1305    : 1098 micro-secs, 1010% faster than TweetNaCl
! Blake2b     : 2017 micro-secs,  130% faster than TweetNaCl's Sha512
  Sha512      : 3489 micro-secs,   34% faster than TweetNaCl
  x25519      :  127 micro-secs,  349% faster than TweetNaCl
  ed25519(sig):  144 micro-secs,  976% faster than TweetNaCl
  ed25519(chk):  279 micro-secs, 1007% faster than TweetNaCl
Note: TweetNaCl rejected its own signature, I don't know why

Overall, I think Monocypher strikes a rather nice balance between frugality and performance.

changes since 1.0

changes since 0.8

changes since 0.7

changes since 0.6

changes since 0.5

changes since 0.4

Fun fact: TweetNaCl and ref10 have the same bug. Libsodium have corrected the issue, though.

For those who don't comprehend the magnitude of this madness (I didn't until 2 hours ago), yes, the expression -1 << 3 is undefined in C. This is explained in section 6.5.7(§4) of the C11 standard.

changes since 0.3

changes since 0.2

No incompatible change.

changes since 0.1

Future work

I think I'm pretty much done.

The next thing to do, I believe, are bindings to other languages. Except for Rust. I believe Monocypher should be ported to Rust (as in, re-written), so it can benefit from its security guarantees.