# Ed25519 to Curve25519

Ed25519 keys can be converted to X25519 keys, so that the same key pair can be used both for authenticated encryption (`crypto_box`) and for signatures (`crypto_sign`).

Before considering this operation, please read these relevant paragraphs from the FAQ:

* [Do I need to add a signature to encrypted messages to detect if they have been tampered with?](https://libsodium.gitbook.io/doc/quickstart#do-i-need-to-add-a-signature-to-encrypted-messages-to-detect-if-they-have-been-tampered-with)
* [How can I sign and encrypt using the same key pair?](https://libsodium.gitbook.io/doc/quickstart#how-can-i-sign-and-encrypt-using-the-same-key-pair)

## Example

```c
unsigned char ed25519_pk[crypto_sign_ed25519_PUBLICKEYBYTES];
unsigned char ed25519_skpk[crypto_sign_ed25519_SECRETKEYBYTES];
unsigned char x25519_pk[crypto_scalarmult_curve25519_BYTES];
unsigned char x25519_sk[crypto_scalarmult_curve25519_BYTES];

crypto_sign_ed25519_keypair(ed25519_pk, ed25519_skpk);

crypto_sign_ed25519_pk_to_curve25519(x25519_pk, ed25519_pk);
crypto_sign_ed25519_sk_to_curve25519(x25519_sk, ed25519_skpk);
```

## Usage

```c
int crypto_sign_ed25519_pk_to_curve25519(unsigned char *x25519_pk,
                                         const unsigned char *ed25519_pk);
```

The `crypto_sign_ed25519_pk_to_curve25519()` function converts an Ed25519 public key `ed25519_pk` to an X25519 public key and stores it into `x25519_pk`.

```c
int crypto_sign_ed25519_sk_to_curve25519(unsigned char *x25519_sk,
                                         const unsigned char *ed25519_sk);
```

The `crypto_sign_ed25519_sk_to_curve25519()` function converts an Ed25519 secret key `ed25519_sk` to an X25519 secret key and stores it into `x25519_sk`.

In order to save CPU cycles and prevent key mismatches, the `crypto_sign_open()` and `crypto_sign_verify_detached()` functions expect Ed25519 secret keys generated by `crypto_sign_keypair()` or `crypto_sign_seed_keypair()`. These keys are 64 byte long.

However, the `crypto_sign_ed25519_sk_to_curve25519()` function only reads the first 32 bytes (the 32 byte seed returned by `crypto_sign_ed25519_sk_to_seed()`) and ignores the 32 remaining bytes.

## Notes

If you can afford it, using distinct keys for signing and for encryption is still highly recommended. Signing keys are usually long-term keys, while keys used for key exchange should rather be ephemeral.

An alternative is to do the ECDH operation over the Edwards curve, avoiding the conversion altogether.

In order to do this, the `crypto_scalarmult_ed25519()` function is available.

However, that still requires computing the Edwards25519 secret key from the Ed25519 seed. See the Quickstart/FAQ page for guidance on how to do it.

## References

* [On using the same key pair for Ed25519 and an X25519 based KEM](https://eprint.iacr.org/2021/509.pdf) - E. Thormarker
