I'm using mbed TLS for ECDH key agreement using Curve25519. The private and public keys are stored and transmitted as Hex strings as easily generated with mbed TLS. Those strings are big-endian. This worked quite fine so far.

Now someone tried to create key-pairs using OpenSSL

openssl genpkey -algorithm X25519 -out priv.pem
openssl pkey -in priv.pem -pubout -out pub.pem

and extracted the keys directly from there to Hex strings. So just copying the key bytes using an ASN.1 viewer. We were of the impression that this should work flawlessly, as I2OSP defines big-endian for key encoding.

Obviously, it didn't work but we need to reverse the byte order in the string to be able to parse a valid key pair.

I'm tended to believe that OpenSSL does this correctly, but started to dig into the RFCs to find proof and some clarification, why this should be different for X25519 (and probably X448) to the key for RSA or the other EC curves (secp...)

how a private key is encoded is left for the document describing the algorithm itself

but also refers to Asymmetric Key Packages which again refers to the document that defines the algorithm. While RFC5915 for ECPrivateKey defines a big-endian byte order (I2OSP), RFC7748 and RFC8031 both only mention little-endian byte order for the formatting of the keys. - draft-ietf-curdle-pkix-10

Now, this somehow confirms to me, that OpenSSL is right, but I'm still missing the reason to why one should not just use network-order as done by every other algorithm out their, but the direct opposite.

Any thoughts and further information on that?


the *25519 algos specify little-endian. I myself was taken aback by that, so I tried to figure out why. My understanding is that the point of Ed25519 and its relatives is to pick out of the wide space of possible curves and implementations a subset both efficient and resistant to a number of attacks. To that end, it specifies both calculation steps, primitives, and the representation to be used - which is little endian.

So, the key representation you get here is exactly as used in the algorithm. The only point in reversing it (and needing to reverse again before use) would be the consistency of key representation, and some distaste for little-endian.

And because we're all trying to be mature, someone made the decision to keep the key as the algorithm would expect it for use, to save others unnecessary conversions and confusion.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.