CRYPTO_CURVE_TO_HIDDEN(3MONOCYPHER) | 3MONOCYPHER | CRYPTO_CURVE_TO_HIDDEN(3MONOCYPHER) |

# NAME

hiding of X25519 public keys```
#include
<monocypher.h>
```

`int`

`crypto_curve_to_hidden`

(`uint8_t
hidden[32]`, `const uint8_t curve[32]`,
`uint8_t tweak`);

`void`

`crypto_hidden_to_curve`

(`uint8_t
curve[32]`, `const uint8_t hidden[32]`);

`void`

`crypto_hidden_key_pair`

(`uint8_t
hidden[32]`, `uint8_t secret_key[32]`,
`uint8_t seed[32]`);

# DESCRIPTION

These functions allow obfuscating X25519 public keys by making
them appear effectively indistinguishable from random noise. This is of
interest for key exchange protocols that require indistinguishability from
randomness, such as padded uniform random blobs (PURBs). They are intended
for ephemeral (short-lived, possibly just one-time) X25519 keys, not for
long-term public keys. After an initial key exchange involving hidden keys,
subsequent key exchange messages should be encrypted instead; see, for
example, the Noise Protocol Framework. This is an
*advanced
feature*. Unless you are implementing an protocol that requires
indistinguishability of all communications from random noise, consider
crypto_x25519() instead.
Both this family of functions and
crypto_x25519() should be
used as a building block to implement a key exchange protocol.

For understanding what these functions do, it is
important to note that a “public key” in this context refers
to a *point on
Curve25519*. This also means that these functions are not compatible
with crypto_sign() and
related functions.

The arguments are:

`curve`- A point on the curve which is a Curve25519 public key generated with either crypto_x25519_dirty_fast() or crypto_x25519_dirty_small().
`hidden`- The hidden encoding of a point on the curve which is effectively indistinguishable from random.
`secret_key`- The secret key that was generated from the given
`seed`. `seed`- A 32-byte random number from which to derive a key pair. See
intro() for advice about
generating random bytes (use the operating system's random number
generator). The
`seed`is wiped automatically. - A 1-byte random number, which influences the final output of
`crypto_curve_to_hidden`

().

The `hidden` and `curve`
arguments may overlap or point at the same buffer.

# RETURN VALUES

`crypto_curve_to_hidden`

() returns 0 on
success and -1 if the given `curve` argument is
unsuitable for hiding.

`crypto_hidden_to_curve`

() and
`crypto_hidden_key_pair`

() return nothing. They cannot
fail.

# EXAMPLES

Generate a key pair manually using crypto_x25519_dirty_small() instead of its fast variant:

uint8_t sk [32]; /* Secret key output */ uint8_t pk [32]; /* Hidden public key output */ uint8_t tweak; /* Random tweak input */ arc4random_buf(&tweak, 1); for (;;) { arc4random_buf(sk, 32); crypto_x25519_dirty_small(pk, sk); if (crypto_curve_to_hidden(pk, pk, tweak) == 0) break; } /* Now save the secret key and send the hidden public key. */

Performing a key exchange with the other party's public key having been hidden:

uint8_t hidden_pk [32]; /* Their hidden public key */ uint8_t their_pk [32]; /* Their unhidden public key */ uint8_t your_sk [32]; /* Your secret key */ uint8_t shared_key[32]; /* Shared session key */ crypto_hidden_to_curve(their_pk, hidden_pk); crypto_x25519(shared_key, your_sk, their_pk); /* Wipe secrets if they are no longer needed */ crypto_wipe(your_sk, 32);

# SEE ALSO

# STANDARDS

These functions implement the Elligator 2 mapping for Curve25519.
This mapping is incompatible with both the hash-to-curve Internet draft and
the implementation of Elligator 2 in libsodium. Elligator 2 was described
in: Daniel J. Bernstein,
Mike Hamburg, Anna
Krasnova, and Tanja Lange,
Elligator: Elliptic-curve points indistinguishable from
uniform random strings, *Association for Computing
Machinery*, *CCS '13: Proceedings of the 2013 ACM SIGSAC
conference on Computer & communications security*,
pp. 967–980,
2013.

# HISTORY

The `crypto_curve_to_hidden`

(),
`crypto_hidden_to_curve`

(), and
`crypto_hidden_key_pair`

() functions first appeared in
Monocypher 3.1.0.

# SECURITY CONSIDERATIONS

The secret keys for the public keys fed into
`crypto_curve_to_hidden`

()
**must be chosen
randomly** rather than deterministically. Otherwise, the timing
information given by the required number of retries also leaks information
on the secret keys.

These functions
*help* build highly
difficult-to-analyse protocols but are insufficient by themselves: Other
metadata, such as the number of bytes sent in a packet or the size of the
32-byte random looking string that represents the curve point itself, can be
very strong indicators of the use of cryptography. Consider using
appropriate padding algorithms, such as PADME, and obscure other metadata as
much as possible.

February 13, 2022 | Debian |