How to get public key from ECDSA private key in OpenSSL?

I provide 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'm trying to do is display the public key from the private key (there must be an elliptical private key). I did not know how to do this until I ran into a similar problem.

How can I pass arbitrary OpenSSL data for use when signing an ECDSA?

This is where I showed myself how to get the public key and use EC_POINT_bn2point instead of hex2point, which internally executes BN_hex2bn according to the OpenSSL source code.

So why does EC_POINT_bn2point return NULL? I'm seriously thinking of recompiling OpenSSL and putting some debugging routines to find out why it fails.

+4
source share
2 answers

The private key ECDSA d (integer) and the public key Q (dot) are calculated through Q = dG, where G is an unclassified domain parameter. BB Developer's Guide for FIPS 186-3 (ECDSA) details ECDSA.

OpenSSL uses ECDSA_generate_key to create a key pair. What it does is generate a private key randomly, and then multiply Q = dG by computing 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. If I had a private key, I would set it as a private key in the EC_KEY or ECDSA structure. Then I will configure the domain settings on it. And finally, I would do EC_POINT_mul to get the public key point.

+7
source

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 the library

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

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

+4
source

Source: https://habr.com/ru/post/1434888/


All Articles