int crypto_box_easy(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, const unsigned char *pk, const unsigned char *sk) { if (mlen > SIZE_MAX - crypto_box_MACBYTES) { return -1; } return crypto_box_detached(c + crypto_box_MACBYTES, c, m, mlen, n, pk, sk); }
std::error_code encrypt_message_in_place_and_write_header() noexcept { message_header header(session_.header_buffer); header.generate_data_nonce(); header.generate_followup_nonce(); header.set_message_length(message_.length()); auto data_nonce = header.data_nonce_span(); if ( crypto_box_detached( &message_[0] , &session_.mac[0] , &message_[0] , message_.size() , &data_nonce[0] , &session_.remote_public_key[0] , &session_.local_private_key[0] ) != 0 ) { return error::message_encrypt; } nonce temp_followup_nonce; header.copy_followup_nonce(temp_followup_nonce); if ( !header.encrypt_to( session_.encrypt_nonce , session_.remote_public_key , session_.local_private_key ) ) { return error::message_header_encrypt; } std::copy( temp_followup_nonce.begin() , temp_followup_nonce.end() , session_.encrypt_nonce.begin() ); return {}; }
int main(void) { unsigned char *alicepk; unsigned char *alicesk; unsigned char *bobpk; unsigned char *bobsk; unsigned char *mac; unsigned char *nonce; unsigned char *k1; unsigned char *k2; unsigned char *m; unsigned char *m2; unsigned char *c; size_t mlen; size_t i; size_t m_size; size_t m2_size; size_t c_size; int ret; m2_size = m_size = 1U + randombytes_uniform(10000); c_size = crypto_box_MACBYTES + m_size; m = (unsigned char *) sodium_malloc(m_size); m2 = (unsigned char *) sodium_malloc(m2_size); c = (unsigned char *) sodium_malloc(c_size); alicepk = (unsigned char *) sodium_malloc(crypto_box_PUBLICKEYBYTES); alicesk = (unsigned char *) sodium_malloc(crypto_box_SECRETKEYBYTES); bobpk = (unsigned char *) sodium_malloc(crypto_box_PUBLICKEYBYTES); bobsk = (unsigned char *) sodium_malloc(crypto_box_SECRETKEYBYTES); mac = (unsigned char *) sodium_malloc(crypto_box_MACBYTES); nonce = (unsigned char *) sodium_malloc(crypto_box_NONCEBYTES); k1 = (unsigned char *) sodium_malloc(crypto_box_BEFORENMBYTES); k2 = (unsigned char *) sodium_malloc(crypto_box_BEFORENMBYTES); crypto_box_keypair(alicepk, alicesk); crypto_box_keypair(bobpk, bobsk); mlen = (size_t) randombytes_uniform((uint32_t) m_size) + 1U; randombytes_buf(m, mlen); randombytes_buf(nonce, crypto_box_NONCEBYTES); ret = crypto_box_easy(c, m, mlen, nonce, bobpk, alicesk); assert(ret == 0); if (crypto_box_open_easy(m2, c, (unsigned long long) mlen + crypto_box_MACBYTES, nonce, alicepk, bobsk) != 0) { printf("open() failed"); return 1; } printf("%d\n", memcmp(m, m2, mlen)); for (i = 0; i < mlen + crypto_box_MACBYTES - 1; i++) { if (crypto_box_open_easy(m2, c, (unsigned long long) i, nonce, alicepk, bobsk) == 0) { printf("short open() should have failed"); return 1; } } memcpy(c, m, mlen); ret = crypto_box_easy(c, c, (unsigned long long) mlen, nonce, bobpk, alicesk); assert(ret == 0); printf("%d\n", memcmp(m, c, mlen) == 0); printf("%d\n", memcmp(m, c + crypto_box_MACBYTES, mlen) == 0); if (crypto_box_open_easy(c, c, (unsigned long long) mlen + crypto_box_MACBYTES, nonce, alicepk, bobsk) != 0) { printf("crypto_box_open_easy() failed\n"); } ret = crypto_box_beforenm(k1, alicepk, bobsk); assert(ret == 0); ret = crypto_box_beforenm(k2, bobpk, alicesk); assert(ret == 0); memset(m2, 0, m2_size); if (crypto_box_easy_afternm(c, m, SIZE_MAX - 1U, nonce, k1) == 0) { printf("crypto_box_easy_afternm() with a short ciphertext should have failed\n"); } crypto_box_easy_afternm(c, m, (unsigned long long) mlen, nonce, k1); if (crypto_box_open_easy_afternm(m2, c, (unsigned long long) mlen + crypto_box_MACBYTES, nonce, k2) != 0) { printf("crypto_box_open_easy_afternm() failed\n"); } printf("%d\n", memcmp(m, m2, mlen)); if (crypto_box_open_easy_afternm(m2, c, crypto_box_MACBYTES - 1U, nonce, k2) == 0) { printf("crypto_box_open_easy_afternm() with a huge ciphertext should have failed\n"); } memset(m2, 0, m2_size); ret = crypto_box_detached(c, mac, m, (unsigned long long) mlen, nonce, alicepk, bobsk); assert(ret == 0); if (crypto_box_open_detached(m2, c, mac, (unsigned long long) mlen, nonce, bobpk, alicesk) != 0) { printf("crypto_box_open_detached() failed\n"); } printf("%d\n", memcmp(m, m2, mlen)); memset(m2, 0, m2_size); crypto_box_detached_afternm(c, mac, m, (unsigned long long) mlen, nonce, k1); if (crypto_box_open_detached_afternm(m2, c, mac, (unsigned long long) mlen, nonce, k2) != 0) { printf("crypto_box_open_detached_afternm() failed\n"); } printf("%d\n", memcmp(m, m2, mlen)); sodium_free(alicepk); sodium_free(alicesk); sodium_free(bobpk); sodium_free(bobsk); sodium_free(mac); sodium_free(nonce); sodium_free(k1); sodium_free(k2); sodium_free(m); sodium_free(m2); sodium_free(c); printf("OK\n"); return 0; }
/* * Using public-key authenticated encryption, Bob can encrypt a * confidential message specifically for Alice, using Alice's public * key. * * Using Bob's public key, Alice can verify that the encrypted * message was actually created by Bob and was not tampered with, * before eventually decrypting it. * * Alice only needs Bob's public key, the nonce and the ciphertext. * Bob should never ever share his secret key, even with Alice. * * And in order to send messages to Alice, Bob only needs Alice's * public key. Alice should never ever share her secret key either, * even with Bob. * * Alice can reply to Bob using the same system, without having to * generate a distinct key pair. * * The nonce doesn't have to be confidential, but it should be used * with just one invokation of crypto_box_open_easy() for a * particular pair of public and secret keys. * * One easy way to generate a nonce is to use randombytes_buf(), * considering the size of nonces the risk of any random collisions * is negligible. For some applications, if you wish to use nonces to * detect missing messages or to ignore replayed messages, it is also * ok to use a simple incrementing counter as a nonce. * * When doing so you must ensure that the same value can never be * re-used (for example you may have multiple threads or even hosts * generating messages using the same key pairs). * * This system provides mutual authentication. However, a typical use * case is to secure communications between a server, whose public * key is known in advance, and clients connecting anonymously. */ static int box_detached(void) { unsigned char bob_pk[crypto_box_PUBLICKEYBYTES]; /* Bob's public key */ unsigned char bob_sk[crypto_box_SECRETKEYBYTES]; /* Bob's secret key */ unsigned char alice_pk[crypto_box_PUBLICKEYBYTES]; /* Alice's public key */ unsigned char alice_sk[crypto_box_SECRETKEYBYTES]; /* Alice's secret key */ unsigned char nonce[crypto_box_NONCEBYTES]; unsigned char message[MAX_INPUT_LEN]; unsigned char mac[crypto_box_MACBYTES]; unsigned char ciphertext[MAX_INPUT_LEN]; size_t message_len; int ret; puts("Example: crypto_box_detached\n"); puts("Generating keypairs...\n"); crypto_box_keypair(bob_pk, bob_sk); /* generate Bob's keys */ crypto_box_keypair(alice_pk, alice_sk); /* generate Alice's keys */ puts("Bob"); printf("Public key: "); print_hex(bob_pk, sizeof bob_pk); printf("Secret key: "); print_hex(bob_sk, sizeof bob_sk); puts("Alice"); printf("Public key: "); print_hex(alice_pk, sizeof alice_pk); printf("Secret key: "); print_hex(alice_sk, sizeof alice_sk); /* nonce must be unique per (key, message) - it can be public and deterministic */ puts("Generating nonce..."); randombytes_buf(nonce, sizeof nonce); printf("Nonce: "); print_hex(nonce, sizeof nonce); /* read input */ message_len = prompt_input("a message", (char*)message, sizeof message, 1); print_hex(message, message_len); /* encrypt and authenticate the message */ printf("Encrypting and authenticating with %s\n\n", crypto_box_primitive()); crypto_box_detached(ciphertext, mac, message, message_len, nonce, alice_pk, bob_sk); /* send the nonce, the MAC and the ciphertext */ puts("Bob sends the nonce, the MAC and the ciphertext...\n"); printf("Nonce: "); print_hex(nonce, sizeof nonce); printf("MAC: "); print_hex(mac, sizeof mac); printf("Ciphertext: "); print_hex(ciphertext, message_len); /* decrypt the message */ puts("Alice verifies the MAC and decrypts the ciphertext..."); ret = crypto_box_open_detached(message, ciphertext, mac, message_len, nonce, bob_pk, alice_sk); print_hex(message, message_len); print_verification(ret); if (ret == 0) { printf("Plaintext: "); fwrite(message, 1U, message_len, stdout); putchar('\n'); } sodium_memzero(bob_sk, sizeof bob_sk); /* wipe sensitive data */ sodium_memzero(alice_sk, sizeof alice_sk); sodium_memzero(message, sizeof message); sodium_memzero(ciphertext, sizeof ciphertext); return ret; }