.\" This file is dual-licensed. Choose whichever you want. .\" .\" The first licence is a regular 2-clause BSD licence. The second licence .\" is the CC-0 from Creative Commons. It is intended to release Monocypher .\" to the public domain. The BSD licence serves as a fallback option. .\" .\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0 .\" .\" ---------------------------------------------------------------------------- .\" .\" Copyright (c) 2017-2019 Loup Vaillant .\" Copyright (c) 2018 Michael Savage .\" Copyright (c) 2017, 2019-2020 Fabio Scotoni .\" All rights reserved. .\" .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions are .\" met: .\" .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the .\" distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS .\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT .\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR .\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT .\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, .\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT .\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE .\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" ---------------------------------------------------------------------------- .\" .\" Written in 2017-2020 by Loup Vaillant, Michael Savage and Fabio Scotoni .\" .\" To the extent possible under law, the author(s) have dedicated all copyright .\" and related neighboring rights to this software to the public domain .\" worldwide. This software is distributed without any warranty. .\" .\" You should have received a copy of the CC0 Public Domain Dedication along .\" with this software. If not, see .\" .\" .Dd March 31, 2020 .Dt CRYPTO_CHACHA20 3MONOCYPHER .Os .Sh NAME .Nm crypto_chacha20 , .Nm crypto_chacha20_ctr , .Nm crypto_xchacha20 , .Nm crypto_xchacha20_ctr .Nd Chacha20 and XChacha20 encryption functions .Sh SYNOPSIS .In monocypher.h .Ft void .Fo crypto_chacha20 .Fa "uint8_t *cipher_text" .Fa "const uint8_t *plain_text" .Fa "size_t text_size" .Fa "const uint8_t key[32]" .Fa "const uint8_t nonce[8]" .Fc .Ft void .Fo crypto_xchacha20 .Fa "uint8_t *cipher_text" .Fa "const uint8_t *plain_text" .Fa "size_t text_size" .Fa "const uint8_t key[32]" .Fa "const uint8_t nonce[24]" .Fc .Ft uint64_t .Fo crypto_chacha20_ctr .Fa "uint8_t *cipher_text" .Fa "const uint8_t *plain_text" .Fa "size_t text_size" .Fa "const uint8_t key[32]" .Fa "const uint8_t nonce[8]" .Fa "uint64_t ctr" .Fc .Ft uint64_t .Fo crypto_xchacha20_ctr .Fa "uint8_t *cipher_text" .Fa "const uint8_t *plain_text" .Fa "size_t text_size" .Fa "const uint8_t key[32]" .Fa "const uint8_t nonce[24]" .Fa "uint64_t ctr" .Fc .Sh DESCRIPTION These functions provide an interface for the Chacha20 encryption primitive. .Pp Chacha20 is a low-level primitive. Consider using authenticated encryption, implemented by .Xr crypto_lock 3monocypher . .Pp The arguments are: .Bl -tag -width Ds .It Fa key A 32-byte secret key. .It Fa nonce An 8-byte or 24-byte number, used only once with any given key. It does not need to be secret or random, but it does have to be unique. Repeating a nonce with the same key reveals the XOR of two different messages, which allows decryption. 24-byte nonces can be selected at random. 8-byte nonces .Em cannot . They are too small, and the same nonce may be selected twice by accident. See .Xr intro 3monocypher for advice about generating random numbers (use the operating system's random number generator). .It Fa plain_text The message to encrypt. It is allowed to be .Dv NULL , in which case it will be interpreted as an all zero input. .Fa cipher_text will then contain the raw Chacha20 stream. .It Fa cipher_text The encrypted message. .It Fa text_size Length of both .Fa plain_text and .Fa cipher_text , in bytes. .It Fa ctr The number of 64-byte blocks since the beginning of the stream. .El .Pp The .Fa key and .Fa nonce buffers may overlap. .Fa plain_text and .Fa cipher_text must either be the same buffer (for in-place encryption), or non-overlapping. .Pp .Fn crypto_chacha20 performs a Chacha20 operation. It uses an 8-byte nonce, which is too small to be selected at random. Use a message counter as a nonce instead. .Pp .Fn crypto_xchacha20 performs an XChacha20 operation. It uses a 24-byte nonce, which is large enough to be selected at random. .Pp .Fn crypto_xchacha20 is recommended over .Fn crypto_chacha20 . The ability to use random nonces makes it easier to use securely, and the performance hit is often negligible in practice. .Pp The .Fn crypto_chacha20 and .Fn crypto_xchacha20 encrypt .Fa plain_text by XORing it with a pseudo-random stream of numbers, seeded by the provided .Fa key and .Fa nonce . .Pp Since XOR is its own inverse, decryption is the same operation as encryption. To decrypt the cipher text, .Dq encrypt it again with the same key and nonce. You will likely want to wipe the key when you are done with encryption or decryption. Use .Xr crypto_wipe 3monocypher to wipe them. .Pp The .Fa plain_text pointer is allowed to be .Dv NULL , in which case it will be interpreted as an all zero input. This is useful as a user space random number generator. While .Sy this should not be used as a random number generator for secrets , for which the operating system random number generator should be preferred, it can be handy outside of a security context. Deterministic procedural generation and reproducible property-based tests come to mind. Additionally, it .Em can be used to generate large amounts of random-looking data quickly, for example to generate padding. .Pp The .Fn crypto_chacha20_ctr and .Fn crypto_xchacha20_ctr perform a Chacha20 or XChacha20 encryption, respectively, starting the stream at the block .Fa ctr (which is the byte .Ql ctr \(mu 64 ) . This can be used to encrypt (or decrypt) part of a long message, or to implement some AEAD constructions such as the one described in RFC 8439. Be careful when using this not to accidentally reuse parts of the random stream as that would destroy confidentiality. .Sh RETURN VALUES .Fn crypto_chacha20 and .Fn crypto_xchacha20 return nothing. .Fn crypto_chacha20_ctr and .Fn crypto_xchacha20_ctr functions return the next .Fa ctr to use with the same key and nonce values; this is always .Fa text_size divided by 64; plus one if there was a remainder. .Sh EXAMPLES The following examples assume the existence of .Fn arc4random_buf , which fills the given buffer with cryptographically secure random bytes. If .Fn arc4random_buf does not exist on your system, see .Xr intro 3monocypher for advice about how to generate cryptographically secure random bytes. .Pp Simple encryption: .Bd -literal -offset indent uint8_t key [ 32]; /* Secret random key */ uint8_t nonce [ 24]; /* Unique nonce (possibly random) */ uint8_t plain_text [500] = {1}; /* Secret message */ uint8_t cipher_text[500]; /* Encrypted message */ arc4random_buf(key, 32); arc4random_buf(nonce, 24); crypto_xchacha20(cipher_text, plain_text, 500, key, nonce); /* Wipe secrets if they are no longer needed */ crypto_wipe(key, 32); crypto_wipe(plain_text, 500); .Ed .Pp To decrypt the above: .Bd -literal -offset indent uint8_t key [ 32]; /* Same key as above */ const uint8_t nonce [ 24]; /* Same nonce as above */ uint8_t plain_text [500]; /* Message to decrypt */ uint8_t cipher_text[500]; /* Secret message */ crypto_xchacha20(cipher_text, plain_text, 500, key, nonce); /* Wipe secrets if they are no longer needed */ crypto_wipe(key, 32); /* The plain text likely needs to be processed before you wipe it */ crypto_wipe(plain_text, 12); .Ed .Pp Incremental encryption (in blocks of 64 bytes): .Bd -literal -offset indent uint8_t key [ 32]; /* Secret random key */ uint8_t nonce [ 24]; /* Unique nonce (possibly random) */ uint8_t plain_text [500]; /* Secret message */ uint8_t cipher_text[500]; /* Encrypted message */ uint64_t ctr = 0; /* Block counter */ unsigned int i; arc4random_buf(key, 32); arc4random_buf(nonce, 24); for(i = 0; i < 500; i += 64) { ctr = crypto_xchacha20_ctr(cipher_text+i, plain_text+i, 64, key, nonce, ctr); } /* Process data that didn't fit into 64 byte pieces */ crypto_xchacha20_ctr(cipher_text+500-(i-64), plain_text+500-(i-64), 500-(i-64), key, nonce, ctr); /* Wipe secrets if they are no longer needed */ crypto_wipe(key, 32); crypto_wipe(plain_text, 500); .Ed .Pp Encryption by jumping around (do not do that, this is only meant to show how .Fn crypto_xchacha20_ctr works): .Bd -literal -offset indent uint8_t key [ 32]; /* Secret random key */ uint8_t nonce [ 24]; /* Unique nonce (possibly random) */ uint8_t plain_text [500] = {1}; /* Message to be encrypted */ uint8_t cipher_text[500]; /* Will be the encrypted message */ arc4random_buf(key, 32); arc4random_buf(nonce, 24); /* Encrypt the second part of the message first... */ crypto_xchacha20_ctr(cipher_text + (3 * 64), plain_text + (3 * 64), 500 - (3 * 64), key, nonce, 3); /* ...then encrypt the first part */ crypto_xchacha20_ctr(cipher_text, plain_text, 3 * 64, key, nonce, 0); /* Wipe secrets if they are no longer needed */ crypto_wipe(key, 32); crypto_wipe(plain_text, 500); .Ed .Sh SEE ALSO .Xr crypto_ietf_chacha20 3monocypher , .Xr crypto_lock 3monocypher , .Xr crypto_wipe 3monocypher , .Xr intro 3monocypher .Sh STANDARDS These functions implement Chacha20 and XChacha20. Chacha20 is described in: .Rs .%A Daniel J. Bernstein .%J SASC 2008 \(en The State of the Art of Stream Ciphers .%P pp. 273\(en278 .%T ChaCha, a variant of Salsa20 .Re The nonce and counter sizes were modified in RFC 8439. XChacha20 derives from Chacha20 the same way XSalsa20 derives from Salsa20, and benefits from the same security reduction (proven secure as long as Chacha20 itself is secure). .Sh HISTORY .Fn crypto_chacha20 , .Fn crypto_chacha20_ctr , .Fn crypto_xchacha20 , and .Fn crypto_xchacha20_ctr were added in Monocypher 3.0.0. They replace .Fn crypto_chacha20_encrypt , .Fn crypto_chacha20_init , .Fn crypto_chacha20_stream , .Fn crypto_chacha20_x_init , and .Fn crypto_chacha20_set_ctr that were deprecated in Monocypher 3.0.0. .Sh SECURITY CONSIDERATIONS .Ss Encrypted does not mean secure Chacha20 only protects against eavesdropping, not forgeries. Most applications need protection against forgeries to be properly secure. To ensure the integrity of a message, use Blake2b in keyed mode, or authenticated encryption; see .Xr crypto_blake2b 3monocypher and .Xr crypto_lock 3monocypher . .Ss Nonce reuse Repeating a nonce with the same key exposes the XOR of two or more plain text messages, effectively destroying confidentiality. .Pp For the same reason, .Sy do not select small nonces at random . The .Fn crypto_chacha20 nonce spans only 64 bits, which is small enough to trigger accidental reuses. A message counter should be used instead. If multiple parties send out messages, Each can start with an initial nonce of 0, 1 .. n-1 respectively, and increment them by n for each new message. Make sure the counters never wrap around. .Ss Secure random number generation Do not use these functions as a cryptographic random number generator. Always use the operating system's random number generator for cryptographic purposes, see .Xr intro 3monocypher . .Ss Protection against side channels Secrets should not dwell in memory longer than needed. Use .Xr crypto_wipe 3monocypher to erase secrets you no longer need. For Chacha20, this means the key and in some cases the plain text itself.