Public-key Authenticated Encryption#

Public-key authenticated encryption (Crypto Box).

This module provides a combined- and detached API with and without precomputation. Please make sure that you use the correct pairs of functions to encrypt and decrypt messages as these APIs are not meant to be mixed.

Furthermore, NaCl supports in-place encryption/decryption. Thus, the message and ciphertext are allowed to overlap.

API Reference#

Combined mode#

In combined mode, the authentication tag and encrypted message are stored consecutively in memory. Thus, c must always point to memory with length 16 (tag length) + mlen (message length).

Example

// Note: HACL Packages will provide this (or a similar) define in a later
// version.
#define HACL_NACL_CRYPTO_BOX_SECRETKEYBYTES 32
#define HACL_NACL_CRYPTO_BOX_PUBLICKEYBYTES 32
#define HACL_NACL_CRYPTO_BOX_BEFORENMBYTES 32
#define HACL_NACL_CRYPTO_BOX_NONCEBYTES 24
#define HACL_NACL_CRYPTO_BOX_MACBYTES 16
// Alice wants to encrypt a message to Bob.
// Thus, both parties do need cryptographic keys.
//
// Note: HACL* does not provide randomness yet.
//       Thus, you must bring your own random (including keys and nonces).

// Alice
unsigned char alice_pk[HACL_NACL_CRYPTO_BOX_PUBLICKEYBYTES];
unsigned char alice_sk[HACL_NACL_CRYPTO_BOX_SECRETKEYBYTES];

// Example: The `crypto_box_keypair_` function does not exist in HACL*.
crypto_box_keypair_alice(alice_sk, alice_pk);

// Bob
unsigned char bob_pk[HACL_NACL_CRYPTO_BOX_PUBLICKEYBYTES];
unsigned char bob_sk[HACL_NACL_CRYPTO_BOX_SECRETKEYBYTES];

// Example: The `crypto_box_keypair_` function does not exist in HACL*.
crypto_box_keypair_bob(bob_sk, bob_pk);
const char* plaintext = "Hello, World!";
const size_t plaintext_size = strlen(plaintext);

// Generate a nonce.
uint8_t nonce[HACL_NACL_CRYPTO_BOX_NONCEBYTES];
generate_random(nonce, HACL_NACL_CRYPTO_BOX_NONCEBYTES);

// Alice encrypts a message to Bob.
uint8_t* ciphertext =
  (uint8_t*)malloc(HACL_NACL_CRYPTO_BOX_MACBYTES + plaintext_size);
uint32_t res_enc = Hacl_NaCl_crypto_box_easy(
  ciphertext, (uint8_t*)plaintext, plaintext_size, nonce, bob_pk, alice_sk);

if (res_enc != 0) {
  // Encryption error
}

// Bob decrypts a message from Alice.
uint8_t* decrypted = (uint8_t*)malloc(plaintext_size);
uint32_t res_dec = Hacl_NaCl_crypto_box_open_easy(
  decrypted,
  ciphertext,
  HACL_NACL_CRYPTO_BOX_MACBYTES + plaintext_size,
  nonce,
  alice_pk,
  bob_sk);

if (res_dec != 0) {
  // Decryption error
}

free(decrypted);
free(ciphertext);
uint32_t Hacl_NaCl_crypto_box_easy(uint8_t *c, uint8_t *m, uint32_t mlen, uint8_t *n, uint8_t *pk, uint8_t *sk)#

Encrypt a message using the recipient’s public key, the sender’s secret key, and a nonce.

Parameters
  • c – Pointer to 16 (tag length) + mlen bytes of memory where the authentication tag and ciphertext is written to.

  • m – Pointer to mlen bytes of memory where the message is read from.

  • mlen – Length of the message.

  • n – Pointer to 24 (crypto_box_NONCEBYTES) bytes of memory where the nonce is read from.

  • pk – Pointer to 32 bytes of memory where the public key of the recipient is read from.

  • sk – Pointer to 32 bytes of memory where the secret key of the sender is read from.

uint32_t Hacl_NaCl_crypto_box_open_easy(uint8_t *m, uint8_t *c, uint32_t clen, uint8_t *n, uint8_t *pk, uint8_t *sk)#

