crypto_lock_init,
crypto_lock_aead_auth,
crypto_lock_update,
crypto_lock_final,
crypto_unlock_init,
crypto_unlock_aead_auth,
crypto_unlock_update,
crypto_unlock_final,
crypto_lock_auth,
crypto_lock_encrypt —
incremental authenticated encryption with
additional data
#include
<monocypher.h>
void
crypto_lock_init(
crypto_lock_ctx
*ctx,
const uint8_t key[32],
const uint8_t nonce[24]);
void
crypto_lock_aead_auth(
crypto_lock_ctx
*ctx,
const uint8_t *ad,
size_t ad_size);
void
crypto_lock_update(
crypto_lock_ctx
*ctx,
uint8_t *cipher_text,
const uint8_t *plain_text,
size_t text_size);
void
crypto_lock_final(
crypto_lock_ctx
*ctx,
uint8_t mac[16]);
void
crypto_unlock_init(
crypto_unlock_ctx
*ctx,
const uint8_t key[32],
const uint8_t nonce[24]);
void
crypto_unlock_aead_auth(
crypto_unlock_ctx
*ctx,
const uint8_t *ad,
size_t ad_size);
void
crypto_unlock_update(
crypto_unlock_ctx
*ctx,
uint8_t *plain_text,
const uint8_t *cipher_text,
size_t text_size);
int
crypto_unlock_final(
crypto_unlock_ctx
*ctx,
const uint8_t mac[16]);
void
crypto_lock_auth(
crypto_lock_ctx
*ctx,
const uint8_t *ad,
size_t ad_size);
void
crypto_lock_encrypt(
crypto_lock_ctx
*ctx,
uint8_t *cipher_text,
const uint8_t *plain_text,
size_t text_size);
These functions are variants of
crypto_lock(3monocypher),
crypto_unlock(3monocypher),
crypto_aead_lock(3monocypher)
and
crypto_aead_unlock(3monocypher).
Prefer those simpler functions if possible.
This incremental interface can be used to encrypt and decrypt messages too large
to fit in a single buffer. The arguments are the same as described for the
direct interface described in
crypto_lock(3monocypher).
Encryption requires four steps:
- Initialise a context with
crypto_lock_init().
- Authenticate additional data, if any, with
crypto_lock_aead_auth().
- Encrypt and authenticate some data with
crypto_lock_update().
- Generate the MAC with
crypto_lock_final().
Decryption also requires four steps:
- Initialise a context with
crypto_unlock_init().
- Verify additional data, if any, with
crypto_unlock_aead_auth().
- Decrypt and verify some data with
crypto_unlock_update().
- Verify the MAC with
crypto_unlock_final().
crypto_lock_encrypt() encrypts or decrypts data
without authenticating it. It is meant as a
building block. Used with
crypto_lock_auth(), it
enables various AEAD constructions. Most users do not need either of them.
Prefer
crypto_lock_update() and
crypto_unlock_update() instead.
crypto_lock_init(),
crypto_unlock_init(),
crypto_lock_auth(),
crypto_lock_encrypt(),
crypto_lock_aead_auth(),
crypto_unlock_aead_auth(),
crypto_lock_update(),
crypto_unlock_update(), and
crypto_lock_final() return nothing. They cannot
fail.
crypto_unlock_final() returns 0 on success or -1 if
the message was corrupted. Corruption can be caused by transmission errors,
programmer error, or an attacker's interference.
Always check the return value.
Encryption:
const uint8_t key [ 32]; /* Session key */
const uint8_t nonce [ 32]; /* Unique per session key */
const uint8_t ad [500]; /* Optional additional data */
const uint8_t plain_text [500]; /* Secret message */
uint8_t cipher_text[500]; /* Encrypted message */
uint8_t mac [ 16]; /* Message authentication code */
/* Set up initial context */
crypto_lock_ctx ctx;
crypto_lock_init(&ctx, key, nonce);
/* Wipe the key if it is no longer needed */
crypto_wipe(key, 32);
/* Authenticate additional data */
for (size_t i = 0; i < 500; i += 100) {
crypto_lock_aead_auth(&ctx, ad + i, 100);
}
/* Encrypt message */
for (size_t i = 0; i < 500; i += 100) {
crypto_lock_update(&ctx, cipher_text + i, plain_text + i, 100);
/* Wipe the secret message if it is no longer needed */
crypto_wipe(plain_text + i, 100);
}
/* Produce the MAC */
crypto_lock_final(&ctx, mac);
To decrypt the above:
const uint8_t key [ 32]; /* Session key */
const uint8_t nonce [ 32]; /* Unique per session key */
const uint8_t mac [ 16]; /* Transmitted MAC */
const uint8_t ad [500]; /* Optional additional data */
const uint8_t cipher_text[500]; /* Encrypted message */
uint8_t plain_text [500]; /* Secret message */
/* Set up initial context */
crypto_unlock_ctx ctx;
crypto_unlock_init(&ctx, key, nonce);
/* Wipe the key if it is no longer needed */
crypto_wipe(key, 32);
/* Verify additional data */
for (size_t i = 0; i < 500; i += 100) {
crypto_unlock_aead_auth(&ctx, ad + i, 100);
}
/* Decrypt message */
for (size_t i = 0; i < 500; i += 100) {
crypto_unlock_update(&ctx, plain_text + i, cipher_text + i, 100);
}
/* Check the MAC */
if (crypto_unlock_final(&ctx, mac)) {
/* Corrupted message, abort processing */
} else {
/* Genuine message */
}
/* Wipe the secret message if it is no longer needed */
crypto_wipe(plain_text, 500);
In-place encryption without additional data:
const uint8_t key [ 32]; /* Session key */
const uint8_t nonce [ 32]; /* Unique per session key */
uint8_t text [500]; /* Message */
uint8_t mac [ 16]; /* Message authentication code */
/* Set up initial context */
crypto_lock_ctx ctx;
crypto_lock_init(&ctx, key, nonce);
/* Wipe the key if it is no longer needed */
crypto_wipe(key, 32);
/* Encrypt message */
for (size_t i = 0; i < 500; i += 100) {
crypto_lock_update(&ctx, text + i, text + i, 100);
}
/* Produce the MAC */
crypto_lock_final(&ctx, mac);
crypto_aead_lock(3monocypher),
crypto_aead_unlock(3monocypher),
crypto_key_exchange(3monocypher),
crypto_lock(3monocypher),
crypto_unlock(3monocypher),
crypto_wipe(3monocypher),
intro(3monocypher)
These functions implement the XChacha20 (encryption) and Poly1305 (MAC)
primitives. Chacha20 and Poly1305 are described in RFC 7539. 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).
Messages are not verified until the call to
crypto_unlock_final(). Make sure to call it and
check the return value
before processing the
message. Messages may be stored before they are verified, but they cannot be
trusted. Processing untrusted messages increases the attack surface of the
system. Doing so securely is hard. Do not process messages before calling
crypto_unlock_final().
- crypto_unlock_ctx is an
alias to crypto_lock_ctx.
- crypto_unlock_init() is an
alias to crypto_lock_init().
- crypto_lock_aead_auth() and
crypto_unlock_aead_auth() are aliases to
crypto_lock_auth().
The incremental interface is roughly three times slower than the direct
interface at identifying corrupted messages. This is because the incremental
interface works in a single pass and has to interleave decryption and
verification. Users who expect a high corruption rate may want to avoid
it.