Secret-key single-message authentication using Poly1305

One-time authentication in Sodium uses Poly1305, a Wegman-Carter authenticator designed by D. J. Bernstein.

Poly1305 takes a 32-byte, one-time key and a message and produces a 16-byte tag that authenticates the message such that an attacker has a negligible chance of producing a valid tag for a inauthentic message.

Poly1305 keys have to be:

  • secret. An attacker can compute a valid authentication tag for any message, for any given key. The security of Poly1305 relies on the fact that attackers don't know the key being used to compute the tag. This implies that they have to be:
  • unpredictable. Do not use timestamps or counters.
  • unique. Never reuse a key. A new key is required for every single message.

The standard way to use Poly1305's is to derive a dedicated subkey from a (key, nonce) tuple, for example by taking the first bytes generated by a stream cipher.

Due to its output size, Poly1305 is recommended for online protocols, exchanging many small messages, rather than for authenticating very large files.

Finally, Poly1305 is not a replacement for a hash function.

Single-part example

#define MESSAGE ((const unsigned char *) "Data to authenticate")
#define MESSAGE_LEN 20

unsigned char out[crypto_onetimeauth_BYTES];
unsigned char key[crypto_onetimeauth_KEYBYTES];

randombytes_buf(key, sizeof key);
crypto_onetimeauth(out, MESSAGE, MESSAGE_LEN, key);

if (crypto_onetimeauth_verify(out, MESSAGE, MESSAGE_LEN, key) != 0) {
    /* message forged! */
}

Multi-part example

#define MESSAGE1 ((const unsigned char *) "Multi-part")
#define MESSAGE1_LEN 10
#define MESSAGE2 ((const unsigned char *) "data")
#define MESSAGE2_LEN 4

unsigned char out[crypto_onetimeauth_BYTES];
unsigned char key[crypto_onetimeauth_KEYBYTES];
crypto_onetimeauth_state state;

randombytes_buf(key, sizeof key);

crypto_onetimeauth_init(&state, key);
crypto_onetimeauth_update(&state, MESSAGE1, MESSAGE1_LEN);
crypto_onetimeauth_update(&state, MESSAGE2, MESSAGE2_LEN);
crypto_onetimeauth_final(&state, out);

Usage

Single-part interface

int crypto_onetimeauth(unsigned char *out, const unsigned char *in,
                       unsigned long long inlen, const unsigned char *k);

The crypto_onetimeauth() function authenticates a message in whose length is inlen using a secret key k (crypto_onetimeauth_KEYBYTES bytes) and puts the authenticator into out (crypto_onetimeauth_BYTES bytes).

int crypto_onetimeauth_verify(const unsigned char *h, const unsigned char *in,
                              unsigned long long inlen, const unsigned char *k);

The crypto_onetimeauth_verify() function verifies, in constant time, that h is a correct authenticator for the message in whose length is inlen bytes, using the secret key k.

It returns -1 is the verification fails, or 0 on success.

Multi-part (streaming) interface

int crypto_onetimeauth_init(crypto_onetimeauth_state *state,
                            const unsigned char *key);
int crypto_onetimeauth_update(crypto_onetimeauth_state *state,
                              const unsigned char *in,
                              unsigned long long inlen);
int crypto_onetimeauth_final(crypto_onetimeauth_state *state,
                             unsigned char *out);

The crypto_onetimeauth_init() function initializes a structure pointed by state using a key key.

crypto_onetimeauth_update() can then be called more than one in order to compute the authenticator from sequential chunks of the message.

Finally, crypto_onetimeauth_final() puts the authenticator into out.

The state must be initialized with crypto_onetimeauth_init() before updating or finalizing it.

After crypto_onetimeauth_final() returns, the state should not be used any more, unless it is reinitialized using crypto_onetimeauth_init().

Constants

  • crypto_onetimeauth_BYTES
  • crypto_onetimeauth_KEYBYTES

Data types

  • crypto_onetimeauth_state

Algorithm details

  • Poly1305

results matching ""

    No results matching ""