Verify and decrypt a ciphertext produced by crypto_box_easy.

Parameters
  • m – Pointer to clen - 16 (tag length) bytes of memory where the decrypted message is written to.

  • c – Pointer to clen bytes of memory where the ciphertext is read from. Note: the ciphertext must include the tag.

  • clen – Length of the ciphertext.

  • n – Pointer to 24 (crypto_box_NONCEBYTES) bytes of memory where the nonce is read from.

  • pk – Pointer to 32 bytes of memory where the public key of the sender is read from.

  • sk – Pointer to 32 bytes of memory where the secret key of the recipient is read from.

Detached mode#

In detached mode, the authentication tag and encrypted message are stored separately. Thus, c must always point to mlen bytes of memory and tag must always point to 16 (tag length) bytes of memory.

Note: NaCl supports in-place encryption/decryption. Thus, the message and ciphertext are allowed to overlap.

Example

// Note: HACL Packages will provide this (or a similar) define in a later
// version.
#define HACL_NACL_CRYPTO_BOX_SECRETKEYBYTES 32
#define HACL_NACL_CRYPTO_BOX_PUBLICKEYBYTES 32
#define HACL_NACL_CRYPTO_BOX_BEFORENMBYTES 32
#define HACL_NACL_CRYPTO_BOX_NONCEBYTES 24
#define HACL_NACL_CRYPTO_BOX_MACBYTES 16
// Alice wants to encrypt a message to Bob.
// Thus, both parties do need cryptographic keys.
//
// Note: HACL* does not provide randomness yet.
//       Thus, you must bring your own random (including keys and nonces).

// Alice
unsigned char alice_pk[HACL_NACL_CRYPTO_BOX_PUBLICKEYBYTES];
unsigned char alice_sk[HACL_NACL_CRYPTO_BOX_SECRETKEYBYTES];

// Example: The `crypto_box_keypair_` function does not exist in HACL*.
crypto_box_keypair_alice(alice_sk, alice_pk);

// Bob
unsigned char bob_pk[HACL_NACL_CRYPTO_BOX_PUBLICKEYBYTES];
unsigned char bob_sk[HACL_NACL_CRYPTO_BOX_SECRETKEYBYTES];

// Example: The `crypto_box_keypair_` function does not exist in HACL*.
crypto_box_keypair_bob(bob_sk, bob_pk);
const char* plaintext = "Hello, World!";
const size_t plaintext_size = strlen(plaintext);

// Generate a nonce.
uint8_t nonce[HACL_NACL_CRYPTO_BOX_NONCEBYTES];
generate_random(nonce, HACL_NACL_CRYPTO_BOX_NONCEBYTES);

// Alice encrypts a message to Bob.
uint8_t tag[HACL_NACL_CRYPTO_BOX_MACBYTES];
uint8_t* ciphertext = (uint8_t*)malloc(plaintext_size);
uint32_t res_enc = Hacl_NaCl_crypto_box_detached(ciphertext,
                                                 tag,
                                                 (uint8_t*)plaintext,
                                                 plaintext_size,
                                                 nonce,
                                                 bob_pk,
                                                 alice_sk);

if (res_enc != 0) {
  // Encryption error
}

// Bob decrypts a message from Alice.
uint8_t* decrypted = (uint8_t*)malloc(plaintext_size);
uint32_t res_dec = Hacl_NaCl_crypto_box_open_detached(
  decrypted, ciphertext, tag, plaintext_size, nonce, alice_pk, bob_sk);

if (res_dec != 0) {
  // Decryption error
}

free(decrypted);
free(ciphertext);
uint32_t Hacl_NaCl_crypto_box_detached(uint8_t *c, uint8_t *tag, uint8_t *m, uint32_t mlen, uint8_t *n, uint8_t *pk, uint8_t *sk)#

Encrypt a message using the recipient’s public key, the sender’s secret key, and a nonce.

Parameters
  • c – Pointer to mlen bytes of memory where the ciphertext is written to.

  • tag – Pointer to 16 (tag length) bytes of memory where the authentication tag is written to.

  • m – Pointer to mlen bytes of memory where the message is read from.

  • mlen – Length of the message.

  • n – Pointer to 24 (crypto_box_NONCEBYTES) bytes of memory where the nonce is read from.

  • pk – Pointer to 32 bytes of memory where their public key is read from.

  • sk – Pointer to 32 bytes of memory where my secret key is read from.

