OpenSSL EdDSA Specify Key Size

I need to generate some keypairs with the ed25519 curve for NodeJS’s elliptic module for a project I’m working on. After some searching, a discovered that this can be done with the following command:

openssl genpkey -algorithm ed25519 -out private.pem

However, this always generates a key of 64 characters in length. I wish to specify a certain size for the key though. Is this possible using OpenSSL? If not, could I please be pointed to a method by which to securely generate such keys with a set size elsewhere?

Also, I am very new to elliptic curve cryptography, and don’t quite yet understand how EdDSA keys are generated. So please tell me if I’ve completely failed at understanding this, and please explain where I’ve gone terribly wrong if so.

Answer

ed25519 private keys are by definition 32-bits in length. From section 5.1.5 of RFC8032:

The private key is 32 octets (256 bits, corresponding to b) of
cryptographically secure random data. See [RFC4086] for a discussion about randomness.

I don’t know where you get 64 characters in your question above. I might expect that you are looking at the encoded length – but that also doesn’t make sense.

If I do this:

openssl genpkey -algorithm ed25519 -out private.pem

Then I get a PEM encoded private key which is 119 bytes in length. This is encoded according to section 7 of RFC8410. You can look at the contents like this:

openssl asn1parse -in private.pem
    0:d=0  hl=2 l=  46 cons: SEQUENCE          
    2:d=1  hl=2 l=   1 prim: INTEGER           :00
    5:d=1  hl=2 l=   5 cons: SEQUENCE          
    7:d=2  hl=2 l=   3 prim: OBJECT            :ED25519
   12:d=1  hl=2 l=  34 prim: OCTET STRING      [HEX DUMP]:0420F897797B25D84588192CE39F0E6311954034CB80F6D8CD648A3BCBFC2346A83E

The actual raw private key itself is encoded as an OCTET STRING inside the OCTET STRING shown above (in accordance with RFC 8410). As you can see above that octet string starts at offset 12, with a header length of 2 – so the data itself is at offset 14:

openssl asn1parse -in private.pem -offset 14
    0:d=0  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]:F897797B25D84588192CE39F0E6311954034CB80F6D8CD648A3BCBFC2346A83E

Which shows you a private key of 32 bytes in length as expected.

Some software may store keys in different formats not conformant with RFC8410 (e.g. by storing the private key and public key together) – so if you’ve loaded this key into something else then that might explain where the 64 is coming from. You can’t use OpenSSL to generate those formats though.

However the bottom line is, ed25519 private keys are always 32-bits and you can’t change it. Its a fundamental property of the algorithm.

Leave a Reply

Your email address will not be published. Required fields are marked *