CRYPTO_X25519(3MONOCYPHER) | 3MONOCYPHER | CRYPTO_X25519(3MONOCYPHER) |
crypto_x25519
,
crypto_x25519_public_key
—
#include <monocypher.h>
void
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; X25519 is
a building block for protocols. To perform a key exchange, use a higher level
protocol, such as the X3DH key agreement protocol.
crypto_x25519_public_key
()
deterministically computes the public key from a random secret key.
The arguments are:
raw_shared_secret and your_secret_key may overlap if your secret is no longer required.
Some protocols, such as some password-authenticated key exchange
(PAKE) protocols and oblivious pseudo-random functions (OPRF), may require
“contributory” behaviour, which ensures that no untrusted
party forces the shared secret to a known constant. If a protocol requires
contributory behaviour, compare the output of
crypto_x25519
() to an all-zero buffer using
crypto_verify32(3monocypher),
then abort the protocol if the output and the all-zero buffer are equal.
Do not use the same secret key for both key exchanges and signatures. The public keys are different and revealing both may leak information. If there really is no room to store or derive two different secret keys, consider generating a key pair for signatures and then converting it with crypto_from_eddsa_private(3monocypher) and crypto_from_eddsa_public(3monocypher).
crypto_x25519
() and
crypto_x25519_public_key
() return nothing.
arc4random_buf
(), which fills the given buffer with
cryptographically secure random bytes. If
arc4random_buf
() does not exist on your system, see
intro(3monocypher) for advice about how to
generate cryptographically secure random bytes.
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 */ uint8_t your_sk [32]; /* Your secret key */ uint8_t your_pk [32]; /* Your public key */ uint8_t shared_secret[32]; /* Shared secret (NOT a key) */ arc4random_buf(your_sk, 32); crypto_x25512(your_pk, your_sk); 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_ctx ctx; crypto_blake2b_init (&ctx); crypto_blake2b_update(&ctx, shared_secret, 32); crypto_blake2b_update(&ctx, your_pk , 32); crypto_blake2b_update(&ctx, their_pk , 32); crypto_blake2b_final (&ctx, shared_keys); 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_x25519
() and
crypto_x25519_public_key
() functions first appeared in
Monocypher 0.1.
Many (private, public) key pairs produce the same shared secret. Therefore, not including the public keys in the key derivation can lead to subtle vulnerabilities. This can be avoided by hashing the shared secret concatenated with both public keys. For example,
February 23, 2022 | Debian |