Ed25519 private key from seed

can i generate ed25519 keypair from seed using crypto app or public_key?

{Priv, Pub} = crypto:generate_key(eddsa, ed25519). should work.

I’ve also done the following the generate an ed25519-compatible private key from a crypto random number if that’s what you meant by “seed", but then you would need to derive the public key from the private key (scalar multiplication with the base point).

new() →

PrePrivate = crypto:strong_rand_bytes(32),

%% match out the first byte and the 31st byte for clamping

<<First:8, Middle:240/bitstring, Last:8>> = PrePrivate,

ReplaceFirst = First band 248,

ReplaceLast = (Last band 127) bor 64,

%% return the clamped 32 bytes as a curve 25519 compatible and

%% hopefully secure key

<<ReplaceFirst:8, Middle:240/bitstring, Last:8>>.

  • johnk

Short answer is no there is no API for that in crypto or public_key.

For the sake of the longer answer I will assume that by “seed” you mean seed in the normal EdDSA way. I.e. an EdDSA key pair is generated from a seed by first transforming the seed into a private key (a scalar), and then using that scalar to calculate the corresponding public key!

For ed25519 the seed is normally 32-bytes, and then you proceed to compute the private key by hashing the seed using SHA512 and selecting the first 32-bytes of this hash. Interpret the resulting 32-byte value as a little-endian integer. The final step is clamping (the process of making sure this result is in the prime field and isn’t in the inner twist of the elliptic curve) and after that you have the private key.
(Note: the function given by @frumiousj is only the the clamping, it misses the hashing part.)

To get the public key you multiply the private key by ‘G’ (the curve’s base point) and then compress it (store the x component + parity if I remember correctly.

The first library for doing this that comes to mind is enacl ( GitHub - jlouis/enacl: Erlang bindings for NaCl / libsodium ) which I have used in the past, it isn’t recently updated, but I have no better personal recommendations. Perhaps someone else can chime in?

For educational purposes there is also a little library I wrote to wrap my head around some EC crypto, it is pure Erlang and thus not very performant: GitHub - hanssv/ec_utils: Elliptic curve utilility functions in pure Erlang

Good point @hanssv. Updated my code:

new() →
PrePrivate = crypto:strong_rand_bytes(32),

ExpandedSeed = crypto:hash(sha512, PrePrivate),

<<LeftSeed:32/binary, RightSeed:32/binary>> = ExpandedSeed,

%% match out the first byte and the 31st byte for clamping
<<First:8, Middle:240/bitstring, Last:8>> = LeftSeed,

ReplaceFirst = First band 248,
ReplaceLast = (Last band 127) bor 64,

%% return the clamped 32 LH bytes as a curve 25519 compatible and
%% hopefully secure key
{<<ReplaceFirst:8, Middle:240/bitstring, ReplaceLast:8>>, RightSeed}.

  • johnk