Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Fwd: Converting public part of 'EVP_PKEY' structure to 'unsigned char*' , and back.

728 views
Skip to first unread message

pratyush parimal

unread,
Jun 30, 2014, 12:43:13 AM6/30/14
to
Hi all,

Did anyone have any luck with this one?

Thanks,
Pratyush Parimal.

---------- Forwarded message ----------
From: pratyush parimal <pratyush...@gmail.com>
Date: Wed, Jun 25, 2014 at 10:43 AM
Subject: Converting public part of 'EVP_PKEY' structure to 'unsigned char*' , and back.
To: openss...@openssl.org


Hi all,

I was trying to use ECDH (in OpenSSL v1.0.1f) for a project, and after generating the EVP_PKEY structure, I needed to extract its public key and send it over to the other party. I was unable to find a straightforward way which worked for me.

What I tried was this:

EVP_PKEY*
extract_peerkey_3(EVP_PKEY* EVP_PKEY_both) //'both' meaning it contains public + private
{
int len = 0;

len = i2d_PUBKEY(EVP_PKEY_both, NULL); //find out required buffer length
unsigned char *buf, *p;
buf = (unsigned char*) malloc(len); //allocate
p = buf;
len = i2d_PUBKEY(EVP_PKEY_both, &p);

const unsigned char* p2 = buf;
EVP_PKEY* EVP_PKEY_public = d2i_PUBKEY(NULL, &p2, len);
if (EVP_PKEY_public == NULL)
{
handleCryptoError("d2i failed", ERR_get_error());
}

return EVP_PKEY_public;
}

The function doesn't throw an error, but when I pass the returned 'EVP_PKEY_public' structure to the function 'EVP_PKEY_derive_set_peer', I get an error message "error:10071065:elliptic curve routines:EC_POINT_cmp:incompatible objects".

When i reconstruct the EVP_PKEY using the steps EC_POINT_oct2point() -> EC_KEY_set_public_key() -> EVP_PKEY_set1_EC_KEY(), the resulting EVP_PKEY does work for me. In fact I'm able to derive the same secret on both sides using this sequence, but I feel it's too roundabout.

I also saw the following: http://marc.info/?l=openssl-users&m=116474297608094&w=2, which talks about using 'i2d_PUBKEY', but I haven't been able to make it work so far.

Is my usage of d2i_PUBKEY or i2d_PUBKEY wrong in some way? Does anyone know how to use them properly?
Any help will be appreciated.

Thanks!
Pratyush Parimal

Bala Duvvuri

unread,
Jun 30, 2014, 2:47:11 AM6/30/14
to
We do the below for this operation:

1>How we convert public part of 'EVP_PKEY' structure to 'unsigned char*

//Extract a public key from a PKEY struct.

ec_copy_public(EVP_PKEY *pKey, uint8_t *keybuf)

EC_KEY *pEcKey;
uint8_t encoded_key[MAX_KEYLEN_X962];
uint8_t *pMem;
int keylen = 0;

/* Get the EC_KEY struct pointer. */
pEcKey = (EC_KEY *)EVP_PKEY_get0(pKey);

/* Extract the private key from the EC key struct. */
if (pEcKey) {
pMem = encoded_key;
keylen = i2o_ECPublicKey(pEcKey, &pMem);

/* Copy the decoded public key into the provided buffer. */
if (keylen) {
keylen = ipsec_ec_x962_decode(pEcKey, encoded_key, keylen, keybuf); //fn defined in the end
}
}
}

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2>How we get the peerkey to pass to EVP_PKEY_derive_set_peer(pctx, peerkey);


//The below function takes a character string as input and converts it to a public key.

Prototype:

EVP_PKEY *ec_create_static_public(uint8_t *public_key, int keylen, int curve)

EC_KEY *pEcKey = NULL;
EC_KEY *pEcKeyTemp;
uint8_t encoded_key[MAX_KEYLEN_X962];
const uint8_t *pMem;
EC_POINT *pEcPoint = NULL;
BIGNUM *pBignum = NULL;
EVP_PKEY *pKey = NULL;


switch(curve) {
case NID_secp384r1:
pEcKey = EC_KEY_new_by_curve_name(curve);
break;
default:
pEcKey = NULL;
}

/* Encode the public key string into X9.62 format. */ defined later

ec_x962_encode(pEcKey, public_key, keylen, encoded_key);

pMem = encoded_key;
pEcKeyTemp = pEcKey;

/* Place the encoded public key in the EC_KEY struct. */
pEcKeyTemp = o2i_ECPublicKey(&pEcKeyTemp, &pMem, keylen);

/* Allocate an EVP_PKEY struct for the EC_KEY. */
pKey = EVP_PKEY_new();

/* Assign the public key to the EVP_PKEY wrapper. */
EVP_PKEY_assign_EC_KEY(pKey, pEcKey);

pEcKey = NULL;

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


int
ec_x962_encode(EC_KEY *pEcKey, uint8_t *key, int keylen, uint8_t *conv)
{
point_conversion_form_t form;

/* Get the conversion format. */
form = EC_KEY_get_conv_form(pEcKey);

/* Make sure the format is supported. If so, the first byte of the encoded
data will be the format identifier. */
switch (form) {
case POINT_CONVERSION_UNCOMPRESSED:
conv[0] = POINT_CONVERSION_UNCOMPRESSED;
conv++;
break;
case POINT_CONVERSION_COMPRESSED:
case POINT_CONVERSION_HYBRID:
default:
keylen = 0;
break;
}

/* If the format is valid, copy the key into the destination buffer. */
if (keylen) {
memcpy(conv, key, keylen);
keylen++;
}

return(keylen);
}


Thanks,
Bala

--------------------------------------------
On Sun, 6/29/14, pratyush parimal <pratyush...@gmail.com> wrote:

Subject: Fwd: Converting public part of 'EVP_PKEY' structure to 'unsigned char*' , and back.
To: openss...@openssl.org
Date: Sunday, June 29, 2014, 11:43 PM

Hi all,
Did anyone have any luck with this
one?
Thanks,Pratyush Parimal.
properly?Any help will be
appreciated.
Thanks!
Pratyush Parimal




______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openss...@openssl.org
Automated List Manager majo...@openssl.org

Thulasi Goriparthi

unread,
Jun 30, 2014, 3:28:36 AM6/30/14
to
Guessing the context that is sent to EVP_PKEY_derive_set_peer is initialized/created with a pkey belonging to different group.

In other words, EC keys of both parties in DH are not of the same group.

Peng Liu

unread,
Oct 30, 2015, 2:48:52 AM10/30/15
to
Hi, Bala Duvvuri,

I read this post and follow your code. It doesn't work. One thing I am confused is that in the function of ec_x962_encode(), the first byte of pEcKey is the conversion format, why do you still set the first byte of conv to the conversion format and use memcpy to copy the whole key string to conv? In that way, the first 2 bytes will be the convert format. It is duplicate byte.
0 new messages