Wow, that is a lot of good information. Thanks, Matt. And I am still trying to digest the first paragraph. So do you mean the R value that I mentioned is actually the public key? And if I was provided with a private key, are the following lines of code appropriate to compute the public key and get its x-y coordinates?
EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_secp256k1); if(eckey == NULL) { printf("ERROR: NULL EC_KEY!\r\n"); } else { BIGNUM *retbn; retbn = BN_bin2bn(tempkey,32,NULL); // tempkey is an array of 32 u_char if(EC_KEY_set_private_key(eckey,retbn)!=1) { printf("ERROR: Fail to set private key!\r\n"); } EC_POINT* pub_key = EC_POINT_new(EC_KEY_get0_group(eckey)); if(EC_POINT_mul(EC_KEY_get0_group(eckey),pub_key,retbn,NULL,NULL,NULL) != 1) { printf("ERROR: Fail to generate public key!\r\n"); } if(EC_KEY_set_public_key(eckey,pub_key) != 1) { printf("ERROR: Can't set public key!\r\n"); } BIGNUM *x_coord = BN_new(); BIGNUM *y_coord = BN_new(); // IS THIS THE RIGHT WAY TO GET X-Y COORDINATES? if(EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(eckey), EC_KEY_get0_public_keyeckey), x_coord, y_coord, NULL)!=1) { printf("ERROR: Fail to get affine coordinates!\r\n"); } } Regards, Chuong D. Khuc On 5/24/12 5:40 PM, "Matt Caswell (fr...@baggins.org)" <fr...@baggins.org> wrote: >On 24/05/12 14:40, Khuc, Chuong D. wrote: >> Hello, >> I was able to sign my message using the ECDSA 256 function from openssl: >> ECDSA_SIG *signature = ECDSA_do_sign( &message[0], message_length, >>eckey); >> And the sign is verified to be valid also. And my question is about >> the compression of the signature. I understand that the signature has >> an r value and an s value. And there is a way to compress the r value >> to a temporary elliptic curve point R. And the value of curve point R >> is dependent on the LSB of the y-coordinate somehow. So does anyone >> know how to go from (r, s) to a compressed (R,s) in openssl? Thank you >> very much. >> >> Regards, >> >> Chuong D. Khuc >> >> >I think perhaps your are confusing a couple of things. > >A point on an elliptic curve has an x and a y co-ordinate. The ECDSA >signing algorithm constructs a random point on the curve, (what you >called R), performs various calculations and then emits r and s. The >value r is simply the x co-ordinate of the random point without the y >value - so in that sense it is already "compressed". > >However what you are describing sounds to me like the point compression >that you can perform on an ECDSA curve generator (or in fact any point >on the curve including the public key). The generator forms part of the >ECDSA parameters. > >A point on the curve simply consists of its x and y co-ordinates. Now >for any given x co-ordinate of a valid point on the curve there cannot >be more than 2 valid y co-ordinates and so it turns out that it is >sufficient to only hold the least significant bit of y to distinguish >between the two possibilities. > >ECDSA recognises three ways of encoding a point: compressed, >uncompressed and hybrid. This is represented by the >point_conversion_form_t enum in OpenSSL (defined in ec.h): > > typedef enum { > /** the point is encoded as z||x, where the octet z specifies > * which solution of the quadratic equation y is */ > POINT_CONVERSION_COMPRESSED = 2, > /** the point is encoded as z||x||y, where z is the octet 0x02 >*/ > POINT_CONVERSION_UNCOMPRESSED = 4, > /** the point is encoded as z||x||y, where the octet z specifies > * which solution of the quadratic equation y is */ > POINT_CONVERSION_HYBRID = 6 > } point_conversion_form_t; > > >If you want to use compressed form for points you can do so by using the >following function: > >void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform); > >There is also an equivalent "get" function: > >point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key); > > >These functions just call the similar functions defined on the >underlying EC_GROUP object (i.e. the curve itself). This only makes a >difference when a point is converted into some external format. For >example it is used when calling the following: > > int i2d_ECPKParameters(const EC_GROUP *x, unsigned char **out); > > >This creates a DER encoded structure to hold the public parameters for >the curve - including the generator encoded according to the point >conversion form that you specified. > >Similarly the following function DER encodes a private key (which is >just a number), along with the public key (which is a point). The public >key will be encoded according to the point conversion form that you >specified: > >int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) > > >You can also encode EC_POINT objects directly using: > > BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *, > point_conversion_form_t form, BIGNUM *, BN_CTX *); >or > size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p, > point_conversion_form_t form, > unsigned char *buf, size_t len, BN_CTX *ctx); > >These convert an EC_POINT object (such as a public key) into a BIGNUM >or an octet string respectively, encoded according to the specified >point conversion form. > >Hope that helps, > >Matt > > >______________________________________________________________________ >OpenSSL Project http://www.openssl.org >User Support Mailing List openssl-users@openssl.org >Automated List Manager >majordomo@openssl.org______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager majord...@openssl.org