libcurve/src/curve.c

230 lines
5.2 KiB
C

#include <curve.h>
#include <sha256.h>
#include <mpztools.h>
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 (;n<firstOne;n++)
curve_point_add( p, p, p, curve );
n++;
curve_point_set( dst, p );
for (;n<size;n++)
{
curve_point_add( p, p, p, curve );
if (mpz_tstbit(i, n))
curve_point_add( dst, dst, p, curve );
}
curve_point_clear(p);
return 0;
}
int32_t curve_map_to_curve( ec_point_t dst, mpz_t u, curve_t curve)
{
mpz_t_cleanup_set(u2, u);
mpz_mod( u2, u2, curve->n );
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 );
}