/** * Multiply the generator g of the elliptic curve by @a val * to obtain the point on the curve representing @a val. * Afterwards, point addition will correspond to integer * addition. #GNUNET_CRYPTO_ecc_dlog() can be used to * convert a point back to an integer (as long as the * integer is smaller than the MAX of the @a edc context). * * @param edc calculation context for ECC operations * @param val value to encode into a point * @return representation of the value as an ECC point, * must be freed using #GNUNET_CRYPTO_ecc_free() */ gcry_mpi_point_t GNUNET_CRYPTO_ecc_dexp (struct GNUNET_CRYPTO_EccDlogContext *edc, int val) { gcry_mpi_t fact; gcry_mpi_t n; gcry_mpi_point_t g; gcry_mpi_point_t r; g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); GNUNET_assert (NULL != g); fact = gcry_mpi_new (0); if (val < 0) { n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); gcry_mpi_set_ui (fact, - val); gcry_mpi_sub (fact, n, fact); gcry_mpi_release (n); } else { gcry_mpi_set_ui (fact, val); } r = gcry_mpi_point_new (0); gcry_mpi_ec_mul (r, fact, g, edc->ctx); gcry_mpi_release (fact); gcry_mpi_point_release (g); return r; }
int point_decompress(struct affine_point *p, const gcry_mpi_t x, int yflag, const struct domain_params *dp) { gcry_mpi_t h, y; int res; h = gcry_mpi_snew(0); y = gcry_mpi_snew(0); gcry_mpi_mulm(h, x, x, dp->m); gcry_mpi_addm(h, h, dp->a, dp->m); gcry_mpi_mulm(h, h, x, dp->m); gcry_mpi_addm(h, h, dp->b, dp->m); if ((res = mod_root(y, h, dp->m))) if ((res = (gcry_mpi_cmp_ui(y, 0) || ! yflag))) { p->x = gcry_mpi_snew(0); p->y = gcry_mpi_snew(0); gcry_mpi_set(p->x, x); if (gcry_mpi_test_bit(y, 0) == yflag) gcry_mpi_set(p->y, y); else gcry_mpi_sub(p->y, dp->m, y); assert(point_on_curve(p, dp)); } gcry_mpi_release(h); gcry_mpi_release(y); return res; }
/* compute 2^m (mod phi(p)), for a prime p */ static gcry_mpi_t twopowmodphi(uint64_t m, const gcry_mpi_t p) { gcry_mpi_t phi, r; int n; phi = gcry_mpi_new(0); gcry_mpi_sub_ui(phi, p, 1); /* count number of used bits in m */ for (n = 0; (1ULL << n) <= m; n++) ; r = gcry_mpi_new(0); gcry_mpi_set_ui(r, 1); while (n) { /* square and multiply algorithm for fast exponentiation */ n--; gcry_mpi_mulm(r, r, r, phi); if (m & ((uint64_t)1 << n)) { gcry_mpi_add(r, r, r); if (gcry_mpi_cmp(r, phi) >= 0) gcry_mpi_sub(r, r, phi); } } gcry_mpi_release(phi); return r; }
/** * Obtain a random point on the curve and its * additive inverse. Both returned values * must be freed using #GNUNET_CRYPTO_ecc_free(). * * @param edc calculation context for ECC operations * @param[out] r set to a random point on the curve * @param[out] r_inv set to the additive inverse of @a r */ void GNUNET_CRYPTO_ecc_rnd (struct GNUNET_CRYPTO_EccDlogContext *edc, gcry_mpi_point_t *r, gcry_mpi_point_t *r_inv) { gcry_mpi_t fact; gcry_mpi_t n; gcry_mpi_point_t g; fact = GNUNET_CRYPTO_ecc_random_mod_n (edc); /* calculate 'r' */ g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); GNUNET_assert (NULL != g); *r = gcry_mpi_point_new (0); gcry_mpi_ec_mul (*r, fact, g, edc->ctx); /* calculate 'r_inv' */ n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); gcry_mpi_sub (fact, n, fact); /* fact = n - fact = - fact */ *r_inv = gcry_mpi_point_new (0); gcry_mpi_ec_mul (*r_inv, fact, g, edc->ctx); gcry_mpi_release (n); gcry_mpi_release (fact); gcry_mpi_point_release (g); }
/** * Do pre-calculation for ECC discrete logarithm for small factors. * * @param max maximum value the factor can be * @param mem memory to use (should be smaller than @a max), must not be zero. * @return @a max if dlog failed, otherwise the factor */ struct GNUNET_CRYPTO_EccDlogContext * GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max, unsigned int mem) { struct GNUNET_CRYPTO_EccDlogContext *edc; unsigned int K = ((max + (mem-1)) / mem); gcry_mpi_point_t g; struct GNUNET_PeerIdentity key; gcry_mpi_point_t gKi; gcry_mpi_t fact; gcry_mpi_t n; unsigned int i; GNUNET_assert (max < INT32_MAX); edc = GNUNET_new (struct GNUNET_CRYPTO_EccDlogContext); edc->max = max; edc->mem = mem; edc->map = GNUNET_CONTAINER_multipeermap_create (mem * 2, GNUNET_NO); GNUNET_assert (0 == gcry_mpi_ec_new (&edc->ctx, NULL, CURVE)); g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); GNUNET_assert (NULL != g); fact = gcry_mpi_new (0); gKi = gcry_mpi_point_new (0); for (i=0;i<=mem;i++) { gcry_mpi_set_ui (fact, i * K); gcry_mpi_ec_mul (gKi, fact, g, edc->ctx); extract_pk (gKi, edc->ctx, &key); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (edc->map, &key, (void*) (long) i + max, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } /* negative values */ n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); for (i=1;i<mem;i++) { gcry_mpi_set_ui (fact, i * K); gcry_mpi_sub (fact, n, fact); gcry_mpi_ec_mul (gKi, fact, g, edc->ctx); extract_pk (gKi, edc->ctx, &key); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (edc->map, &key, (void*) (long) max - i, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } gcry_mpi_release (fact); gcry_mpi_release (n); gcry_mpi_point_release (gKi); gcry_mpi_point_release (g); return edc; }
/** * Do some DLOG operations for testing. * * @param edc context for ECC operations * @param do_dlog #GNUNET_YES if we want to actually do the bencharked operation */ static void test_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, int do_dlog) { gcry_mpi_t fact; gcry_mpi_t n; gcry_ctx_t ctx; gcry_mpi_point_t q; gcry_mpi_point_t g; unsigned int i; int x; int iret; GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE)); g = gcry_mpi_ec_get_point ("g", ctx, 0); GNUNET_assert (NULL != g); n = gcry_mpi_ec_get_mpi ("n", ctx, 0); q = gcry_mpi_point_new (0); fact = gcry_mpi_new (0); for (i=0;i<TEST_ITER;i++) { fprintf (stderr, "."); x = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, MAX_FACT); if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2)) { gcry_mpi_set_ui (fact, x); gcry_mpi_sub (fact, n, fact); x = - x; } else { gcry_mpi_set_ui (fact, x); } gcry_mpi_ec_mul (q, fact, g, ctx); if ( (GNUNET_YES == do_dlog) && (x != (iret = GNUNET_CRYPTO_ecc_dlog (edc, q))) ) { fprintf (stderr, "DLOG failed for value %d (%d)\n", x, iret); GNUNET_assert (0); } } gcry_mpi_release (fact); gcry_mpi_release (n); gcry_mpi_point_release (g); gcry_mpi_point_release (q); gcry_ctx_release (ctx); fprintf (stderr, "\n"); }
unsigned char* sub(unsigned char* x, unsigned char* y){ size_t scanned; unsigned char *result; gcry_mpi_t a = gcry_mpi_new(0); gcry_mpi_t b = gcry_mpi_new(0); gcry_mpi_scan(&a, GCRYMPI_FMT_HEX, x, 0, &scanned); gcry_mpi_scan(&b, GCRYMPI_FMT_HEX, y, 0, &scanned); gcry_mpi_sub(a, a, b); gcry_mpi_aprint(GCRYMPI_FMT_HEX, &result, NULL, a); return result; }
int mixin_key_and_curve(struct affine_point *P, gcry_mpi_t pubkey, const struct curve_params *cp) { int yflag, res; if ((yflag = (gcry_mpi_cmp(pubkey, cp->dp.m) >= 0))) gcry_mpi_sub(pubkey, pubkey, cp->dp.m); res = gcry_mpi_cmp_ui(pubkey, 0) >= 0 && gcry_mpi_cmp(pubkey, cp->dp.m) < 0 && point_decompress(P, pubkey, yflag, &cp->dp); return res; }
/** * Obtain a random scalar for point multiplication on the curve and * its multiplicative inverse. * * @param edc calculation context for ECC operations * @param[out] r set to a random scalar on the curve * @param[out] r_inv set to the multiplicative inverse of @a r */ void GNUNET_CRYPTO_ecc_rnd_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, gcry_mpi_t *r, gcry_mpi_t *r_inv) { gcry_mpi_t n; *r = GNUNET_CRYPTO_ecc_random_mod_n (edc); /* r_inv = n - r = - r */ *r_inv = gcry_mpi_new (0); n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); gcry_mpi_sub (*r_inv, n, *r); }
static bigint_t wrap_gcry_mpi_sub (bigint_t w, const bigint_t a, const bigint_t b) { if (w == NULL) w = _gnutls_mpi_alloc_like (b); if (w == NULL) return NULL; gcry_mpi_sub (w, a, b); return w; }
static int test_sub (void) { gcry_mpi_t one; gcry_mpi_t two; gcry_mpi_t result; unsigned char* pc; gcry_mpi_scan(&one, GCRYMPI_FMT_USG, ones, sizeof(ones), NULL); gcry_mpi_scan(&two, GCRYMPI_FMT_USG, twos, sizeof(twos), NULL); result = gcry_mpi_new(0); gcry_mpi_sub(result, two, one); gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result); if (verbose) printf("Result of two minus one:\n%s\n", pc); gcry_free(pc); gcry_mpi_release(one); gcry_mpi_release(two); gcry_mpi_release(result); return 1; }
void gcry_mpi_subm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) { gcry_mpi_sub(w, u, v); _gcry_mpi_fdiv_r( w, w, m ); }