void darray_destroy(struct darray *da) { check(da != NULL, "darray is null before destroy"); darray_clear(da); free(da); error: return; }
// x in Z_r, g, h in some group of order r // finds x such that g^x = h void element_dlog_pollard_rho(element_t x, element_t g, element_t h) { // see Blake, Seroussi and Smart // only one snark for this implementation int i, s = 20; field_ptr Zr = x->field, G = g->field; element_t asum; element_t bsum; element_t a[s]; element_t b[s]; element_t m[s]; element_t g0, snark; darray_t hole; int interval = 5; mpz_t counter; int found = 0; mpz_init(counter); element_init(g0, G); element_init(snark, G); element_init(asum, Zr); element_init(bsum, Zr); darray_init(hole); //set up multipliers for (i = 0; i < s; i++) { element_init(a[i], Zr); element_init(b[i], Zr); element_init(m[i], G); element_random(a[i]); element_random(b[i]); element_pow_zn(g0, g, a[i]); element_pow_zn(m[i], h, b[i]); element_mul(m[i], m[i], g0); } element_random(asum); element_random(bsum); element_pow_zn(g0, g, asum); element_pow_zn(snark, h, bsum); element_mul(snark, snark, g0); record(asum, bsum, snark, hole, counter); for (;;) { int len = element_length_in_bytes(snark); unsigned char *buf = pbc_malloc(len); unsigned char hash = 0; element_to_bytes(buf, snark); for (i = 0; i < len; i++) { hash += buf[i]; } i = hash % s; pbc_free(buf); element_mul(snark, snark, m[i]); element_add(asum, asum, a[i]); element_add(bsum, bsum, b[i]); for (i = 0; i < hole->count; i++) { snapshot_ptr ss = hole->item[i]; if (!element_cmp(snark, ss->snark)) { element_sub(bsum, bsum, ss->b); element_sub(asum, ss->a, asum); //answer is x such that x * bsum = asum //complications arise if gcd(bsum, r) > 1 //which can happen if r is not prime if (!mpz_probab_prime_p(Zr->order, 10)) { mpz_t za, zb, zd, zm; mpz_init(za); mpz_init(zb); mpz_init(zd); mpz_init(zm); element_to_mpz(za, asum); element_to_mpz(zb, bsum); mpz_gcd(zd, zb, Zr->order); mpz_divexact(zm, Zr->order, zd); mpz_divexact(zb, zb, zd); //if zd does not divide za there is no solution mpz_divexact(za, za, zd); mpz_invert(zb, zb, zm); mpz_mul(zb, za, zb); mpz_mod(zb, zb, zm); do { element_pow_mpz(g0, g, zb); if (!element_cmp(g0, h)) { element_set_mpz(x, zb); break; } mpz_add(zb, zb, zm); mpz_sub_ui(zd, zd, 1); } while (mpz_sgn(zd)); mpz_clear(zm); mpz_clear(za); mpz_clear(zb); mpz_clear(zd); } else { element_div(x, asum, bsum); } found = 1; break; } } if (found) break; mpz_add_ui(counter, counter, 1); if (mpz_tstbit(counter, interval)) { record(asum, bsum, snark, hole, counter); interval++; } } for (i = 0; i < s; i++) { element_clear(a[i]); element_clear(b[i]); element_clear(m[i]); } element_clear(g0); element_clear(snark); for (i = 0; i < hole->count; i++) { snapshot_ptr ss = hole->item[i]; element_clear(ss->a); element_clear(ss->b); element_clear(ss->snark); pbc_free(ss); } darray_clear(hole); element_clear(asum); element_clear(bsum); mpz_clear(counter); }
void darray_destroy(darray_t *array) { darray_clear(array); h_free(array); }
void symtab_clear(symtab_t t) { darray_forall(t->list, clear); darray_clear(t->list); }
void darray_clear_destroy(darray_t *array) { darray_clear(array); darray_destroy(array); }
void darray_free(darray_ptr a) { darray_clear(a); pbc_free(a); }
// See Cohen; my D is -D in his notation. size_t pbc_hilbert(mpz_t **arr, int D) { int a, b; int t; int B = (int)floor(sqrt((double) D / 3.0)); mpc_t alpha; mpc_t j; mpf_t sqrtD; mpf_t f0; darray_t Pz; mpc_t z0, z1, z2; double d = 1.0; int h = 1; int jcount = 1; // Compute required precision. b = D % 2; for (;;) { t = (b*b + D) / 4; a = b; if (a <= 1) { a = 1; goto step535_4; } step535_3: if (!(t % a)) { jcount++; if ((a == b) || (a*a == t) || !b) { d += 1.0 / ((double) a); h++; } else { d += 2.0 / ((double) a); h+=2; } } step535_4: a++; if (a * a <= t) { goto step535_3; } else { b += 2; if (b > B) break; } } //printf("modulus: %f\n", exp(3.14159265358979 * sqrt(D)) * d * 0.5); d *= sqrt(D) * 3.14159265358979 / log(2); precision_init((int)(d + 34)); pbc_info("class number %d, %d bit precision", h, (int) d + 34); darray_init(Pz); mpc_init(alpha); mpc_init(j); mpc_init(z0); mpc_init(z1); mpc_init(z2); mpf_init(sqrtD); mpf_init(f0); mpf_sqrt_ui(sqrtD, D); b = D % 2; h = 0; for (;;) { t = (b*b + D) / 4; if (b > 1) { a = b; } else { a = 1; } step3: if (t % a) { step4: a++; if (a * a <= t) goto step3; } else { // a, b, t/a are coeffs of an appropriate primitive reduced positive // definite form. // Compute j((-b + sqrt{-D})/(2a)). h++; pbc_info("[%d/%d] a b c = %d %d %d", h, jcount, a, b, t/a); mpf_set_ui(f0, 1); mpf_div_ui(f0, f0, 2 * a); mpf_mul(mpc_im(alpha), sqrtD, f0); mpf_mul_ui(f0, f0, b); mpf_neg(mpc_re(alpha), f0); compute_j(j, alpha); if (0) { int i; for (i=Pz->count - 1; i>=0; i--) { printf("P %d = ", i); mpc_out_str(stdout, 10, 4, Pz->item[i]); printf("\n"); } } if (a == b || a * a == t || !b) { // P *= X - j int i, n; mpc_ptr p0; p0 = (mpc_ptr) pbc_malloc(sizeof(mpc_t)); mpc_init(p0); mpc_neg(p0, j); n = Pz->count; if (n) { mpc_set(z1, Pz->item[0]); mpc_add(Pz->item[0], z1, p0); for (i=1; i<n; i++) { mpc_mul(z0, z1, p0); mpc_set(z1, Pz->item[i]); mpc_add(Pz->item[i], z1, z0); } mpc_mul(p0, p0, z1); } darray_append(Pz, p0); } else { // P *= X^2 - 2 Re(j) X + |j|^2 int i, n; mpc_ptr p0, p1; p0 = (mpc_ptr) pbc_malloc(sizeof(mpc_t)); p1 = (mpc_ptr) pbc_malloc(sizeof(mpc_t)); mpc_init(p0); mpc_init(p1); // p1 = - 2 Re(j) mpf_mul_ui(f0, mpc_re(j), 2); mpf_neg(f0, f0); mpf_set(mpc_re(p1), f0); // p0 = |j|^2 mpf_mul(f0, mpc_re(j), mpc_re(j)); mpf_mul(mpc_re(p0), mpc_im(j), mpc_im(j)); mpf_add(mpc_re(p0), mpc_re(p0), f0); n = Pz->count; if (!n) { } else if (n == 1) { mpc_set(z1, Pz->item[0]); mpc_add(Pz->item[0], z1, p1); mpc_mul(p1, z1, p1); mpc_add(p1, p1, p0); mpc_mul(p0, p0, z1); } else { mpc_set(z2, Pz->item[0]); mpc_set(z1, Pz->item[1]); mpc_add(Pz->item[0], z2, p1); mpc_mul(z0, z2, p1); mpc_add(Pz->item[1], z1, z0); mpc_add(Pz->item[1], Pz->item[1], p0); for (i=2; i<n; i++) { mpc_mul(z0, z1, p1); mpc_mul(alpha, z2, p0); mpc_set(z2, z1); mpc_set(z1, Pz->item[i]); mpc_add(alpha, alpha, z0); mpc_add(Pz->item[i], z1, alpha); } mpc_mul(z0, z2, p0); mpc_mul(p1, p1, z1); mpc_add(p1, p1, z0); mpc_mul(p0, p0, z1); } darray_append(Pz, p1); darray_append(Pz, p0); } goto step4; } b+=2; if (b > B) break; } // Round polynomial and assign. int k = 0; { *arr = pbc_malloc(sizeof(mpz_t) * (Pz->count + 1)); int i; for (i=Pz->count - 1; i>=0; i--) { if (mpf_sgn(mpc_re(Pz->item[i])) < 0) { mpf_set_d(f0, -0.5); } else { mpf_set_d(f0, 0.5); } mpf_add(f0, f0, mpc_re(Pz->item[i])); mpz_init((*arr)[k]); mpz_set_f((*arr)[k], f0); k++; mpc_clear(Pz->item[i]); pbc_free(Pz->item[i]); } mpz_init((*arr)[k]); mpz_set_ui((*arr)[k], 1); k++; } darray_clear(Pz); mpc_clear(z0); mpc_clear(z1); mpc_clear(z2); mpf_clear(f0); mpf_clear(sqrtD); mpc_clear(alpha); mpc_clear(j); precision_clear(); return k; }