diff options
Diffstat (limited to 'moon-abe/pbc-0.5.14/guru/indexcalculus.c')
-rw-r--r-- | moon-abe/pbc-0.5.14/guru/indexcalculus.c | 869 |
1 files changed, 869 insertions, 0 deletions
diff --git a/moon-abe/pbc-0.5.14/guru/indexcalculus.c b/moon-abe/pbc-0.5.14/guru/indexcalculus.c new file mode 100644 index 00000000..4ef5e4ea --- /dev/null +++ b/moon-abe/pbc-0.5.14/guru/indexcalculus.c @@ -0,0 +1,869 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> // for intptr_t +#include <string.h> +#include <math.h> +#include <gmp.h> +#include "pbc.h" +#include "pbc_utils.h" + +struct cell_s { + int ind; + mpz_t data; +}; +typedef struct cell_s *cell_ptr; + +static cell_ptr newcell(void) +{ + cell_ptr res; + res = pbc_malloc(sizeof(struct cell_s)); + //res->data = pbc_malloc(sizeof(mpz_t)); + //mpz_init(res->data); + mpz_init(res->data); + return res; +} + +static void delcell(void *p) +{ + cell_ptr cp = p; + mpz_clear(cp->data); + pbc_free(p); +} + +static int is_gen(mpz_t x, mpz_t q, darray_ptr fac, darray_ptr mul) { + int result = 1; + mpz_t z; + mpz_t q1; + int i; + UNUSED_VAR(mul); + + mpz_init(z); + mpz_init(q1); + + mpz_sub_ui(q1, q, 1); + for (i=0; i<fac->count; i++) { + mpz_divexact(z, q1, fac->item[i]); + mpz_powm(z, x, z, q); + if (!mpz_cmp_ui(z, 1)) { + result = 0; + break; + } + } + + mpz_clear(q1); + mpz_clear(z); + return result; +} + +// Garner's Algorithm. +// See Algorithm 14.71, Handbook of Cryptography. +static void CRT(mpz_t x, mpz_ptr *v, mpz_ptr *m, int t) { + mpz_t u; + mpz_t C[t]; + int i, j; + + mpz_init(u); + for (i=1; i<t; i++) { + mpz_init(C[i]); + mpz_set_ui(C[i], 1); + for (j=0; j<i; j++) { + mpz_invert(u, m[j], m[i]); + mpz_mul(C[i], C[i], u); + mpz_mod(C[i], C[i], m[i]); + } + } + mpz_set(u, v[0]); + mpz_set(x, u); + for (i=1; i<t; i++) { + mpz_sub(u, v[i], x); + mpz_mul(u, u, C[i]); + mpz_mod(u, u, m[i]); + for (j=0; j<i; j++) { + mpz_mul(u, u, m[j]); + } + mpz_add(x, x, u); + } + + for (i=1; i<t; i++) mpz_clear(C[i]); + mpz_clear(u); +} + +//TODO: http://www.cecm.sfu.ca/CAG/abstracts/aaron27Jan06.pdf +//TODO: don't need to store last element of list in row[i] +//TODO: linked lists might be better than dynamic arrays (avoids memmove()) +//TODO: allow holes in the table +//(if drought lasts too long) +void index_calculus_step1(mpz_t *ind, int r, mpz_t g, mpz_t q, + darray_ptr fac, darray_ptr mul) { + int count = 0; + int i, j; + mpz_t z, z0, z1; + int relcount; + unsigned int *prime = pbc_malloc(sizeof(unsigned int) * r); + int bundlecount = (r - 10 + 19) / 20; + mpz_t *bundle = pbc_malloc(sizeof(mpz_t) * bundlecount); + int faci; + mpz_t k, km; + + cell_ptr *rel = pbc_malloc(sizeof(cell_ptr) * r); + cell_ptr *relm = pbc_malloc(sizeof(cell_ptr) * r); + //''matrix'' is actually a list of matrices + //(we solve over different moduli and combine using CRT) + //darray_t **matrix = pbc_malloc(sizeof(darray_t *) * fac->count); + darray_t *matrix[fac->count]; + int minfound[fac->count]; + + for (i=0; i<r; i++) { + rel[i] = newcell(); + relm[i] = newcell(); + } + for (i=0; i<fac->count; i++) { + //similarly ''row'' refers to a list of rows + darray_t *row = pbc_malloc(sizeof(darray_t) * r); + for (j=0; j<r; j++) { + darray_init(row[j]); + } + matrix[i] = row; + minfound[i] = 0; + } + + mpz_init(k); + mpz_init(km); + mpz_init(z); + mpz_init(z1); + mpz_init(z0); + + printf("building prime table...\n"); + prime[0] = 2; + mpz_set_ui(z, 2); + for (i=1; i<r; i++) { + mpz_nextprime(z, z); + prime[i] = mpz_get_ui(z); + } + + for (i=0; i<bundlecount; i++) { + mpz_init(bundle[i]); + mpz_set_ui(bundle[i], 1); + for (j=0; j<20; j++) { + int jj = 10 + 20 * i + j; + if (jj >= r) break; + mpz_mul_ui(bundle[i], bundle[i], prime[jj]); + } + element_printf("bundle %d: %Zd\n", i, bundle[i]); + } + printf("searching for r-smooth numbers\n"); + + mpz_set_ui(z, 1); + mpz_init(k); + int try = 0; + do { + mpz_mul(z, z, g); + mpz_mod(z, z, q); + mpz_add_ui(k, k, 1); + + /* + pbc_mpz_random(k, q); + mpz_powm(z, g, k, q); + */ + + try++; + + mpz_set(z1, z); + relcount = 0; + for (i=0; i<10; i++) { + if (i >= r) break; + j = 0; + while (mpz_divisible_ui_p(z1, prime[i])) { + mpz_divexact_ui(z1, z1, prime[i]); + j++; + } + if (j) { + rel[relcount]->ind = i; + mpz_set_ui(rel[relcount]->data, j); + relcount++; + if (!mpz_cmp_ui(z1, 1)) goto found; + } + } + for (i=0; i<bundlecount; i++) { + mpz_gcd(z0, bundle[i], z1); + if (mpz_cmp_ui(z0, 1)) { + int ii; + for (ii = 0; ii < 20; ii++) { + int jj = 10 + i * 20 + ii; + if (jj >= r) break; + j = 0; + while (mpz_divisible_ui_p(z1, prime[jj])) { + mpz_divexact_ui(z1, z1, prime[jj]); + j++; + } + if (j) { + rel[relcount]->ind = jj; + mpz_set_ui(rel[relcount]->data, j); + relcount++; + if (!mpz_cmp_ui(z1, 1)) goto found; + } + } + } + } + continue; +found: + +/* + printf("found r-smooth number after %d tries\n", try); + + gmp_printf("g^%Zd = %Zd:", k, z); + for (i=0; i<relcount; i++) { + gmp_printf(" %u:%Zd", rel[i]->ind, rel[i]->data); + } + printf("\n"); +*/ + try = 0; + + for (faci=0; faci<fac->count; faci++) { + darray_t *row = matrix[faci]; + mpz_ptr order = fac->item[faci]; + int relmcount = 0; + mpz_mod(km, k, order); + + //gmp_printf("mod %Zd\n", order); + for (i=0; i<relcount; i++) { + mpz_mod(z0, rel[i]->data, order); + if (mpz_sgn(z0)) { + mpz_set(relm[relmcount]->data, z0); + relm[relmcount]->ind = rel[i]->ind; + relmcount++; + } + } + + while (relmcount) { + //start from the sparse end + int rind = relm[relmcount - 1]->ind; + darray_ptr rp = row[rind]; + + if (rind < minfound[faci]) break; + + mpz_set(z0, relm[relmcount - 1]->data); + if (!rp->count) { + mpz_invert(z0, z0, order); + cell_ptr cnew = newcell(); + cnew->ind = -1; + mpz_mul(z1, km, z0); + mpz_mod(cnew->data, z1, order); + darray_append(rp, cnew); + for (j=0; j<relmcount; j++) { + cnew = newcell(); + cnew->ind = relm[j]->ind; + mpz_mul(z1, relm[j]->data, z0); + mpz_mod(cnew->data, z1, order); + darray_append(rp, cnew); + } + count++; +printf("%d / %d\n", count, r * fac->count); +/* +for (i=1; i<rp->count; i++) { + cnew = rp->item[i]; + gmp_printf(" %u:%Zd", cnew->ind, cnew->data); +} +cnew = rp->item[0]; +gmp_printf(" %Zd\n", cnew->data); +*/ + + if (rind == minfound[faci]) { + do { + if (!minfound[faci]) { + printf("found log p_%d\n", minfound[faci]); + cnew = rp->item[0]; + gmp_printf("km = %Zd mod %Zd\n", cnew->data, order); + } + minfound[faci]++; + if (minfound[faci] >= r) break; + rp = row[minfound[faci]]; + } while (rp->count); + } + break; + + } + +/* +{ +//gmp_printf("mod = %Zd\n", order); +printf("before:"); +for (i=0; i<relmcount; i++) { + gmp_printf(" %u:%Zd", relm[i]->ind, relm[i]->data); +} +gmp_printf(" %Zd\n", km); +cell_ptr cp; +printf("sub %d:", rind); +for (i=1; i<rp->count; i++) { + cp = rp->item[i]; + gmp_printf(" %u:%Zd", cp->ind, cp->data); +} +cp = rp->item[0]; +gmp_printf(" %Zd\n", cp->data); +} +*/ + cell_ptr cpi, cpj; + relmcount--; + i=0; j=1; + while (i<relmcount && j<rp->count - 1) { + cpi = relm[i]; + cpj = rp->item[j]; + if (cpi->ind == cpj->ind) { + mpz_mul(z1, z0, cpj->data); + mpz_mod(z1, z1, order); + int res = mpz_cmp(z1, cpi->data); + if (!res) { + memmove(&relm[i], &relm[i + 1], (relmcount - i - 1) * sizeof(cell_ptr)); + relm[relmcount - 1] = cpi; + relmcount--; + j++; + } else if (res > 0) { + mpz_sub(z1, order, z1); + mpz_add(cpi->data, cpi->data, z1); + i++; + j++; + } else { + mpz_sub(cpi->data, cpi->data, z1); + i++; + j++; + } + } else if (cpi->ind > cpj->ind) { + cpi = relm[relmcount]; + memmove(&relm[i + 1], &relm[i], (relmcount - i) * sizeof(cell_ptr)); + relm[i] = cpi; + relmcount++; + + cpi->ind = cpj->ind; + mpz_mul(z1, z0, cpj->data); + mpz_mod(z1, z1, order); + mpz_sub(cpi->data, order, z1); + //cpi->data = order - ((u0 * cpj->data) % order); + i++; + j++; + } else { + i++; + } + } + + if (i == relmcount) { + while (j < rp->count - 1) { + cpi = relm[relmcount]; + cpj = rp->item[j]; + cpi->ind = cpj->ind; + mpz_mul(z1, z0, cpj->data); + mpz_mod(z1, z1, order); + mpz_sub(cpi->data, order, z1); + //cpi->data = order - ((u0 * cpj->data) % order); + relmcount++; + j++; + } + } + + cpj = rp->item[0]; + mpz_mul(z1, z0, cpj->data); + mpz_mod(z1, z1, order); + //u1 = (u0 * cpj->data) % order; + if (mpz_cmp(km, z1) >= 0) { + mpz_sub(km, km, z1); + } else { + mpz_sub(z1, order, z1); + mpz_add(km, km, z1); + } + +/* +printf("after:"); +for (i=0; i<relmcount; i++) { + gmp_printf(" %u:%Zd", relm[i]->ind, relm[i]->data); +} +gmp_printf(" %Zd\n", km); +*/ + } + } + + } while (count < r * fac->count); + + for (faci=0; faci<fac->count; faci++) { + darray_t *row = matrix[faci]; + mpz_ptr order = fac->item[faci]; + for (i=1; i<r; i++) { + darray_ptr rp = row[i]; + cell_ptr c0 = rp->item[0]; + for (j=1; j<rp->count-1; j++) { + cell_ptr cp = rp->item[j]; + darray_ptr r2 = row[cp->ind]; + cell_ptr c2 = r2->item[0]; + mpz_mul(z0, cp->data, c2->data); + mpz_sub(c0->data, c0->data, z0); + mpz_mod(c0->data, c0->data, order); + } + } + } + + mpz_ptr *tmp = pbc_malloc(sizeof(mpz_ptr) * fac->count); + for (i=0; i<fac->count; i++) { + tmp[i] = pbc_malloc(sizeof(mpz_t)); + mpz_init(tmp[i]); + mpz_pow_ui(fac->item[i], fac->item[i], (unsigned int) mul->item[i]); + } + + for (i=0; i<r; i++) { + for (faci=0; faci<fac->count; faci++) { + darray_t *row = matrix[faci]; + cell_ptr cp = row[i]->item[0]; + mpz_set(tmp[faci], cp->data); + } + CRT(ind[i], tmp, (mpz_ptr *) fac->item, fac->count); + } + + for (i=0; i<fac->count; i++) { + mpz_clear(tmp[i]); + } + pbc_free(tmp); + + for (faci=0; i<fac->count; faci++) { + //similarly ''row'' refers to a list of rows + darray_t *row = matrix[faci]; + for (j=0; j<r; j++) { + darray_forall(row[j], delcell); + darray_clear(row[j]); + } + pbc_free(matrix[faci]); + } + + for (i=0; i<r; i++) { + delcell(rel[i]); + delcell(relm[i]); + } + + pbc_free(prime); + pbc_free(rel); + pbc_free(relm); + mpz_clear(k); + mpz_clear(km); + mpz_clear(z); + mpz_clear(z0); + mpz_clear(z1); +} + +// Brute-force: does not use the fact that matrices are sparse. +void slow_index_calculus_step1(mpz_t *ind, int r, mpz_t g, mpz_t q, + darray_ptr fac, darray_ptr mul) { + int count = 0; + int i, j; + mpz_t z, z0, z1; + //mpz_t rel[r + 1]; + //mpz_t relm[r + 1]; + mpz_t *rel = pbc_malloc(sizeof(mpz_t) * (r + 1)); + mpz_t *relm = pbc_malloc(sizeof(mpz_t) * (r + 1)); + unsigned int *prime = pbc_malloc(sizeof(unsigned int) * r); + darray_t matrix; + int faci; + mpz_t k; + int minfound[fac->count]; + + for (i=0; i<r+1; i++) mpz_init(rel[i]); + for (i=0; i<r+1; i++) mpz_init(relm[i]); + + mpz_init(k); + mpz_init(z); + mpz_init(z1); + mpz_init(z0); + + darray_init(matrix); + + for (i=0; i<fac->count; i++) { + darray_append(matrix, pbc_malloc(r * sizeof(mpz_t *))); + minfound[i] = 0; + } + + for (j=0; j<fac->count; j++) { + mpz_t **row = matrix->item[j]; + for (i=0; i<r; i++) row[i] = NULL; + } + + printf("building prime table...\n"); + prime[0] = 2; + mpz_set_ui(z, 2); + for (i=1; i<r; i++) { + mpz_nextprime(z, z); + prime[i] = mpz_get_ui(z); + } + printf("searching for r-smooth numbers\n"); + + mpz_set_ui(z, 1); + mpz_init(k); + int try = 0; + do { + mpz_mul(z, z, g); + mpz_mod(z, z, q); + + mpz_add_ui(k, k, 1); + /* + pbc_mpz_random(k, q); + mpz_powm(z, g, k, q); + */ + + try++; + + mpz_set(z1, z); + for (i=0; i<r; i++) { + mpz_set_ui(rel[i], 0); + while (mpz_divisible_ui_p(z1, prime[i])) { + mpz_add_ui(rel[i], rel[i], 1); + mpz_divexact_ui(z1, z1, prime[i]); + } + } + if (mpz_cmp_ui(z1, 1)) { + continue; + } + mpz_set(rel[r], k); + +/* + printf("found r-smooth number after %d tries\n", try); + gmp_printf("g^%Zd = %Zd:", rel[r], z); + for (i=0; i<r; i++) { + if (mpz_sgn(rel[i])) { + gmp_printf(" %u:%Zd", i, rel[i]); + } + } + printf("\n"); +*/ + + try = 0; + + for (faci=0; faci<fac->count; faci++) { + mpz_t **row = matrix->item[faci]; + mpz_ptr order = fac->item[faci]; + //gmp_printf("mod %Zd\n", order); + for (i=0; i<r+1; i++) { + mpz_mod(relm[i], rel[i], order); + } + + for (;;) { + /* + for (i=0; i<r && !mpz_sgn(relm[i]); i++); + if (i == r) { + //printf("redundant relation\n"); + break; + } + */ + for (i=r-1; i>=0 && !mpz_sgn(relm[i]); i--); + if (i < 0) { + //printf("redundant relation\n"); + break; + } + if (i < minfound[faci]) { + break; + } + mpz_set(z0, relm[i]); + if (!row[i]) { + row[i] = pbc_malloc(sizeof(mpz_t) * (r + 1)); + mpz_invert(z1, z0, order); + for (j=0; j<r+1; j++) { + mpz_init(row[i][j]); + mpz_mul(row[i][j], z1, relm[j]); + mpz_mod(row[i][j], row[i][j], order); + } + count++; +printf("%d / %d\n", count, r * fac->count); +/* +for (j=0; j<r; j++) { + if (mpz_sgn(row[i][j])) { + gmp_printf(" %d:%Zd", j, row[i][j]); + } +} +gmp_printf(" %Zd\n", row[i][j]); +*/ + + if (i == minfound[faci]) { + do { + if (!minfound[faci]) { + printf("found log p_%d\n", minfound[faci]); + gmp_printf("km = %Zd mod %Zd\n", row[i][r], order); + } + minfound[faci]++; + if (minfound[faci] >= r) break; + } while (row[minfound[faci]]); + } + break; + } + + /* + printf("before:"); + for (j=0; j<r; j++) { + if (mpz_sgn(relm[j])) { + gmp_printf(" %d:%Zd", j, relm[j]); + } + } + gmp_printf(" %Zd\n", relm[j]); + + printf("sub %d:", i); + for (j=0; j<r; j++) { + if (mpz_sgn(row[i][j])) { + gmp_printf(" %d:%Zd", j, row[i][j]); + } + } + gmp_printf(" %Zd\n", row[i][j]); + */ + + for (j=0; j<r+1; j++) { + mpz_mul(z1, z0, row[i][j]); + mpz_sub(relm[j], relm[j], z1); + mpz_mod(relm[j], relm[j], order); + } + + /* + printf("after:"); + for (j=0; j<r; j++) { + if (mpz_sgn(relm[j])) { + gmp_printf(" %d:%Zd", j, relm[j]); + } + } + gmp_printf(" %Zd\n", relm[j]); + */ + } + } + + } while (count < r * fac->count); + + for (faci=0; faci<fac->count; faci++) { + mpz_t **row = matrix->item[faci]; + mpz_ptr order = fac->item[faci]; + /* + gmp_printf("mod %Zd:\n", order); + for (i=0; i<r; i++) { + for (j=0; j<r+1; j++) { + gmp_printf(" %Zd", row[i][j]); + } + printf("\n"); + } + printf("\n"); + */ + + for (i=1; i<r; i++) { + for (j=0; j<i; j++) { + if (mpz_sgn(row[i][j])) { + mpz_mul(z0, row[i][j], row[j][r]); + mpz_sub(row[i][r], row[i][r], z0); + mpz_mod(row[i][r], row[i][r], order); + } + } + } + /* + for (i=r-2; i>=0; i--) { + for (j=i+1; j<r; j++) { + if (mpz_sgn(row[i][j])) { + mpz_mul(z0, row[i][j], row[j][r]); + mpz_sub(row[i][r], row[i][r], z0); + mpz_mod(row[i][r], row[i][r], order); + } + } + } + */ + + /* + for (i=0; i<r; i++) { + mpz_set(rel[i], row[i][r]); + gmp_printf(" %Zd", row[i][r]); + printf("\n"); + } + */ + } + + mpz_ptr *tmp = pbc_malloc(sizeof(mpz_ptr) * fac->count); + for (i=0; i<fac->count; i++) { + tmp[i] = pbc_malloc(sizeof(mpz_t)); + mpz_init(tmp[i]); + mpz_pow_ui(fac->item[i], fac->item[i], (unsigned int) mul->item[i]); + } + + for (i=0; i<r; i++) { + for (faci=0; faci<fac->count; faci++) { + mpz_t **row = matrix->item[faci]; + mpz_set(tmp[faci], row[i][r]); + } + CRT(ind[i], tmp, (mpz_ptr *) fac->item, fac->count); + } + + for (i=0; i<fac->count; i++) { + mpz_clear(tmp[i]); + } + pbc_free(tmp); + + for (faci=0; faci<matrix->count; faci++) { + mpz_t **row = matrix->item[faci]; + for (j=0; j<r; j++) { + for (i=0; i<r+1; i++) { + mpz_clear(row[j][i]); + } + pbc_free(row[j]); + } + pbc_free(row); + } + darray_clear(matrix); + for (i=0; i<r+1; i++) mpz_clear(rel[i]); + for (i=0; i<r+1; i++) mpz_clear(relm[i]); + pbc_free(prime); + pbc_free(rel); + pbc_free(relm); + mpz_clear(k); + mpz_clear(z); + mpz_clear(z0); + mpz_clear(z1); + + printf("step 1 completed\n"); + for (i=0; i<r; i++) element_printf(" %Zd", ind[i]); + printf("\n"); +} + +static void index_calculus_step2(mpz_t x, mpz_t *ind, int r, + mpz_t g, mpz_t h, mpz_t q) { + mpz_t prime; + mpz_t s; + mpz_t z, z1; + mpz_t rel[r]; + int i; + + mpz_init(z); + mpz_init(z1); + mpz_init(s); + mpz_init(prime); + for (i=0; i<r; i++) mpz_init(rel[i]); + + mpz_set(z, h); + + for (;;) { + mpz_mul(z, z, g); + mpz_mod(z, z, q); + mpz_add_ui(s, s, 1); + + mpz_set(z1, z); + mpz_set_ui(prime, 1); + for (i=0; i<r; i++) { + mpz_set_ui(rel[i], 0); + mpz_nextprime(prime, prime); + while (mpz_divisible_p(z1, prime)) { + mpz_add_ui(rel[i], rel[i], 1); + mpz_divexact(z1, z1, prime); + } + } + if (mpz_cmp_ui(z1, 1)) continue; + element_printf("found r-smooth number on try #%Zd\n", s); + mpz_set_ui(x, 0); + for (i=0; i<r; i++) { + mpz_mul(z, rel[i], ind[i]); + mpz_add(x, x, z); + } + mpz_sub(x, x, s); + mpz_sub_ui(z, q, 1); + mpz_mod(x, x, z); + break; + } +} + +static void mpzclear(void *p) { + mpz_clear(p); + pbc_free(p); +} + +struct addfm_scope_var { + darray_ptr fac, mul; +}; + +static int addfm(mpz_t f, unsigned int m, struct addfm_scope_var *v) { + darray_append(v->fac, f); + darray_append(v->mul, int_to_voidp(m)); + return 0; +} + +void pbc_mpz_index_calculus(mpz_t x, mpz_t g, mpz_t h, mpz_t q) { + int i, r; + mpz_t q1, z0; + + mpz_init(q1); + mpz_init(z0); + + mpz_sub_ui(q1, q, 1); + mpz_setbit(z0, 6); + + darray_t fac, mul; + darray_init(fac); + darray_init(mul); + struct addfm_scope_var v = {.fac = fac, .mul = mul}; + pbc_trial_divide((int(*)(mpz_t,unsigned,void*))addfm, &v, q1, z0); + + for (i=0; i<mul->count; i++) { + unsigned int m = (unsigned int) mul->item[i]; + if (m != 1) { + //TODO + printf("p-adics not implemented yet\n"); + return; + } + } + + { + double dq = mpz_get_d(q); + //r = exp(sqrt(log(dq)*log(log(dq)))); + //printf("r = %d\n", r); + r = exp(1.2 * sqrt(log(dq))); + printf("r = %d\n", r); + } + mpz_t *ind = pbc_malloc(sizeof(mpz_t) * r); + for (i=0; i<r; i++) mpz_init(ind[i]); + + if (is_gen(g, q, fac, mul)) { + + index_calculus_step1(ind, r, g, q, fac, mul); + + index_calculus_step2(x, ind, r, g, h, q); + } else { + mpz_t y, z; + mpz_t d; + + mpz_init(d); + mpz_init(y); + mpz_init(z); + do { + pbc_mpz_random(z, q); + } while (!is_gen(z, q, fac, mul)); + + gmp_printf("new gen: %Zd\n", z); + + index_calculus_step1(ind, r, z, q, fac, mul); + //slow_index_calculus_step1(ind, r, z, q, fac, mul); + + index_calculus_step2(x, ind, r, z, g, q); + index_calculus_step2(y, ind, r, z, h, q); + //want y / x mod q-1 + mpz_gcd(d, x, q1); + mpz_divexact(q1, q1, d); + mpz_divexact(x, x, d); + //if y not divisible by d there is no solution + mpz_divexact(y, y, d); + mpz_invert(x, x, q1); + mpz_mul(x, y, x); + mpz_mod(x, x, q1); + + do { + mpz_powm(z0, g, x, q); + if (!mpz_cmp(z0, h)) { + break; + } + mpz_add(x, x, q1); + mpz_sub_ui(d, d, 1); + } while (mpz_sgn(d)); + + mpz_clear(d); + mpz_clear(y); + mpz_clear(z); + } + + for (i=0; i<r; i++) mpz_clear(ind[i]); + pbc_free(ind); + + darray_forall(fac, mpzclear); + darray_clear(mul); + darray_clear(fac); + mpz_clear(q1); + mpz_clear(z0); +} |