Incompatibility between X25519 key created with OpenSSL

I’m using mbedTLS to do ECDH using the Curve25519. The private and public keys I want to create using the openssl (1.1.0) cmdline tool. Starting with the private key, I’m experience problems that I think originate from different encoding/format in the corresponding octet strings.

openssl genpkey -algorithm X25519 -outform DER -out privKey1.der
openssl pkey –in privKey1.der –outform DER –pubout –out key1.pub

To use the keys in mbedTLS, I extract the octet string as bytes from the certificate and use mbedtls_mpi_read_binary to load it into mbedtls_pk_ec->d. After that the mbedtls_exp_check_privkey fails as the key is not a multiple of 8.

After some debugging of the openssl app I found that it seems to put the key into the file in little endian format. Therefore I inverted the bytes of the private key. Now the privkey check succeeds but ECDH fails. I assume the public and private keys don’t match any more.

I was of the impression that any integer in a ASN.1 file is in big-endian format and can be read with mbedTLS as is.

Does anyone know, what happens here and how the openSSL genpkey feature can be used alongside mbedTLS ECDH?

Thanks!

Hi Timo,
At the moment, Mbed TLS has only partial support for curve 25519. It supports the 25519 primitive, but not ht efull implementation of the curve, including parsing the keys, as defined in draft-ietf-curdle-pkix.
Because of that, it is possible that the byte order is not as you would expect. As Mbed TLS work with Big Endian MPI. The ASN1 defines OCTET_STRING as “For the keys defined in this document, the private key is always an opaque byte sequence”
You will probably need to bitmask your key, in order to get a proper key.

Regards,
Mbed TLS Team member
Ron

Hi Ron,

thanks for you repsonse. I’m fully aware that mbed TLS doesn’t provide the parsing, yet. That’s why we created the keys using openSSL and are trying to inject them in a big-endian hex string.

Regarding the draft-ietf-curdle-pkix, it also refers to the document that defines the algorithm. For X25519 it seems that this is RFC8031 or RFC7748. Both define a little-endian byte order, which matches with OpenSSL.
But I’m struggeling with this, as this would be more or less the only algorithm that stores the key in a little-endian order and not in network-order. I actually expected this to use I2OSP as other curves. But sometimes there is no reason, someone defined it like that and case closed.

Do you have plans to integrate draft-ietf-curdle-pkix into mbed TLS in the near future? Or the other way round, are you open for pull requests on this topic? Or are there bigger discussions to be hold on how to integrate those algorithms?

Thanks!

Timo

Hi Timo,
As an open source project, we are always open for Pull Requests from the community.

We do intend on having a full implementation of x25519, in the future, but it will probably not be soon enough for you.
Regards,
Mbed TLS Team member
Ron