uint32_t Hacl_NaCl_crypto_box_open_detached(uint8_t *m, uint8_t *c, uint8_t *tag, uint32_t mlen, uint8_t *n, uint8_t *pk, uint8_t *sk)#

Verify and decrypt a ciphertext produced by crypto_box_detached.

Parameters
  • m – Pointer to mlen bytes of memory where the decrypted message is written to.

  • c – Pointer to mlen bytes of memory where the ciphertext is read from. Note: the ciphertext must include the tag.

  • tag – Pointer to 16 (tag length) bytes of memory where the authentication tag is read from.

  • mlen – Length of the message (and ciphertext).

  • n – Pointer to 24 (crypto_box_NONCEBYTES) bytes of memory where the nonce is read from.

  • pk – Pointer to 32 bytes of memory where the public key of the sender is read from.

  • sk – Pointer to 32 bytes of memory where the secret key of the recipient is read from.

With Precomputation#

Applications that send several messages to the same recipient or receive several messages from the same sender can precompute a shared secret k once and reuse it in subsequent _afternm calls to increase performance.

uint32_t Hacl_NaCl_crypto_box_beforenm(uint8_t *k, uint8_t *pk, uint8_t *sk)#

Compute a shared secret key given a public key and secret key.

Parameters
  • k – Pointer to 32 (crypto_box_BEFORENMBYTES) bytes of memory where the shared secret is written to.

  • pk – Pointer to 32 bytes of memory where their public key is read from.

  • sk – Pointer to 32 bytes of memory where my secret key is read from.

Combined mode#

Example

// Note: HACL Packages will provide this (or a similar) define in a later
// version.
#define HACL_NACL_CRYPTO_BOX_SECRETKEYBYTES 32
#define HACL_NACL_CRYPTO_BOX_PUBLICKEYBYTES 32
#define HACL_NACL_CRYPTO_BOX_BEFORENMBYTES 32
#define HACL_NACL_CRYPTO_BOX_NONCEBYTES 24
#define HACL_NACL_CRYPTO_BOX_MACBYTES 16
// Alice wants to encrypt a message to Bob.
// Thus, both parties do need cryptographic keys.
//
// Note: HACL* does not provide randomness yet.
//       Thus, you must bring your own random (including keys and nonces).

// Alice
unsigned char alice_pk[HACL_NACL_CRYPTO_BOX_PUBLICKEYBYTES];
unsigned char alice_sk[HACL_NACL_CRYPTO_BOX_SECRETKEYBYTES];

// Example: The `crypto_box_keypair_` function does not exist in HACL*.
crypto_box_keypair_alice(alice_sk, alice_pk);

// Bob
unsigned char bob_pk[HACL_NACL_CRYPTO_BOX_PUBLICKEYBYTES];
unsigned char bob_sk[HACL_NACL_CRYPTO_BOX_SECRETKEYBYTES];

// Example: The `crypto_box_keypair_` function does not exist in HACL*.
crypto_box_keypair_bob(bob_sk, bob_pk);
uint8_t k[HACL_NACL_CRYPTO_BOX_BEFORENMBYTES];
// Precompute key `k`.
uint32_t res = Hacl_NaCl_crypto_box_beforenm(k, bob_pk, alice_sk);

const char* plaintext = "Hello, World!";
const size_t plaintext_size = strlen(plaintext);

// Generate a nonce.
uint8_t nonce[HACL_NACL_CRYPTO_BOX_NONCEBYTES];
generate_random(nonce, HACL_NACL_CRYPTO_BOX_NONCEBYTES);

// Alice encrypts a message to Bob.
uint8_t* ciphertext =
  (uint8_t*)malloc(HACL_NACL_CRYPTO_BOX_MACBYTES + plaintext_size);
uint32_t res_enc = Hacl_NaCl_crypto_box_easy_afternm(
  ciphertext, (uint8_t*)plaintext, plaintext_size, nonce, k);

if (res_enc != 0) {
  // Encryption error
}

// Bob decrypts a message from Alice.
uint8_t* decrypted = (uint8_t*)malloc(plaintext_size);
uint32_t res_dec = Hacl_NaCl_crypto_box_open_easy_afternm(
  decrypted,
  ciphertext,
  HACL_NACL_CRYPTO_BOX_MACBYTES + plaintext_size,
  nonce,
  k);

if (res_dec != 0) {
  // Decryption error
}

free(decrypted);
free(ciphertext);
uint32_t Hacl_NaCl_crypto_box_easy_afternm(uint8_t *c, uint8_t *m, uint32_t mlen, uint8_t *n, uint8_t *k)#

See crypto_box_easy.

uint32_t Hacl_NaCl_crypto_box_open_easy_afternm(uint8_t *m, uint8_t *c, uint32_t clen, uint8_t *n, uint8_t *k)#

See crypto_box_open_easy.

Detached mode#

Example

// Note: HACL Packages will provide this (or a similar) define in a later
// version.
#define HACL_NACL_CRYPTO_BOX_SECRETKEYBYTES 32
#define HACL_NACL_CRYPTO_BOX_PUBLICKEYBYTES 32
#define HACL_NACL_CRYPTO_BOX_BEFORENMBYTES 32
#define HACL_NACL_CRYPTO_BOX_NONCEBYTES 24
#define HACL_NACL_CRYPTO_BOX_MACBYTES 16
// Alice wants to encrypt a message to Bob.
// Thus, both parties do need cryptographic keys.
//
// Note: HACL* does not provide randomness yet.
//       Thus, you must bring your own random (including keys and nonces).

// Alice
unsigned char alice_pk[HACL_NACL_CRYPTO_BOX_PUBLICKEYBYTES];
unsigned char alice_sk[HACL_NACL_CRYPTO_BOX_SECRETKEYBYTES];

// Example: The `crypto_box_keypair_` function does not exist in HACL*.
crypto_box_keypair_alice(alice_sk, alice_pk);

// Bob
unsigned char bob_pk[HACL_NACL_CRYPTO_BOX_PUBLICKEYBYTES];
unsigned char bob_sk[HACL_NACL_CRYPTO_BOX_SECRETKEYBYTES];

// Example: The `crypto_box_keypair_` function does not exist in HACL*.
crypto_box_keypair_bob(bob_sk, bob_pk);
uint8_t k[HACL_NACL_CRYPTO_BOX_BEFORENMBYTES];
// Precompute key `k`.
uint32_t res = Hacl_NaCl_crypto_box_beforenm(k, bob_pk, alice_sk);

const char* plaintext = "Hello, World!";
const size_t plaintext_size = strlen(plaintext);

// Generate a nonce.
uint8_t nonce[HACL_NACL_CRYPTO_BOX_NONCEBYTES];
generate_random(nonce, HACL_NACL_CRYPTO_BOX_NONCEBYTES);

// Alice encrypts a message to Bob.
uint8_t tag[HACL_NACL_CRYPTO_BOX_MACBYTES];
uint8_t* ciphertext = (uint8_t*)malloc(plaintext_size);
uint32_t res_enc = Hacl_NaCl_crypto_box_detached_afternm(
  ciphertext, tag, (uint8_t*)plaintext, plaintext_size, nonce, k);

if (res_enc != 0) {
  // Encryption error
}

// Bob decrypts a message from Alice.
uint8_t* decrypted = (uint8_t*)malloc(plaintext_size);
uint32_t res_dec = Hacl_NaCl_crypto_box_open_detached_afternm(
  decrypted, ciphertext, tag, plaintext_size, nonce, k);

if (res_dec != 0) {
  // Decryption error
}

free(decrypted);
free(ciphertext);
uint32_t Hacl_NaCl_crypto_box_detached_afternm(uint8_t *c, uint8_t *tag, uint8_t *m, uint32_t mlen, uint8_t *n, uint8_t *k)#

See crypto_box_detached.

uint32_t Hacl_NaCl_crypto_box_open_detached_afternm(uint8_t *m, uint8_t *c, uint8_t *tag, uint32_t mlen, uint8_t *n, uint8_t *k)#

See crypto_box_open_detached.