/* Check if y^2 = x^3 - 3x + b */ static int ecc_valid_p (struct ecc_point *pub) { mpz_t t, x, y; mpz_t lhs, rhs; int res; mp_size_t size; size = pub->ecc->size; /* First check range */ if (mpn_cmp (pub->p, pub->ecc->p, size) >= 0 || mpn_cmp (pub->p + size, pub->ecc->p, size) >= 0) return 0; mpz_init (lhs); mpz_init (rhs); mpz_roinit_n (x, pub->p, size); mpz_roinit_n (y, pub->p + size, size); mpz_mul (lhs, y, y); mpz_mul (rhs, x, x); mpz_sub_ui (rhs, rhs, 3); mpz_mul (rhs, rhs, x); mpz_add (rhs, rhs, mpz_roinit_n (t, pub->ecc->b, size)); res = mpz_congruent_p (lhs, rhs, mpz_roinit_n (t, pub->ecc->p, size)); mpz_clear (lhs); mpz_clear (rhs); return res; }
static PyObject * GMPy_MPZ_Method_IsCongruent(PyObject *self, PyObject *args) { int res; MPZ_Object *tempy = NULL, *tempm = NULL; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("is_congruent() requires 2 integer arguments"); return NULL; } if (!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) || !(tempm = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL))) { Py_XDECREF((PyObject*)tempy); Py_XDECREF((PyObject*)tempm); TYPE_ERROR("is_congruent() requires 2 integer arguments"); return NULL; } res = mpz_congruent_p(MPZ(self), tempy->z, tempm->z); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)tempm); if (res) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
/* Check if y^2 = x^3 - 3x + b */ static int ecc_valid_p (struct ecc_point *pub) { mpz_t t, x, y; mpz_t lhs, rhs; int res; mp_size_t size; size = pub->ecc->p.size; /* First check range */ if (mpn_cmp (pub->p, pub->ecc->p.m, size) >= 0 || mpn_cmp (pub->p + size, pub->ecc->p.m, size) >= 0) return 0; mpz_init (lhs); mpz_init (rhs); mpz_roinit_n (x, pub->p, size); mpz_roinit_n (y, pub->p + size, size); mpz_mul (lhs, y, y); if (pub->ecc->p.bit_size == 255) { /* Check that 121666 (1 + x^2 - y^2) = 121665 x^2 y^2 */ mpz_t x2; mpz_init (x2); mpz_mul (x2, x, x); /* x^2 */ mpz_mul (rhs, x2, lhs); /* x^2 y^2 */ mpz_sub (lhs, x2, lhs); /* x^2 - y^2 */ mpz_add_ui (lhs, lhs, 1); /* 1 + x^2 - y^2 */ mpz_mul_ui (lhs, lhs, 121666); mpz_mul_ui (rhs, rhs, 121665); mpz_clear (x2); } else { /* Check y^2 = x^3 - 3 x + b */ mpz_mul (rhs, x, x); mpz_sub_ui (rhs, rhs, 3); mpz_mul (rhs, rhs, x); mpz_add (rhs, rhs, mpz_roinit_n (t, pub->ecc->b, size)); } res = mpz_congruent_p (lhs, rhs, mpz_roinit_n (t, pub->ecc->p.m, size)); mpz_clear (lhs); mpz_clear (rhs); return res; }
void check_one (mpz_srcptr a, mpz_srcptr c, mpz_srcptr d, int want) { int got; int swap; for (swap = 0; swap <= 1; swap++) { got = (mpz_congruent_p (a, c, d) != 0); if (want != got) { printf ("mpz_congruent_p wrong\n"); printf (" expected %d got %d\n", want, got); mpz_trace (" a", a); mpz_trace (" c", c); mpz_trace (" d", d); mp_trace_base = -16; mpz_trace (" a", a); mpz_trace (" c", c); mpz_trace (" d", d); abort (); } if (mpz_fits_ulong_p (c) && mpz_fits_ulong_p (d)) { unsigned long uc = mpz_get_ui (c); unsigned long ud = mpz_get_ui (d); got = (mpz_congruent_ui_p (a, uc, ud) != 0); if (want != got) { printf ("mpz_congruent_ui_p wrong\n"); printf (" expected %d got %d\n", want, got); mpz_trace (" a", a); printf (" c=%lu\n", uc); printf (" d=%lu\n", ud); mp_trace_base = -16; mpz_trace (" a", a); printf (" c=0x%lX\n", uc); printf (" d=0x%lX\n", ud); abort (); } } MPZ_SRCPTR_SWAP (a, c); } }
int mpz_congruent_ui_p (mpz_srcptr a, unsigned long cu, unsigned long du) { mp_srcptr ap; mp_size_t asize; mp_limb_t c, d, r; if (UNLIKELY (du == 0)) return (mpz_cmp_ui (a, cu) == 0); asize = SIZ(a); if (asize == 0) { if (cu < du) return cu == 0; else return (cu % du) == 0; } /* For nails don't try to be clever if c or d is bigger than a limb, just fake up some mpz_t's and go to the main mpz_congruent_p. */ if (du > GMP_NUMB_MAX || cu > GMP_NUMB_MAX) { mp_limb_t climbs[2], dlimbs[2]; mpz_t cz, dz; ALLOC(cz) = 2; PTR(cz) = climbs; ALLOC(dz) = 2; PTR(dz) = dlimbs; mpz_set_ui (cz, cu); mpz_set_ui (dz, du); return mpz_congruent_p (a, cz, dz); } /* NEG_MOD works on limbs, so convert ulong to limb */ c = cu; d = du; if (asize < 0) { asize = -asize; NEG_MOD (c, c, d); } ap = PTR (a); if (ABOVE_THRESHOLD (asize, BMOD_1_TO_MOD_1_THRESHOLD)) { r = mpn_mod_1 (ap, asize, d); if (c < d) return r == c; else return r == (c % d); } if ((d & 1) == 0) { /* Strip low zero bits to get odd d required by modexact. If d==e*2^n then a==c mod d if and only if both a==c mod 2^n and a==c mod e. */ unsigned twos; if ((ap[0]-c) & LOW_ZEROS_MASK (d)) return 0; count_trailing_zeros (twos, d); d >>= twos; }
void mpz_sqrtmp_r (mpz_ptr root, mpz_srcptr a, mpz_srcptr p) { /* ? a \neq 0 */ if (mpz_get_ui(a) != 0) { /* ? p = 3 (mod 4) */ if (mpz_congruent_ui_p(p, 3L, 4L)) { mpz_t foo; mpz_init_set(foo, p); mpz_add_ui(foo, foo, 1L); mpz_fdiv_q_2exp(foo, foo, 2L); mpz_powm(root, a, foo, p); mpz_clear(foo); return; } /* ! p = 1 (mod 4) */ else { /* ! s = (p-1)/4 */ mpz_t s; mpz_init_set(s, p); mpz_sub_ui(s, s, 1L); mpz_fdiv_q_2exp(s, s, 2L); /* ? p = 5 (mod 8) */ if (mpz_congruent_ui_p(p, 5L, 8L)) { mpz_t foo, b; mpz_init(foo); mpz_powm(foo, a, s, p); mpz_init_set(b, p); mpz_add_ui(b, b, 3L); mpz_fdiv_q_2exp(b, b, 3L); mpz_powm(root, a, b, p); /* ? a^{(p-1)/4} = 1 (mod p) */ if (mpz_cmp_ui(foo, 1L) == 0) { mpz_clear(foo), mpz_clear(s), mpz_clear(b); return; } /* ! a^{(p-1)/4} = -1 (mod p) */ else { do mpz_wrandomm(b, p); while (mpz_jacobi(b, p) != -1); mpz_powm(b, b, s, p); mpz_mul(root, root, b); mpz_mod(root, root, p); mpz_clear(foo), mpz_clear(s), mpz_clear(b); return; } } /* ! p = 1 (mod 8) */ else { mpz_t foo, bar, b, t; mpz_init(foo), mpz_init(bar); mpz_powm(foo, a, s, p); /* while a^s = 1 (mod p) */ while (mpz_cmp_ui(foo, 1L) == 0) { /* ? s odd */ if (mpz_odd_p(s)) { mpz_add_ui(s, s, 1L); mpz_fdiv_q_2exp(s, s, 1L); mpz_powm(root, a, s, p); mpz_clear(foo), mpz_clear(s); return; } /* ! s even */ else { mpz_fdiv_q_2exp(s, s, 1L); } mpz_powm(foo, a, s, p); } /* ! a^s = -1 (mod p) */ mpz_init(b); do mpz_wrandomm(b, p); while (mpz_jacobi(b, p) != -1); mpz_init_set(t, p); mpz_sub_ui(t, t, 1L); mpz_fdiv_q_2exp(t, t, 1L); /* while s even */ while (mpz_even_p(s)) { mpz_fdiv_q_2exp(s, s, 1L); mpz_fdiv_q_2exp(t, t, 1L); mpz_powm(foo, a, s, p); mpz_powm(bar, b, t, p); mpz_mul(foo, foo, bar); mpz_mod(foo, foo, p); mpz_set_si(bar, -1L); /* ? a^s * b^t = -1 (mod p) */ if (mpz_congruent_p(foo, bar, p)) { mpz_set(bar, p); mpz_sub_ui(bar, bar, 1L); mpz_fdiv_q_2exp(bar, bar, 1L); mpz_add(t, t, bar); } } mpz_add_ui(s, s, 1L); mpz_fdiv_q_2exp(s, s, 1L); mpz_fdiv_q_2exp(t, t, 1L); mpz_powm(foo, a, s, p); mpz_powm(bar, b, t, p); mpz_mul(root, foo, bar); mpz_mod(root, root, p); mpz_clear(foo), mpz_clear(bar); mpz_clear(s), mpz_clear(b), mpz_clear(t); return; } } } /* error, return zero root */ mpz_set_ui(root, 0L); }
static void test_modulo (gmp_randstate_t rands, const struct ecc_modulo *m) { mpz_t u; mpz_t v; mpz_t p; mpz_t r; mpz_t t; unsigned z, i; mp_limb_t *up; mp_limb_t *vp; mp_limb_t *rp; mp_limb_t *scratch; mpz_init (u); mpz_init (v); mpz_init (t); mpz_roinit_n (p, m->m, m->size); up = xalloc_limbs (m->size); vp = xalloc_limbs (m->size); rp = xalloc_limbs (2*m->size); scratch = xalloc_limbs (m->sqrt_itch); /* Find a non-square */ for (z = 2; mpz_ui_kronecker (z, p) != -1; z++) ; if (verbose) fprintf(stderr, "Non square: %d\n", z); for (i = 0; i < COUNT; i++) { if (i & 1) { mpz_rrandomb (u, rands, m->bit_size); mpz_rrandomb (v, rands, m->bit_size); } else { mpz_urandomb (u, rands, m->bit_size); mpz_urandomb (v, rands, m->bit_size); } mpz_limbs_copy (up, u, m->size); mpz_limbs_copy (vp, v, m->size); if (!m->sqrt (m, rp, up, vp, scratch)) { mpz_mul_ui (u, u, z); mpz_mod (u, u, p); mpz_limbs_copy (up, u, m->size); if (!m->sqrt (m, rp, up, vp, scratch)) { fprintf (stderr, "m->sqrt returned failure, bit_size = %d\n" "u = 0x", m->bit_size); mpz_out_str (stderr, 16, u); fprintf (stderr, "\nv = 0x"); mpz_out_str (stderr, 16, v); fprintf (stderr, "\n"); abort (); } } /* Check that r^2 v = u */ mpz_roinit_n (r, rp, m->size); mpz_mul (t, r, r); mpz_mul (t, t, v); if (!mpz_congruent_p (t, u, p)) { fprintf (stderr, "m->sqrt gave incorrect result, bit_size = %d\n" "u = 0x", m->bit_size); mpz_out_str (stderr, 16, u); fprintf (stderr, "\nv = 0x"); mpz_out_str (stderr, 16, v); fprintf (stderr, "\nr = 0x"); mpz_out_str (stderr, 16, r); fprintf (stderr, "\n"); abort (); } } mpz_clear (u); mpz_clear (v); mpz_clear (t); free (up); free (vp); free (rp); free (scratch); }