Monocypher is an easy to use crypto library inspired by libsodium and TweetNaCl. Here are its main selling points:
Secure. Monocypher uses state of the art primitives (Chacha20, Poly1305, Blake2b, Argon2i, X25519, and EdDSA), and is immune to timing attacks.
Small. Monocypher is a little over 1300 lines of code (counted with sloccount), small enough to allow comprehensive audits.
Easy to deploy. Just put
monocypher.hin your project. They compile as C99, C11, or C++, and have zero dependency.
Easy to use. The API is small, consistent, and cannot fail on correct input.
Fast. The chosen primitives are fast to begin with, and performance wasn't needlessly sacrificed. While Monocypher can't compete with libsodium's optimised assembly, it remains much faster than TweetNaCl.
The Mighty Manual.
Here, shipped with a comprehensive test suite. Alternatively, you can fetch it from github.
the test suite. Run thus:
$ tar -xzf monocypher-1.0.1.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.
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. Argon2i already uses Blake2b. 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
Version 1.0.1 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.
I benchmarked Monocypher on my laptop (Intel i5 Skylake) with GCC,
-O3 -march=native optimisation options. Symmetric crypto uses
big messages (1Mb). Smaller messages (down to 1kb) have a slightly
Chacha20 : 357 Mb/s Poly1305 : 1219 Mb/s Auth'd encryption: 277 Mb/s Blake2b : 522 Mb/s Argon2i : 514 Mb/s (3 passes) x25519 : 7785 exchanges per second EdDSA(sign) : 6907 signatures per second EdDSA(check) : 3569 checks per second
While you should test the speed on your target platform, I believe Monocypher will be fast enough for all but the most demanding applications (like, Google scale).
changes since 1.0
- Optimised the loading and unloading code of the symmetric crypto (Blake2b, sha512, Chacha20, and Poly1305).
- Fused self contained tests together for easier analysis with Frama-C and the TIS interpreter.
changes since 0.8
crypto_chacha20_x_init, for consistency reasons (snake case everywhere).
- Fixed signed integer overflow detected by UBSan.
- Doubled the speed of EdDSA by performing the scalar product in Montgomery space.
changes since 0.7
Added about a hundred lines of code to improve performance of public key cryptography. Diffie-Hellman is now 20% faster than before. (The effects are less pronounces for EdDSA).
Added random self-consistency tests.
Added a speed benchmark against libsodium. Requires POSIX timers. You might want to adjust the compilation option to make it work (see the beginning of the makefile). To run the benchmark, run the following:
$ make speed $ ./speed
changes since 0.6
- Slightly changed the authenticated encryption API. Functions are now all in "detached" mode. The reason is better support for authenticated encryption without additional data.
- Rewrote Blake2b from spec, so it can use the same licence as everything else.
- Added random tests that compare Monocypher with libsodium and ed25519-donna.
- Added explicit support for Frama-C analysis (this doesn't affect the source code)
changes since 0.5
- Fixed incorrect poly1305 output on empty messages. (Found by Mike Pechkin.)
changes since 0.4
- Fixed many undefined behaviours in curve25519, that occur whenever we perform a left shift on a signed negative integer. It doesn't affect the generated code, but you never know. (Found with Frama-C by André Maroneze.)
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
Fixed critical bug causing Argon2i to fail whenever it uses more than 512 blocks. It was reading uninitialised memory, and the results were incorrect. (Found by Mike Pechkin.)
Fixed an undefined behaviour in curve25519 (
fe_tobytes()). It was accessing uninitialised memory, before throwing it away. It didn't affect the compiled code nor the results, but you never know. (Found with Frama-C by André Maroneze.)
changes since 0.2
No incompatible change.
Got the invariants of poly1305 right, put them in the comments. There was no bug, but that was lucky (turned out the IETF test vectors were designed to trigger the bugs I was afraid of).
Simplified poly1305 finalisation (replaced conditional subtraction by a carry propagation).
- Made a few cosmetic changes here and there.
changes since 0.1
- Public interface significantly reworked. Removed redundant, hard to mess up constructions.
- Added AEAD.
- Sped up curve25519 by a factor of more than 6 (switched to ref10 arithmetic)
- Added various test vectors, completed the consistency tests.
I think I'm pretty much done.
The next thing to do, I believe, are bindings to other languages. Except maybe for Rust: a complete rewrite in Rust would leverage its security guarantees.