CRYPTO_POLY1305(3MONOCYPHER) | 3MONOCYPHER | CRYPTO_POLY1305(3MONOCYPHER) |
crypto_poly1305
,
crypto_poly1305_init
,
crypto_poly1305_update
,
crypto_poly1305_final
—
#include <monocypher.h>
void
crypto_poly1305
(uint8_t mac[16],
const uint8_t *message, size_t
message_size, const uint8_t key[32]);
void
crypto_poly1305_init
(crypto_poly1305_ctx
*ctx, const uint8_t key[32]);
void
crypto_poly1305_update
(crypto_poly1305_ctx
*ctx, const uint8_t *message,
size_t message_size);
void
crypto_poly1305_final
(crypto_poly1305_ctx
*ctx, uint8_t mac[16]);
Poly1305 is a low-level primitive. Consider using authenticated encryption, implemented by crypto_lock(3monocypher).
The arguments are:
crypto_poly1305
() produces a message authentication code
for the given message and authentication key. To verify the integrity of a
message, use
crypto_verify16(3monocypher) to
compare the received MAC to the output mac.
crypto_poly1305_init
() initialises a context.
key should be wiped once the context is initialised.
Then crypto_poly1305_update
() authenticates the
message chunk by chunk. Once the message is entirely processed,
crypto_poly1305_final
() yields the message
authentication code.
arc4random_buf
(), which fills the given buffer with
cryptographically secure random bytes. If
arc4random_buf
() does not exist on your system, see
intro(3monocypher) for advice about how to
generate cryptographically secure random bytes.
To authenticate a message:
const uint8_t msg[ 5] = "Lorem"; /* Message to authenticate */ uint8_t key[32]; /* Random secret key (use only once) */ uint8_t mac[16]; /* Message authentication code (MAC) */ arc4random_buf(key, 32); crypto_poly1305(mac, msg, 5, key); /* Wipe the key */ crypto_wipe(key, 32);
To verify the above message:
const uint8_t msg [ 5] = "Lorem"; /* Message to verify */ uint8_t key [32]; /* The above key */ const uint8_t mac [16]; /* The above MAC */ uint8_t real_mac[16]; /* The actual MAC */ crypto_poly1305(real_mac, msg, 5, key); /* Wipe the key */ crypto_wipe(key, 32); if (crypto_verify16(mac, real_mac)) { /* Corrupted message, abort processing */ } else { /* Genuine message */ } /* The real mac is secret. Wipe it */ crypto_wipe(real_mac, 16);
Incremental authentication:
const uint8_t msg[500]= {1}; /* Message to authenticate */ uint8_t key[ 32]; /* Random secret key (use only once) */ uint8_t mac[ 16]; /* Message authentication code (MAC) */ crypto_poly1305_ctx ctx; arc4random_buf(key, 32); crypto_poly1305_init(&ctx, key); /* Wipe the key */ crypto_wipe(key, 32); for (int i = 0; i < 500; i += 100) { crypto_poly1305_update(&ctx, msg, 100); } crypto_poly1305_final(&ctx, mac);
crypto_poly1305_init
(),
crypto_poly1305_update
(), and
crypto_poly1305_final
() functions first appeared in
Monocypher 0.1. crypto_poly1305
() first appeared in
Monocypher 1.1.0.
The only practical source for the authentication key is a chunk of the encryption stream used to encrypt the message. That chunk must be dedicated to the authentication key: if it is reused to encrypt the message itself, the attacker may recover that chunk by guessing the message then forge arbitrary messages.
To get this right, you need a session key, a unique nonce, and a stream cipher. Generate a stream with the session key and nonce. Take the first 32 bytes of that stream as your authentication key, then use the rest of the stream to encrypt your message. This is the approach used by crypto_lock_aead(3monocypher).
The authentication key should be wiped with crypto_wipe(3monocypher) after use.
The incremental interface automatically wipes its context when finished, so users do not need to do it themselves.
June 11, 2021 | Debian |