I have tested Public-key-cryptography by libsodium and came across a strange behavior. The encrypted message is decrypted without the private key.
Example from official site libsodium
#define MESSAGE "test"
#define MESSAGE_LEN 4
#define CIPHERTEXT_LEN (crypto_box_MACBYTES + MESSAGE_LEN)
static bool TestSodium()
unsigned char alice_publickey[crypto_box_PUBLICKEYBYTES];
unsigned char alice_secretkey[crypto_box_SECRETKEYBYTES];
unsigned char bob_publickey[crypto_box_PUBLICKEYBYTES];
unsigned char bob_secretkey[crypto_box_SECRETKEYBYTES];
unsigned char nonce[crypto_box_NONCEBYTES];
unsigned char ciphertext[CIPHERTEXT_LEN];
randombytes_buf(nonce, sizeof nonce);
// message alice -> bob
if (crypto_box_easy(ciphertext, (const unsigned char*)MESSAGE, MESSAGE_LEN, nonce, bob_publickey, alice_secretkey) != 0)
unsigned char decrypted[MESSAGE_LEN + 1];
decrypted[MESSAGE_LEN] = 0;
//if (crypto_box_open_easy(decrypted, ciphertext, CIPHERTEXT_LEN, nonce, alice_publickey, bob_secretkey) != 0)
// Whis works without Bobs secret key!
if (crypto_box_open_easy(decrypted, ciphertext, CIPHERTEXT_LEN, nonce, bob_publickey, alice_secretkey) != 0)
if(strcmp((const char*)decrypted, MESSAGE) != 0) return false;
Using public-key authenticated encryption, Alice can encrypt a confidential message specifically for Bob, using Bob's public key.
Using Alice's public key, Bob can verify that the encrypted message was actually created by Alice and was not tampered with, before eventually decrypting it.
Bob only needs Alice's public key, the nonce and the ciphertext.
And in order to send messages to Bob, Alice only needs Bobs's public key.
In libsodium, public-key authenticated encryption is done in three separate phases, in that order:
Key exchange — Use an elliptic-curve Diffie-Hellman algorithm (X25519) to generate the shared secret keys from my private key and your public key.
Encryption — Apply symmetric-key encryption (XSalsa20) to the plaintext message using a shared secret key generated in step 1.
Authentication — Generate a MAC (Poly1305), again relying on the keys generated in the above steps.
crypto_box_afternmsteps, which are the same as
Using symmetric encryption in steps 2-3 means the same key must be computable by both Alice and Bob, i.e.
shared_key_computed_by_alice = crypto_box_beforenm(bob_pk, slice_sk) shared_key_computed_by_bob = crypto_box_beforenm(alice_pk, bob_sk) assert(shared_key_computed_by_alice == shared_key_computed_by_bob)
Since we require both key pairs to generate the same shared secret key, it is not hard to see that both pairs can also decrypt the same message.
Note that in your implementation of the "wrong" decryption, you not only used Bob's public key, but also Alice's private key (which only Alice knows).
Since it is Alice that wants to send the encrypted message to Bob, this means Alice should already know the plain text message in the first place. So she can decrypt that message using her own private key is not a security problem.
The decryption routine would really fail if you used Bob's public key with another person (Eve)'s private key.
If you think Alice being able to decrypt her own message is a problem, you could force Alice to destroy her private key after the conversation