<p>It's not possible to directly compute the ed25519 public key from the private key.  Instead, use the deterministic private key to create a seed, then use the seed to re-create the private key with its corresponding public key. The following code snippet assumes <code>ed25519_skpk</code> is already initialized:</p>

<pre><code>char           hex_ed_pk[65];                                      
unsigned char  seed[crypto_sign_SEEDBYTES];                       
unsigned char  ed25519_skpk[crypto_sign_ed25519_SECRETKEYBYTES];        
unsigned char  ed25519_pk[crypto_sign_ed25519_PUBLICKEYBYTES];

// COMPUTE ED25519 PUBLIC KEY, REQUIRES ESTABLISHING A SEED
(void)crypto_sign_ed25519_sk_to_seed( seed,ed25519_skpk);                
(void)crypto_sign_seed_keypair( ed25519_pk, ed25519_skpk, seed );      
(void)sodium_bin2hex( hex_ed_pk, 65, ed25519_pk, 32 );
</code></pre>

CC BY-SA 3.0
2016-01-20T00:08:55.997Z
2017-09-11T15:00:09.963Z
2017-09-11T15:00:09.963Z
skaht
<p>On libsodium > 1.0.15, the <code>crypto_scalarmult_ed25519_base()</code> can do this.</p>

CC BY-SA 3.0
2017-11-10T01:13:09.953Z
2017-11-10T01:13:09.953Z
Frank Denis
<p>Not all crypto currencies are using <strong>secp256k1</strong> technology for keypair generation and digital signatures. <strong>Curve25519</strong> technology (frequently used to support ECDH key exchanges) is being used by a few other cryptocurrencies. <strong>Ed25519</strong> cryptography (meant to support EdDSA functionality) and Curve25519 cryptography are closely related through transformations and the trend is to start with Ed25519 keys and transform them to Curve25519 key pairs. </p>

<p>Been using this <a href="http://fossies.org/linux/tor/src/test/ed25519_vectors.inc" rel="noreferrer">reference</a> as a source of eight <strong>ED25519_SECRET_KEYS</strong> and corresponding <strong>ED25519_PUBLIC_KEYS</strong> to use as test vectors for applying Ed25519 package implementations. </p>

<p>Got <a href="https://github.com/floodyberry/ed25519-donna" rel="noreferrer">floodyberry/ed25519-donna</a> to function as expected. However, I could not compute the <strong>ED25519_CURVE25519_PUBLIC_KEYS</strong> from the reference using ed25519-donna using its <em><code>curved25519_scalarmult_basepoint()</code></em> function to match. This pushed me towards trying <a href="https://github.com/jedisct1/libsodium" rel="noreferrer">jedisct1/libsodium</a>. Got <em><code>crypto_scalarmult_base()</code></em> function results from libsodium to match those from ed25519-donna:-)  </p>

