crypto_x25519,
crypto_x25519_public_key —
X25519 key exchange
#include
<monocypher.h>
int
crypto_x25519(
uint8_t
raw_shared_secret[32],
const uint8_t
your_secret_key[32],
const uint8_t
their_public_key[32]);
void
crypto_x25519_public_key(
uint8_t
your_public_key[32],
const uint8_t
your_secret_key[32]);
crypto_x25519() computes a shared secret with
your_secret_key and
their_public_key. It is a low-level
primitive. Use
crypto_key_exchange(3monocypher)
unless you have a specific reason not to.
crypto_x25519_public_key() is the same as
crypto_key_exchange_public_key(3monocypher).
It deterministically computes the public key from a random secret key.
The arguments are:
-
-
- raw_shared_secret
- The shared secret, known only to those who know a relevant
secret key (yours or theirs). It is not cryptographically random. Do not
use it directly as a key. Hash it with
crypto_chacha20_H(3monocypher)
or
crypto_blake2b(3monocypher)
first.
-
-
- your_secret_key
- A 32-byte secret random number. See
intro(3monocypher) for
advice about generating random bytes (use the operating system's random
number generator).
-
-
- their_public_key
- The public key of the other party.
Some public keys force the shared key to a known constant.
crypto_x225519() returns -1 if it detects such a
public key, otherwise it returns 0. This never happens with legitimate public
keys.
The return value has been deprecated.
crypto_x25519() will return
void starting with the next major release of
Monocypher. Some poorly designed protocols require to test for
“contributory” behaviour, which ensures that no untrusted party
forces the shared secret to a known constant. Protocols should instead be
designed in such a way that no such check is necessary, namely by
authenticating the other party or exchanging keys over a trusted channel.
crypto_x25519_public_key() returns nothing.
Generate a pair of shared keys with your secret key and their public key. (This
can help nonce management for full duplex communications.)
const uint8_t their_pk [32]; /* Their public key */
const uint8_t your_sk [32]; /* Your secret key */
uint8_t shared_secret[32]; /* Shared secret (NOT a key) */
crypto_x25519(shared_secret, your_sk, their_pk);
/* Wipe secrets if they are no longer needed */
crypto_wipe(your_sk, 32);
uint8_t shared_keys[64]; /* Two shared session keys */
crypto_blake2b(shared_keys, shared_secret, 32);
const uint8_t *key_1 = shared_keys; /* Shared key 1 */
const uint8_t *key_2 = shared_keys + 32; /* Shared key 2 */
/* Wipe secrets if they are no longer needed */
crypto_wipe(shared_secret, 32);
crypto_key_exchange(3monocypher),
intro(3monocypher)
This function implements X25519, described in RFC 7748.
The
crypto_x25519(), and
crypto_x25519_public_key() functions first
appeared in Monocypher 0.1.
If either of the long term secret keys leaks, it may compromise
all past messages. This can be avoided by using
protocols that provide forward secrecy, such as the X3DH key agreement
protocol.
The most significant bit of the public key is systematically ignored. It is not
needed because every public key should be smaller than 2^255-19, which fits in
255 bits. If another implementation of X25519 gives you a key that is not
fully reduced and has its high bit set, the computation will fail. On the
other hand, it also means you may use this bit for other purposes (such as
parity flipping for Ed25519 compatibility).