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.
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).
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With