<p>However, <strong><code>it is unclear how jedisct1/libsodium can be applied to generate public Ed25519 keys only from secret Ed25519 keys that are natively in an ASCII hexadecimal format</code></strong>:-( It seems that jedisct1/libsodium requires keys to always be generated from it native keypair generation process, opposed to an externally supplied private key.</p>

<p>Used the <em>sodium_hex2bin()</em> to stuff an ASCII hex encoded private key from the reference into the 64 unsigned char ed25519_skpk variable:  </p>

<p><strong>sodium_hex2bin( ed25519_skpk, 32, ED25519_SECRET_KEYS[ii], 64, NULL, NULL, NULL );</strong></p>

<p>Results from the following libsodium function were as expected:</p>

<p><strong>crypto_scalarmult_base( curve25519_pk, ed25519_skpk )</strong> </p>

<p><em>Was a bit frustrated when I discovered that crypto_sign_ed25519_sk_to_pk() was coded to extract the public key from ed25519_skpk that was never initialized.</em></p>

<p><strong>crypto_sign_ed25519_sk_to_pk( ed25519_pk, ed25519_skpk );</strong></p>

<p>Becoming a bit disappointed not locating a libsodium function to compute the ed25519_pk key when ed25519_skpk is loaded with a working private key from an external source. Any assistance will be greatly appreciated.</p>

CC BY-SA 3.0
2016-03-20T10:16:07.997Z
Small nit: the Ed25519 curve is used to implement EdDSA, not ECDSA.
Pieter Wuille
CC BY-SA 3.0
2016-04-14T01:47:27.287Z
Fantastic eye for detail! Reflected the EdDSA change.
skaht
CC BY-SA 4.0
2019-12-14T21:21:23.830Z
FYI - numerous flavors of ed25519 exist. https://tools.ietf.org/html/rfc8032#section-5 documents **ed25519**, **ed25519ph**, and **ed25519ctx**. Monero and I2P use **red25519**. See https://geti2p.net/spec/proposals/146-red25519 for an I2P perspective.
skaht
<private-key><public-key><cryptography><altcoin-development>
How to generate Ed25519 public key from private key using libsodium?
skaht
# How to generate Ed25519 public key from private key using libsodium?

(Asked by: username_0 on 2016-01-19)

Not all crypto currencies are using **secp256k1** technology for keypair generation and digital signatures. **Curve25519** technology (frequently used to support ECDH key exchanges) is being used by a few other cryptocurrencies. **Ed25519** cryptography (meant to support EdDSA functionality) and Curve25519 cryptography are closely related through transformations and the trend is to start with Ed25519 keys and transform them to Curve25519 key pairs.

Been using this [reference](http://fossies.org/linux/tor/src/test/ed25519_vectors.inc) as a source of eight **ED25519\_SECRET\_KEYS** and corresponding **ED25519\_PUBLIC\_KEYS** to use as test vectors for applying Ed25519 package implementations.

Got [floodyberry/ed25519-donna](https://github.com/floodyberry/ed25519-donna) to function as expected. However, I could not compute the **ED25519\_CURVE25519\_PUBLIC\_KEYS** from the reference using ed25519-donna using its *`curved25519_scalarmult_basepoint()`* function to match. This pushed me towards trying [jedisct1/libsodium](https://github.com/jedisct1/libsodium). Got *`crypto_scalarmult_base()`* function results from libsodium to match those from ed25519-donna:-)

However, **`it is unclear how jedisct1/libsodium can be applied to generate public Ed25519 keys only from secret Ed25519 keys that are natively in an ASCII hexadecimal format`**:-( It seems that jedisct1/libsodium requires keys to always be generated from it native keypair generation process, opposed to an externally supplied private key.

Used the *sodium\_hex2bin()* to stuff an ASCII hex encoded private key from the reference into the 64 unsigned char ed25519\_skpk variable:

**sodium\_hex2bin( ed25519\_skpk, 32, ED25519\_SECRET\_KEYS[ii], 64, NULL, NULL, NULL );**

Results from the following libsodium function were as expected:

**crypto\_scalarmult\_base( curve25519\_pk, ed25519\_skpk )**

*Was a bit frustrated when I discovered that crypto\_sign\_ed25519\_sk\_to\_pk() was coded to extract the public key from ed25519\_skpk that was never initialized.*

**crypto\_sign\_ed25519\_sk\_to\_pk( ed25519\_pk, ed25519\_skpk );**

Becoming a bit disappointed not locating a libsodium function to compute the ed25519\_pk key when ed25519\_skpk is loaded with a working private key from an external source. Any assistance will be greatly appreciated.

**Tags:** private-key, public-key, cryptography, altcoin-development

> **Comments:**
> **username_1**: Small nit: the Ed25519 curve is used to implement EdDSA, not ECDSA.  
> **username_0**: Fantastic eye for detail! Reflected the EdDSA change.  
> **username_0**: FYI - numerous flavors of ed25519 exist. https://tools.ietf.org/html/rfc8032#section-5 documents **ed25519**, **ed25519ph**, and **ed25519ctx**. Monero and I2P use **red25519**. See https://geti2p.net/spec/proposals/146-red25519 for an I2P perspective.  

---

## 2 answers

### Answer by username_0 on 2016-01-20. Score: 5

It's not possible to directly compute the ed25519 public key from the private key. Instead, use the deterministic private key to create a seed, then use the seed to re-create the private key with its corresponding public key. The following code snippet assumes `ed25519_skpk` is already initialized:

```
char           hex_ed_pk[65];                                      
unsigned char  seed[crypto_sign_SEEDBYTES];                       
unsigned char  ed25519_skpk[crypto_sign_ed25519_SECRETKEYBYTES];        
unsigned char  ed25519_pk[crypto_sign_ed25519_PUBLICKEYBYTES];

// COMPUTE ED25519 PUBLIC KEY, REQUIRES ESTABLISHING A SEED
(void)crypto_sign_ed25519_sk_to_seed( seed,ed25519_skpk);                
(void)crypto_sign_seed_keypair( ed25519_pk, ed25519_skpk, seed );      
(void)sodium_bin2hex( hex_ed_pk, 65, ed25519_pk, 32 );

```


---

### Answer by username_2 on 2017-11-10. Score: 2

On libsodium > 1.0.15, the `crypto_scalarmult_ed25519_base()` can do this.


---

