Erlang :cryto.generate_key() trouble

Hi,

I’m trying to generate an ED25519 public key from a secret key using Erlang’s crypto application. I’m able to generate a random keypair using:

iex(3)> {p, s} = :crypto.generate_key(:ecdh, :x25519)
{<<139, 150, 158, 47, 97, 82, 64, 37, 96, 216, 224, 34, 120, 116, 57, 178, 35,
   123, 99, 142, 109, 65, 68, 80, 236, 154, 22, 112, 0, 37, 68, 114>>,
 <<32, 123, 30, 206, 152, 213, 66, 101, 231, 22, 173, 128, 18, 84, 98, 91, 73,
   205, 66, 27, 0, 12, 241, 122, 6, 207, 155, 100, 134, 170, 29, 125>>}

But if I want just to generate a public key from an existing secret key I get the following error:

iex(4)> :crypto.generate_key(:ecdh, :x25519, s)      
** (ArgumentError) argument error
    (crypto) :crypto.ec_key_generate({:evp, :x25519}, <<32, 123, 30, 206, 152, 213, 66, 101, 231, 22, 173, 128, 18, 84, 98, 91, 73, 205, 66, 27, 0, 12, 241, 122, 6, 207, 155, 100, 134, 170, 29, 125>>)

It looks like the ec_key_generate() function is implemented as a NIF and I can’t figure out what I’m doing wrong here.

I learned now that X25519 and ED25519 public keys are derived in a different way. So you can’t actually use :crypto.generate_key(:ecdh, :x25519) to generate a ED25519 keypairs. You would need something like :crypto.generate_key(:eddsa, :ed25519), but this is currently not possible with Erlang’s crypto app.

So you can only sign/verify with ED25519, but not actually generate the keys.

:wave:

Not sure if it’s of any help, but you might be interested in trying out enacl, I had a PR that allowed to get the public key from private+seed, but it never got merged.

Hello. I think the issue is now resolved with the last OTP version. https://github.com/erlang/otp/pull/2329

We are now able to generate ed22519 keys from the crypto app.

2 Likes

I contributed that PR :slight_smile:.

I don’t think it’s part of an OTP release yet. Not that familiar with the release structure, but I think the master branch is going to be the next major version? So it may take some time.

2 Likes

I just upgraded yesterday my OTP version using asdf to take the master, so you can try out.

Erlang/OTP 23 [DEVELOPMENT] [erts-10.4.4] [source-1f6cb54c0a] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Interactive Elixir (1.9.1) - press Ctrl+C to exit (type h() ENTER for help)
:crypto.generate_key(:eddsa, :ed25519)
{<<214, 155, 88, 240, 57, 148, 244, 72, 176, 240, 144, 109, 221, 221, 231, 136,
   212, 128, 30, 246, 119, 190, 236, 1, 200, 155, 212, 213, 120, 184, 80, 53>>,
 <<20, 54, 157, 183, 196, 222, 44, 40, 247, 28, 65, 191, 0, 199, 239, 114, 80,
   255, 49, 149, 86, 229, 173, 196, 16, 5, 13, 73, 78, 180, 50, 108>>}