#include #include #include int __ec_point_size = sizeof(struct ec_point); int32_t curve_create(curve_t curve, mpz_t p, mpz_t a, mpz_t b, mpz_t n, int32_t h, mpz_t xg, mpz_t yg) { mpz_init_set( curve->p, p); mpz_init_set( curve->a, a); mpz_init_set( curve->b, b); mpz_init_set( curve->n, n); curve->h = h; curve->bitwidth = (mpz_sizeinbase( p , 2 ) + 7) & 0xFFFFFFF8; curve_point_init_set_xy(curve->G, xg, yg); if (curve->G) return 0; mpz_clear( curve->n ); mpz_clear( curve->b ); mpz_clear( curve->a ); mpz_clear( curve->p ); return -1; }; int32_t curve_destroy(curve_t curve) { if (curve) { if (!curve_point_clear( curve->G )) { mpz_clear( curve->n ); mpz_clear( curve->b ); mpz_clear( curve->a ); mpz_clear( curve->p ); return 0; } } return -1; } int32_t curve_get_generator( ec_point_t dst, curve_t curve ) { mpz_set( dst->x, curve->G->x ); mpz_set( dst->y, curve->G->y ); } int32_t curve_point_init(ec_point_t point) { mpz_init(point->x); mpz_init(point->y); return 0; } int32_t curve_point_init_set(ec_point_t point, ec_point_t src) { mpz_init_set(point->x, src->x); mpz_init_set(point->y, src->y); return 0; } int32_t curve_point_init_set_xy(ec_point_t point, mpz_t x, mpz_t y) { mpz_init_set(point->x, x); mpz_init_set(point->y, y); return 0; } int32_t curve_point_clear(ec_point_t point) { mpz_clear(point->x); mpz_clear(point->y); return 0; } int32_t curve_point_is_valid(ec_point_t point, curve_t curve) { mpz_t yy, yy2; mpz_inits( yy, yy2, NULL ); mpz_powm_ui( yy, point->x, 3, curve->p ); mpz_addmul( yy, curve->a, point->x ); mpz_add( yy, yy, curve->b ); mpz_mod( yy, yy, curve->p ); mpz_powm_ui( yy2, point->y, 2, curve->p ); int result = mpz_cmp( yy, yy2 ) == 0; mpz_clears( yy, yy2, NULL ); return result; } int32_t curve_point_is_infinity(ec_point_t point) { return (mpz_cmp_ui(point->x, 0) == 0) && (mpz_cmp_ui(point->y, 0) == 0); } int32_t curve_point_add(ec_point_t dst, ec_point_t p1, ec_point_t p2, curve_t curve) { int xeq, yeq; xeq = mpz_cmp(p1->x, p2->x) == 0; yeq = mpz_cmp(p1->y, p2->y) == 0; if (xeq && !yeq) { mpz_set_ui( dst->x, 0); mpz_set_ui( dst->y, 0); return 0; } else { int result = -1; mpz_t lambda; mpz_t divlambda; ec_point_t _p1; ec_point_t _p2; curve_point_init_set( _p1, p1 ); curve_point_init_set( _p2, p2 ); mpz_inits( lambda, divlambda, NULL ); if (xeq) { mpz_powm_ui(lambda, _p1->x, 2, curve->p); mpz_mul_ui(lambda, lambda, 3); mpz_add(lambda, lambda, curve->a); mpz_mul_ui(divlambda, _p1->y, 2); } else { mpz_sub( lambda, _p2->y, _p1->y); mpz_sub( divlambda, _p2->x, _p1->x); } mpz_mod( lambda, lambda, curve->p ); mpz_mod( divlambda, divlambda, curve->p ); if (mpz_invert( divlambda, divlambda, curve->p )==0) { printf("%s: no inverse found\n", __func__); } else { mpz_mul( lambda, lambda, divlambda ); mpz_mod( lambda, lambda, curve->p ); mpz_powm_ui( dst->x, lambda, 2, curve->p ); mpz_sub( dst->x, dst->x, _p1->x ); mpz_sub( dst->x, dst->x, _p2->x ); mpz_mod( dst->x, dst->x, curve->p ); mpz_sub( dst->y, _p1->x, dst->x ); mpz_mul( dst->y, dst->y, lambda ); mpz_sub( dst->y, dst->y, _p1->y ); mpz_mod( dst->y, dst->y, curve->p ); result = 0; } mpz_clears( lambda, divlambda, NULL ); curve_point_clear(_p1); curve_point_clear(_p2); return result; } return -1; } int32_t curve_point_mul(ec_point_t dst, ec_point_t p1, mpz_t i, curve_t curve) { if (curve_point_is_infinity(p1) || (mpz_cmp_ui(p1->y, 0)==0)) { mpz_set_ui( dst->x, 0); mpz_set_ui( dst->y, 0); return 0; } int firstOne = mpz_scan1( i, 0 ); int size = (mpz_size( i ) * sizeof(mp_limb_t)) << 3; ec_point_t p; curve_point_init_set(p, p1); int n=0; for (;nn ); curve_point_mul( dst, curve->G, u2, curve ); return 0; } int32_t curve_hash_to_point( ec_point_t dst, char *message, int len, curve_t curve) { char hash[32]; SHA256_CTX sha256; sha256_init(&sha256); sha256_update(&sha256, message, len ); sha256_final(&sha256, hash); mpz_cleanup(k); mpz_import(k, 32, -1, 1, -1, 0, hash); mpz_mul_ui( k, k, 0xdeadbeef ); mpz_mod( k, k, curve->n); return curve_map_to_curve( dst, k, curve ); }