Correct method to generate a Curve25519 keypair

Alexander Lyon arlyon at
Thu Jun 28 17:25:23 CEST 2018

I use use gcry_mpi_dump during debugging so I can check the hex values in a break point. It just prints a hex to stdout (or err not sure). 

As for extracting the q value, I use gcry_sexp_extract_param. the whole process looks something like this:


gcry_mpi_t mpi_Curve_pub = gcry_mpi_new( 0 );
gcry_mpi_t mpi_Curve_priv;

gcry_sexp_build( &sexp_genkey_params, NULL,
                 "    (ecc"
                 "        (curve \"Curve25519\")"
                 "        (flags djb-tweak comp)"
                 "    )"
                 ")" );

gcry_sexp_t sexp_Curve25519_pair;
gcry_pk_genkey( &sexp_Curve25519_pair, sexp_genkey_params );

// the public key is a point stored compressed (determined by the 0x40 prefix)
// in an mpi and it will need to be decompressed
gcry_mpi_t mpi_Curve_pub_compressed;
gcry_sexp_extract_param( sexp_Curve25519_pair, NULL, "qd",
                         &mpi_Curve_pub_compressed, &mpi_Curve_priv, NULL );

// to decompress, we decode it into a point
// then extract the X and discard the rest
gcry_mpi_point_t point_Curve_pub = gcry_mpi_point_new( 0 );
gcry_ctx_t ctx_curve;
gcry_mpi_ec_new( &ctx_curve, NULL, "Curve25519" );
gcry_mpi_ec_decode_point( point_Curve_pub, mpi_Curve_pub_compressed, ctx_curve );

// we extract x, y and z but only need x because
// curve only uses the x coordinate. y and z are discarded.
gcry_mpi_t mpi_Curve_pub_y = gcry_mpi_new( 0 );
gcry_mpi_t mpi_Curve_pub_z = gcry_mpi_new( 0 );

gcry_mpi_point_snatch_get( mpi_Curve_pub, mpi_Curve_pub_y, mpi_Curve_pub_z, point_Curve_pub );

gcry_sexp_release( sexp_genkey_params );
gcry_sexp_release( sexp_Curve25519_pair );
gcry_mpi_release( mpi_Curve_pub_y );
gcry_mpi_release( mpi_Curve_pub_z );
gcry_mpi_release( mpi_Curve_pub_compressed );

uint8_t p_bytes_Curve[32];

error = gcry_mpi_print( GCRYMPI_FMT_USG, p_bytes_Curve, 32, NULL, mpi_Curve_pub );

// Curve25519 is little-endian
reverse_buffer( p_bytes_Curve, 32 );


At that point you'll have the generated private key stored in binary in the p_bytes_Curve buffer.

Hope that helps


> On 28 Jun 2018, at 16:11, Stef Bon <stefbon at> wrote:
> Op do 28 jun. 2018 om 15:57 schreef Alexander Lyon <arlyon at>:
>> A little late, but as a follow up to this, I managed to find the solution. The generated keys are valid but Curve25519 is little-endian and printing it to a buffer is big-endian so the hex dumped by gcry_mpi_dump is in reverse. It was as easy as reversing the buffer when appropriate. This allowed me to extract the public key binary.
> Ok, that explains the remark in "curve25519-sha256 at 4.3
> Shared secret generation ":
> "This conversion follows the network byte order."
> Thanks for sharing this. You're helping me with implementing it in my
> application.
> Some questions: the public key is shared with the other side. This is
> for ecc/ed25519 available in the s-exp created by genkey as "q-value".
> How did you extract
> this "q-value"?
> You're using gcry_mpi_dump. Does this the right tool for this?
> Comments in the documentation say that
> "Dump the value of a in a format suitable for debugging to Libgcrypt’s
> logging stream."
> Stef
> _______________________________________________
> Gcrypt-devel mailing list
> Gcrypt-devel at

More information about the Gcrypt-devel mailing list