.\" This file is dual-licensed.  Choose whichever you want.
.\"
.\" The first licence is a regular 2-clause BSD licence.  The second licence
.\" is the CC-0 from Creative Commons. It is intended to release Monocypher
.\" to the public domain.  The BSD licence serves as a fallback option.
.\"
.\" SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
.\"
.\" ----------------------------------------------------------------------------
.\"
.\" Copyright (c) 2017-2019 Loup Vaillant
.\" Copyright (c) 2017-2018 Michael Savage
.\" Copyright (c) 2017, 2019-2020 Fabio Scotoni
.\" Copyright (c) 2020 Richard Walmsley
.\" All rights reserved.
.\"
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions are
.\" met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
.\"    notice, this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\"    notice, this list of conditions and the following disclaimer in the
.\"    documentation and/or other materials provided with the
.\"    distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" ----------------------------------------------------------------------------
.\"
.\" Written in 2017-2020 by Loup Vaillant, Michael Savage, Fabio Scotoni and
.\" Richard Walmsley
.\"
.\" To the extent possible under law, the author(s) have dedicated all copyright
.\" and related neighboring rights to this software to the public domain
.\" worldwide.  This software is distributed without any warranty.
.\"
.\" You should have received a copy of the CC0 Public Domain Dedication along
.\" with this software.  If not, see
.\" <https://creativecommons.org/publicdomain/zero/1.0/>
.\"
.Dd March 31, 2020
.Dt CRYPTO_X25519 3MONOCYPHER
.Os
.Sh NAME
.Nm crypto_x25519 ,
.Nm crypto_x25519_public_key
.Nd X25519 key exchange
.Sh SYNOPSIS
.In monocypher.h
.Ft void
.Fo crypto_x25519
.Fa "uint8_t raw_shared_secret[32]"
.Fa "const uint8_t your_secret_key[32]"
.Fa "const uint8_t their_public_key[32]"
.Fc
.Ft void
.Fo crypto_x25519_public_key
.Fa "uint8_t your_public_key[32]"
.Fa "const uint8_t your_secret_key[32]"
.Fc
.Sh DESCRIPTION
.Fn crypto_x25519
computes a shared secret with
.Fa your_secret_key
and
.Fa their_public_key .
It is a low-level primitive.
Use
.Xr crypto_key_exchange 3monocypher
unless you have a specific reason not to.
.Pp
.Fn crypto_x25519_public_key
is the same as
.Xr crypto_key_exchange_public_key 3monocypher .
It deterministically computes the public key from a random secret key.
.Pp
The arguments are:
.Bl -tag -width Ds
.It Fa 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
.Xr crypto_chacha20_H 3monocypher
or
.Xr crypto_blake2b 3monocypher
first.
.It Fa your_secret_key
A 32-byte secret random number.
See
.Xr intro 3monocypher
for advice about generating random bytes (use the operating system's
random number generator).
.It Fa their_public_key
The public key of the other party.
.Pp
.Fa raw_shared_secret
and
.Fa your_secret_key
may overlap if your secret is no longer required.
.El
.Pp
Some protocols,
such as some password-authenticated key exchange (PAKE) protocols
and oblivious pseudo-random functions (OPRF),
may require
.Dq 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
.Fn crypto_x25519
to an all-zero buffer using
.Xr crypto_verify32 3monocypher ;
abort the protocol if the output and the all-zero buffer are equal.
.Pp
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
.Xr crypto_from_eddsa_private 3monocypher
and
.Xr crypto_from_eddsa_public 3monocypher .
.Sh RETURN VALUES
.Fn crypto_x25519
and
.Fn crypto_x25519_public_key
return nothing.
.Sh EXAMPLES
The following example assumes the existence of
.Fn arc4random_buf ,
which fills the given buffer with cryptographically secure random bytes.
If
.Fn arc4random_buf
does not exist on your system, see
.Xr intro 3monocypher
for advice about how to generate cryptographically secure random bytes.
.Pp
Generate a pair of shared keys with your secret key and their public
key.
(This can help nonce management for full duplex communications.)
.Bd -literal -offset indent
const uint8_t their_pk     [32]; /* Their public key          */
uint8_t       your_sk      [32]; /* Your secret key           */
uint8_t       shared_secret[32]; /* Shared secret (NOT a key) */
arc4random_buf(your_sk, 32);
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);
.Ed
.Sh SEE ALSO
.Xr crypto_key_exchange 3monocypher ,
.Xr intro 3monocypher
.Sh STANDARDS
This function implements X25519, described in RFC 7748.
.Sh HISTORY
The
.Fn crypto_x25519 ,
and
.Fn crypto_x25519_public_key
functions first appeared in Monocypher 0.1.
.Sh SECURITY CONSIDERATIONS
If either of the long term secret keys leaks, it may compromise
.Em all past messages .
This can be avoided by using protocols that provide forward secrecy,
such as the X3DH key agreement protocol.
.Sh IMPLEMENTATION DETAILS
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).
