Skip to content

Instantly share code, notes, and snippets.

@cosard
Created July 12, 2018 11:50
Show Gist options
  • Save cosard/56e6eaf127884804987eda9efc6ee840 to your computer and use it in GitHub Desktop.
Save cosard/56e6eaf127884804987eda9efc6ee840 to your computer and use it in GitHub Desktop.
Openssl Elliptic Curve Cryptography (ECC) Example
// Cosar Dindar
// to use 192 bits curve compile with -DUSE_192
// or -DUSE_256 for 256 bits curve
// to use predefined points use -DUSE_PREDEFINED_POINTS or draft curve params will be used
// to create new private and public key use -DGENERATE_KEY otherwise embedded keys will be used
// link with -lssl -lcrypto
// -- ex. gcc ecc_sample.c -g -o ecc_sample -lssl -lcrypto -DUSE_256 -DUSE_PREDEFINED_POINTS -DGENERATE_KEY
#include <string.h>
#include <openssl/ec.h> // for EC_GROUP_new_by_curve_name, EC_GROUP_free, EC_KEY_new, EC_KEY_set_group, EC_KEY_generate_key, EC_KEY_free
#include <openssl/ecdsa.h> // for ECDSA_do_sign, ECDSA_do_verify
#include <openssl/obj_mac.h> // for NID_secp192k1
#define BN_OUTPUT_SIZE (8)
static int create_signature(unsigned char* hash)
{
int function_status = -1;
EC_KEY *eckey=EC_KEY_new();
if (NULL == eckey)
{
printf("Failed to create new EC Key\n");
function_status = -1;
}
else
{
BN_CTX *ctx = NULL;
BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *z = NULL, *order = NULL;
EC_GROUP *group = NULL;
EC_POINT *P = NULL;
BIGNUM *private_key = NULL, *pub_x = NULL, *pub_y = NULL;
EC_POINT *public_key = NULL;
EC_KEY *prv_key = NULL, *pub_key = NULL;
ctx = BN_CTX_new();
p = BN_new();
a = BN_new();
b = BN_new();
x = BN_new();
y = BN_new();
z = BN_new();
order = BN_new();
pub_x = BN_new();
pub_y = BN_new();
#if USE_PREDEFINED_POINTS
#if USE_192
BN_hex2bn(&p, "fffffffffffffffffffffffffffffffeffffffffffffffff");
printf("P:\t%s \n", BN_bn2hex(p) );
BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC");
printf("a:\t%s \n", BN_bn2hex(a) );
BN_hex2bn(&b, "64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1");
printf("b:\t%s \n", BN_bn2hex(b) );
BN_hex2bn(&x, "188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012");
printf("x:\t%s \n", BN_bn2hex(x) );
BN_hex2bn(&y, "07192b95ffc8da78631011ed6b24cdd573f977a11e794811");
printf("y:\t%s \n", BN_bn2hex(y) );
BN_hex2bn(&order, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831");
printf("order:\t%s \n", BN_bn2hex(order) );
#elif USE_256
/* curve points grabbed from Atmel Start example */
BN_hex2bn(&p, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF");
printf("P:\t%s \n", BN_bn2hex(p) );
BN_hex2bn(&a, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC");
printf("a:\t%s \n", BN_bn2hex(a) );
/* b point is not available in Atmel Start project, this point is grabbed from somewhere else */
BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B");
printf("b:\t%s \n", BN_bn2hex(b) );
BN_hex2bn(&x, "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296");
printf("x:\t%s \n", BN_bn2hex(x) );
BN_hex2bn(&y, "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5");
printf("y:\t%s \n", BN_bn2hex(y) );
BN_hex2bn(&order, "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551");
printf("order:\t%s \n", BN_bn2hex(order) );
#else
fprintf(stderr, "You must define either USE_192 or USE_256\n");
goto free;
#endif
group = EC_GROUP_new_curve_GFp(p, a, b, ctx);
//EC_GROUP_get_curve_GFp(group, p, a, b, ctx);
P = EC_POINT_new(group);
EC_POINT_set_to_infinity(group, P);
if(EC_POINT_is_at_infinity(group, P))
printf("P is at infinity\n");
EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx);
if(EC_POINT_is_on_curve(group, P, ctx))
printf("P is on the curve\n");
EC_GROUP_set_generator(group, P, order, BN_value_one());
EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx);
#else
#if USE_192
group= EC_GROUP_new_by_curve_name(NID_secp192k1);
#elif USE_256
group= EC_GROUP_new_by_curve_name(NID_secp256k1);
#else
fprintf(stderr, "You must define either USE_192 or USE_256\n");
goto free;
#endif
#endif
/* Checks whether the parameter in the EC_GROUP define a valid ec group */
if(!EC_GROUP_check(group,ctx)) {
fprintf(stdout, "EC_GROUP_check() failed\n");
goto free;
}
else {
fprintf(stdout, "Valid EC group\n");
}
if (NULL == group)
{
printf("Failed to create new EC Group\n");
function_status = -1;
goto free;
}
else
{
int set_group_status = EC_KEY_set_group(eckey,group);
const int set_group_success = 1;
if (set_group_success != set_group_status)
{
printf("Failed to set group for EC Key\n");
function_status = -1;
goto free;
}
else
{
#ifdef GENERATE_KEY
const int gen_success = 1;
int gen_status = EC_KEY_generate_key(eckey);
if (gen_success != gen_status)
{
printf("Failed to generate EC Key\n");
function_status = -1;
}
else
{
/* Verifies that a private and/or public key is valid */
if (!EC_KEY_check_key(eckey)) {
fprintf(stdout, "EC_KEY_check_key() failed\n");
}
else {
fprintf(stdout, "Generated Keys:\n\n");
private_key = (BIGNUM *)EC_KEY_get0_private_key(eckey);
if(private_key)
fprintf(stdout, "private key = %s\n",BN_bn2hex(private_key));
public_key = (EC_POINT *)EC_KEY_get0_public_key(eckey);
if(public_key) {
if(EC_POINT_get_affine_coordinates_GFp(group,public_key,pub_x,pub_y,ctx) == 1)
if(pub_x && pub_y)
fprintf(stdout, "public key = ( %s , %s )\n",
BN_bn2hex(pub_x),BN_bn2hex(pub_y));
else
fprintf(stdout, "EC_POINT_get_affine_coordinates_GFp Failed!\n");
}
private_key = NULL;
}
}
#else
//eckey = EC_KEY_new_by_curve_name(NID_secp192k1);
private_key = BN_new();
#if USE_256
/* private and public keys from Atmel Start project */
BN_hex2bn(&private_key, "9043c2ae427713e868d912862c7bbf58611507f730f0360b2d95c9c42da00390");
BN_hex2bn(&pub_x, "23551BC3DB0A2418B010F313959DAB96C0AE9AA43DC742A9B6C8D773E029942A");
BN_hex2bn(&pub_y, "2C712546615518F95B3CE1B1D171623FE689084ACE032852F2E14EA5C43784F5");
#elif USE_192
BN_hex2bn(&private_key, "1A8D598FC15BF0FD89030B5CB1111AEB92AE8BAF5EA475FB");
BN_hex2bn(&pub_x, "62B12D60690CDCF330BABAB6E69763B471F994DD702D16A5");
BN_hex2bn(&pub_y, "63BF5EC08069705FFFF65E5CA5C0D69716DFCB3474373902");
#endif
EC_KEY_set_private_key(eckey, private_key);
//public_key = EC_POINT_hex2point(EC_KEY_get0_group(eckey), "FD4F787DF52564D5282F4C4B06FF78965B79DCCB8873D065C881C4E12F38A78A", public_key, ctx);
//EC_KEY_set_public_key(eckey, public_key);
//EC_POINT_free(public_key);
EC_KEY_set_public_key_affine_coordinates(eckey, pub_x, pub_y);
fprintf(stdout, "Embedded Keys:\n\n");
if(private_key)
fprintf(stdout, "private key = %s\n",BN_bn2hex(private_key));
if(pub_x && pub_y)
fprintf(stdout, "public key = ( %s , %s )\n",
BN_bn2hex(pub_x),BN_bn2hex(pub_y));
/* Verifies that a private and/or public key is valid */
if (!EC_KEY_check_key(eckey)) {
fprintf(stdout, "EC_KEY_check_key() failed\n");
goto free;
}
else {
fprintf(stdout, "Valid EC_KEY.\n");
}
#endif
}
}
ECDSA_SIG *signature = ECDSA_do_sign(hash, strlen(hash), eckey);
if (NULL == signature)
{
printf("Failed to generate EC Signature\n");
function_status = -1;
}
else
{
/* TO USE PRECALCULATED R AND S VALUES OPEN TWO LINES BELOW AND PUT THE VALUES INTO THEM */
//BN_hex2bn(&signature->r, "09260C8CFD9017732D7B2196F223CAC93CF4B9B52EEE5614E4868A9E5E6F0DDE");
//BN_hex2bn(&signature->s, "275BED75C1FC4F260E269350344034D0E8020475F01640DDA171003F14F964E3");
printf("Signature R: %s\n", BN_bn2hex(signature->r));
printf("Signature S: %s\n", BN_bn2hex(signature->s));
int verify_status = ECDSA_do_verify(hash, strlen(hash), signature, eckey);
const int verify_success = 1;
if (verify_success != verify_status)
{
printf("Failed to verify EC Signature\n");
function_status = -1;
}
else
{
printf("Verifed EC Signature\n");
function_status = 1;
}
}
free:
EC_GROUP_free(group);
EC_KEY_free(eckey);
BN_CTX_free(ctx);
BN_free(p);
BN_free(a);
BN_free(b);
BN_free(x);
BN_free(y);
BN_free(z);
BN_free(order);
BN_free(pub_x);
BN_free(pub_y);
BN_free(private_key);
EC_POINT_free(P);
}
return function_status;
}
int main( int argc , char * argv[] )
{
/* this is the hash of the message "abc" */
unsigned char hash[] = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
int status = create_signature(hash);
return(0) ;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment