Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I obtain the public key from an ECDSA private key in OpenSSL?

I am providing this sample application to show my problem

#include <stdio.h>
#include <stdlib.h>
#include <openssl/ec.h>
#include <openssl/bn.h>

int main()
{
     EC_KEY *pkey = NULL;
     EC_POINT *pub_key = NULL;
     const EC_GROUP *group = NULL;
     BIGNUM start;
     BIGNUM *res;
     BN_CTX *ctx;

     BN_init(&start);
     ctx = BN_CTX_new();

     res = &start;
     BN_hex2bn(&res,"3D79F601620A6D05DB7FED883AB8BCD08A9101B166BC60166869DA5FC08D936E");
     pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
     group = EC_KEY_get0_group(pkey);
     pub_key = EC_POINT_new(group);

     EC_KEY_set_private_key(pkey, res);

     assert(EC_POINT_bn2point(group,res, pub_key, ctx)); // Null here

     EC_KEY_set_public_key(pkey, pub_key);


    return 0;
}

What I am trying to do, is to display the Public key from a private key(should an elliptic private key). I did not know how to do it until I encountered a similar problem

How do I feed OpenSSL random data for use in ECDSA signing?

Which is from where I pointed myself how to get the public key and to use EC_POINT_bn2point instead of hex2point which internally does BN_hex2bn according to the OpenSSL source.

So, why is EC_POINT_bn2point returning NULL? I am seriously considering recompiling OpenSSL and putting some debug routines to figure out why it fails.

like image 978
farmdve Avatar asked Sep 18 '12 16:09

farmdve


People also ask

Does OpenSSL support Ecdsa?

The OpenSSL EC library provides support for Elliptic Curve Cryptography (ECC). It is the basis for the OpenSSL implementation of the Elliptic Curve Digital Signature Algorithm (ECDSA) and Elliptic Curve Diffie-Hellman (ECDH).


2 Answers

Working example:

// using figures on: https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses
// gcc -Wall ecdsapubkey.c -o ecdsapubkey -lcrypto
#include <stdio.h>
#include <stdlib.h>
#include <openssl/ec.h>
#include <openssl/obj_mac.h>
#include <openssl/bn.h>

int main()
{
     EC_KEY *eckey = NULL;
     EC_POINT *pub_key = NULL;
     const EC_GROUP *group = NULL;
     BIGNUM start;
     BIGNUM *res;
     BN_CTX *ctx;

     BN_init(&start);
     ctx = BN_CTX_new(); // ctx is an optional buffer to save time from allocating and deallocating memory whenever required

     res = &start;
//     BN_hex2bn(&res,"3D79F601620A6D05DB7FED883AB8BCD08A9101B166BC60166869DA5FC08D936E");
     BN_hex2bn(&res,"18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725");
     eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
     group = EC_KEY_get0_group(eckey);
     pub_key = EC_POINT_new(group);

     EC_KEY_set_private_key(eckey, res);

     /* pub_key is a new uninitialized `EC_POINT*`.  priv_key res is a `BIGNUM*`. */
     if (!EC_POINT_mul(group, pub_key, res, NULL, NULL, ctx))
       printf("Error at EC_POINT_mul.\n");

//     assert(EC_POINT_bn2point(group, &res, pub_key, ctx)); // Null here

     EC_KEY_set_public_key(eckey, pub_key);

     char *cc = EC_POINT_point2hex(group, pub_key, 4, ctx);

     char *c=cc;

     int i;

     for (i=0; i<130; i++) // 1 byte 0x42, 32 bytes for X coordinate, 32 bytes for Y coordinate
     {
       printf("%c", *c++);
     }

     printf("\n");

     BN_CTX_free(ctx);

     free(cc);

     return 0;
}

See also http://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography - for library

http://www.nsa.gov/ia/_files/ecdsa.pdf - for algorithm

http://cs.ucsb.edu/~koc/ccs130h/notes/ecdsa-cert.pdf - for math

like image 29
Doru Georgescu Avatar answered Sep 18 '22 19:09

Doru Georgescu


An ECDSA private key d (an integer) and public key Q (a point) is computed by Q = dG, where G is a non-secret domain parameter. Suite B Implementer’s Guide to FIPS 186-3 (ECDSA) describes ECDSA in detail.

OpenSSL uses ECDSA_generate_key to generate a key pair. What it does is generate a private key randomly, and then it does the Q = dG multiplication to compute the public key:

/* pub_key is a new uninitialized `EC_POINT*`.  priv_key is a `BIGNUM*`. */
if (!EC_POINT_mul(ecdsa->group, pub_key, priv_key, NULL, NULL, ctx)) goto err;

So you can do the same thing. If I had the private key, I'd set it as the private key in an EC_KEY or ECDSA struct. Then I'd configure the domain parameters on it. And finally I'd do the EC_POINT_mul to get the public key point.

like image 109
indiv Avatar answered Sep 21 '22 19:09

indiv