3

I am attempting to extract a public key from a private key using ED25519 with Go.

I pass my private key byte value into my method, create a new ed25519 private key struct from it, and then use the .Public() method to retrieve the public key.

pk := ed25519.PrivateKey(privateKey).Public()
cpk, ok := pk.(ed25519.PublicKey)
if !ok {
    return nil, errors.New("problem casting public key to ed25519 public key")
}

It's not erroring but the resulting public key byte is always empty, is there something I'm doing incorrectly when creating the private key struct?

mybrave
  • 1,662
  • 3
  • 20
  • 37
N P
  • 2,319
  • 7
  • 32
  • 54

1 Answers1

2

The ed25519 package has this important comment in the overview:

... unlike RFC 8032's formulation, this package's private key representation includes a public key suffix to make multiple signing operations with the same key more efficient. This package refers to the RFC 8032 private key as the “seed”.

This means that it uses the following equivalences and terminology:

  • RFC 8032 private key: 32 bytes, known as "seed" in this package
  • RFC 8032 private key and public key concateneated: 64 bytes, known as "private key" in this package

If you already have a 64 byte slice consisting of RFC 8032 <private key><public key>, you can use the code in your question.

If you only have the a 32 byte slice consisting of RFC 8032 <private key>, you need to calculate the public key as follows:

// Compute the full 64 byte <private key><public key> from the private key
priv := ed25519.NewKeyFromSeed(32bytePrivateKey)

// Print out the public key (the last 32 bytes)
fmt.Println(priv.Public())

Please note: ed25519.PrivateKey and ed25519.PublicKey are both type []byte.

Marc
  • 19,394
  • 6
  • 47
  • 51
  • In my tests this seems to bring back a different public key to the one that is associated with the private key. My tests pass if I do publicKey := make([]byte, ed25519.PublicKeySize) copy(publicKey, pk) With my private key, is this incorrecct? – N P May 14 '20 at 11:08
  • Something is wrong. In the go package, the first 32 bytes of `ed25519.PrivateKey` are the private key (as defined by RFC 8032), the last 32 bytes are the public key (again, as defined by the RFC). – Marc May 14 '20 at 15:15