Monocypher is a cryptographic library. It provides functions for authenticated encryption, hashing, password key derivation, key exchange, and public key signatures.
crypto_unlock() use the Chacha20 cipher and the
Poly1305 one time authenticator. An
incremental interface is also available.
Chacha20 is a stream cipher based on a cryptographic hash function. It runs efficiently on a wide variety of hardware, and unlike AES naturally runs in constant time on all hardware.
Poly1305 is a one time authenticator, derived from Carter & Wegman universal hashing. It is very fast and very simple.
crypto_blake2b() implements the Blake2b hash. Blake2b combines the
security of SHA-3 and the speed of MD5. It is immune to length
extension attacks and provides a keyed mode that makes it a safe, easy
to use authenticator.
crypto_argon2i() implements the Argon2i resource intensive hash
algorithm. Argon2 won the password hashing competition in 2015. Unlike
Scrypt, Argon2i is immune to timing attacks.
crypto_key_exchange() implements X25519, an elliptic curve Diffie
Hellman key exchange algorithm based on Curve25519. X25519 derives a
shared secret from two private/public key pairs. It is fast, simple,
and relatively easy to implement securely.
crypto_check() implement EdDSA, with Curve25519
and Blake2b. This is the same as the more famous Ed25519, with SHA-512
replaced by the faster and more secure Blake2b. Ed25519 (EdDSA with
SHA-512), is supported as a compilation option.
compare buffers in constant time. They should be used to compare
secrets to prevent timing attacks.
crypto_wipe() wipes a buffer. It is meant to erase secrets when they
are no longer needed, to reduce the chances of leaks.
Using cryptography securely is difficult. Flaws that never manifest under normal use might be exploited by a clever adversary. Cryptographic libraries are easy to misuse. Even Monocypher allows a number of fatal mistakes.
Users should follow a formal introduction to cryptography. We currently recommend the https://www.crypto101.io/ online course.
Random number generation
Use the facilities of your operating system. Avoid user space random number generators. They are easy to misuse, which has lead to countless vulnerabilities in the past. For instance, the random stream may be repeated if one is not careful with multi-threading, and forward secrecy is lost without proper key erasure.
Different system calls are available on different systems:
- Recent versions of Linux (glibc >= 2.25, Linux >= 3.17), provide
linux/random.h. Do not set any flag.
- BSD provides
bsd/stdlib.h. This is easier to use than
- Windows provides
/dev/urandom special file may be used on systems that do not
provide an easy to use system call. Be careful though, being a file
/dev/urandom hard to use correctly and securely. Reads may be
interrupted, and more attacks are possible on a file than on a system
Monocypher runs in "constant time". There is no flow from secrets to timings. No secret dependent indices, no secret dependent branches. Nevertheless, there are a couple important caveats.
Comparing secrets should be done with constant-time comparison
functions, such as
crypto_verify64(). Do not use standard comparison functions. They
tend to stop as soon as a difference is spotted. In many cases, this
enables attackers to recover the secrets and destroy all security.
The Poly1305 authenticator, X25519, and EdDSA use multiplication. Some older processors do not multiply in constant time. If the target platform is something other than x86, x86_64, ARM or ARM64, double check how it handles multiplication.
Encryption does not hide the length of the input plaintext. Most compression algorithms work by using fewer bytes to encode previously seen data or common characters. If an attacker can add data to the input before it is compressed and encrypted, they can observe changes to the ciphertext length to recover secrets from the input. Researchers have demonstrated an attack on HTTPS to steal session cookies when compression is enabled, dubbed "CRIME".
Long term secrets cannot be expected to stay safe indefinitely. Users may reveal them by mistake, or the host computer might have a vulnerability and be compromised. To mitigate this problem, some protocols guarantee that past messages are not compromised even if the long term keys are. This is done by generating temporary keys, then encrypting messages with them.
In general, secrets that went through a computer should not be compromised when this computer is stolen or infected at a later point.
A first layer of defence is to explicitly wipe secrets as soon as they
are no longer used. Monocypher already wipes its own temporary buffers,
and contexts are erased with the
crypto_*_final() functions. The
secret keys and messages however are the responsibility of the user.
crypto_wipe() to erase them.
A second layer of defence is to ensure those secrets are not swapped to disk while they are used. There are several ways to do this. The most secure is to disable swapping entirely. Doing so is recommended on sensitive machines. Another way is to encrypt the swap partition (this is less safe). Finally, swap can be disabled locally—this is often the only way.
UNIX systems can disable swap for specific buffers with
disable swap for the whole process with
mlockall(). Windows can
disable swap for specific buffers with
Core dumps cause similar problems. Disable them. Also beware of
suspend to disk (deep sleep mode), which writes all RAM to disk
regardless of swap policy, as well as virtual machine snapshots.
Erasing secrets with
crypto_wipe() is often the only way to mitigate
Monocypher is a C library. C is notoriously unsafe. Using Monocypher incorrectly can trigger undefined behaviour. This can lead to data corruption, data theft, or even arbitrary code execution.
Consider binding to a safe language if possible.