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:

Example

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

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.

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 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

Last updated