/*-------------------------------------------------------------------------*/ void sieve_xy_run_deg5(root_sieve_t *rs, uint64 lattice_size, double line_min, double line_max) { uint32 i, j; sieve_xy_t *xy = &rs->xydata; hit_t hitlist[MAX_CRT_FACTORS]; uint32 num_lattice_primes; uint32 num_lattices; uint32 y_blocks; int64 curr_y; double direction[3] = {0, 1, 0}; xy->lattice_size = lattice_size; xy->dbl_lattice_size = (double)lattice_size; uint64_2gmp(lattice_size, xy->mp_lattice_size); mpz_set_d(xy->y_base, line_min / lattice_size - 1); mpz_mul(xy->y_base, xy->y_base, xy->mp_lattice_size); y_blocks = (line_max - line_min) / lattice_size + 1; if (y_blocks > xy->y_blocks) { xy->x_line_min = (double *)xrealloc(xy->x_line_min, y_blocks * sizeof(double)); xy->x_line_max = (double *)xrealloc(xy->x_line_max, y_blocks * sizeof(double)); } xy->y_blocks = y_blocks; xy->num_lattices = 0; if (lattice_size == 1) { num_lattice_primes = xy->num_lattice_primes = 0; num_lattices = 1; if (num_lattices > xy->num_lattices) { xy->lattices = (lattice_t *)xrealloc(xy->lattices, num_lattices * sizeof(lattice_t)); } memset(xy->lattices, 0, sizeof(lattice_t)); } else { num_lattice_primes = xy->num_lattice_primes = find_lattice_primes(rs->primes, rs->num_primes, lattice_size, xy->lattice_primes); find_hits(xy->lattice_primes, num_lattice_primes, hitlist); for (i = 0, num_lattices = 1; i < num_lattice_primes; i++) { num_lattices *= hitlist[i].num_roots; } if (num_lattices > xy->num_lattices) { xy->lattices = (lattice_t *)xrealloc(xy->lattices, num_lattices * sizeof(lattice_t)); } compute_lattices(hitlist, num_lattice_primes, xy->lattices, lattice_size, num_lattices, 2); } xy->num_lattices = num_lattices; line_min = -10000; line_max = 10000; direction[0] = 1; direction[1] = 0; direction[2] = 0; curr_y = gmp2int64(xy->y_base); for (i = 0; i < y_blocks; i++) { dpoly_t apoly = rs->apoly; apoly.coeff[2] += rs->dbl_p * curr_y; apoly.coeff[1] -= rs->dbl_d * curr_y; compute_line_size(rs->max_norm, &apoly, rs->dbl_p, rs->dbl_d, direction, line_min, line_max, &line_min, &line_max); if (line_min >= line_max) { xy->x_line_min[i] = 0; xy->x_line_max[i] = 0; line_min = -10000; line_max = 10000; } else { xy->x_line_min[i] = line_min; xy->x_line_max[i] = line_max; } curr_y += lattice_size; } for (i = y_blocks; i; i--) { if (xy->x_line_min[i-1] != xy->x_line_max[i-1]) break; } y_blocks = i; for (i = 0; i < y_blocks; i++) { if (xy->x_line_min[i] != xy->x_line_max[i]) break; } mpz_addmul_ui(xy->y_base, xy->mp_lattice_size, i); y_blocks -= i; if (i > 0) { for (j = 0; j < y_blocks; j++) { xy->x_line_min[j] = xy->x_line_min[j+i]; xy->x_line_max[j] = xy->x_line_max[j+i]; } } xy->y_blocks = y_blocks; #if 0 printf("\n%.0lf %u %u\n", (double)lattice_size, y_blocks, num_lattices); #endif sieve_x_run_deg5(rs); }
int ecpp_test(unsigned long n) { mpz_t a, b, x0, y0, xt, yt, tmp; int z; int is_prime = 0; if (n <= USHRT_MAX) { return sieve_test(n); } mpz_init(a); mpz_init(b); mpz_init(x0); mpz_init(y0); mpz_init(xt); mpz_init(yt); mpz_init(tmp); #ifdef DEBUG gmp_fprintf(stderr, "\nTesting %d with ECPP...\n", n); #endif /* DEBUG */ for (;;) /* keep trying while the curve order factoring fails */ { for (;;) /* keep trying while n divides curve discriminant */ { /* initialise a random point P = (x0, y0) * and a random elliptic curve E(a, b): y^2 = x^3 + a*x + b * with b expressed in terms of (a, x0, y0) so the point lies on the curve */ mpz_set_ui(a, rand() % n); mpz_set_ui(x0, rand() % n); mpz_set_ui(y0, rand() % n); mpz_init(b); mpz_mul(b, y0, y0); mpz_mul(tmp, x0, x0); mpz_submul(b, tmp, x0); mpz_submul(b, a, x0); mpz_mod_ui(b, b, n); #ifdef DEBUG gmp_fprintf(stderr, "\n\tn = %d\n", n); gmp_fprintf(stderr, "\tE: y^2 = x^3 + %Zd * x + %Zd\n", a, b); gmp_fprintf(stderr, "\tP = (%Zd,%Zd,1)\n", x0, y0); #endif /* DEBUG */ /* the discriminant of the curve and n are required to be coprimes * -- if not, then either * A) n divides the discriminant -- a new curve must be generated * B) n is composite and a proper factor is found -- the algorithm can * terminate */ ec_discriminant(tmp, a, b); #ifdef DEBUG mpz_mod_ui(tmp, tmp, n); gmp_fprintf(stderr, "\tdelta(E/GF(n)) = %Zd\n", tmp); #endif /* DEBUG */ mpz_gcd_ui(tmp, tmp, n); #ifdef DEBUG gmp_fprintf(stderr, "\tgcd(delta, n) = %Zd\n", tmp); #endif /* DEBUG */ if (0 == mpz_cmp_ui(tmp, 1)) { break; } else if (0 != mpz_cmp_ui(tmp, n)) { #ifdef DEBUG gmp_fprintf(stderr, "\tfound a proper factor, %d is composite\n", n); #endif /* DEBUG */ is_prime = 0; goto cleanup_and_return; } } /* P + P != 0, or a new curve is generated */ z = ec_add(xt, yt, x0, y0, 1, x0, y0, 1, n, a); #ifdef DEBUG gmp_fprintf(stderr, "\t2 * P = (%Zd,%Zd,%d)\n", xt, yt, z); #endif /* DEBUG */ if (0 == z) { continue; } /* the curve order algorithm failing indicates n is composite */ if (!(ec_order(tmp, a, b, n))) { #ifdef DEBUG gmp_fprintf(stderr, "\tcurve order algorithm failed, %d must be composite\n", n); #endif /* DEBUG */ is_prime = 0; break; } #ifdef DEBUG gmp_fprintf(stderr, "\t|E/GF(n)| = %Zd\n", tmp); #endif /* DEBUG */ /* the curve order should be the multiple of 2 and a "probable prime" n -- * if the order is not even, a new curve is generated */ if (!mpz_even_p(tmp)) { #ifdef DEBUG gmp_fprintf(stderr, "\t|E/GF(n)| is odd, generating new curve...\n"); #endif /* DEBUG */ continue; } /* order * P = 0, or n is composite */ z = ec_times(xt, yt, x0, y0, 1, tmp, n, a); #ifdef DEBUG gmp_fprintf(stderr, "\t|E| * P = (%Zd,%Zd,%d)\n", xt, yt, z); #endif /* DEBUG */ if (0 != z) { #ifdef DEBUG gmp_fprintf(stderr, "\t|E| * P is non-zero, %d is composite\n", n); #endif /* DEBUG */ is_prime = 0; break; } /* at this point, order/2 being a prime implies n is a prime -- * a recursive call to ecpp_test is used to test order/2 for primality */ mpz_div_ui(tmp, tmp, 2); if (ecpp_test(mpz_get_ui(tmp))) { is_prime = 1; break; } } cleanup_and_return: mpz_clear(a); mpz_clear(b); mpz_clear(x0); mpz_clear(y0); mpz_clear(xt); mpz_clear(yt); mpz_clear(tmp); return is_prime; }
static PyObject * GMPy_MPZ_is_aprcl_prime(PyObject *self, PyObject *other) { mpz_t N; s64_t T, U; int i, j, H, I, J, K, P, Q, W, X; int IV, InvX, LEVELnow, NP, PK, PL, PM, SW, VK, TestedQs, TestingQs; int QQ, T1, T3, U1, U3, V1, V3; int break_this = 0; MPZ_Object *tempx; if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) { TYPE_ERROR("is_aprcl_prime() requires 'mpz' argument"); return NULL; } mpz_init(N); mpz_set(N, tempx->z); Py_DECREF(tempx); /* make sure the input is >= 2 and odd */ if (mpz_cmp_ui(N, 2) < 0) Py_RETURN_FALSE; if (mpz_divisible_ui_p(N, 2)) { if (mpz_cmp_ui(N, 2) == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; } /* only three small exceptions for this implementation */ /* with this set of P and Q primes */ if (mpz_cmp_ui(N, 3) == 0) Py_RETURN_TRUE; if (mpz_cmp_ui(N, 7) == 0) Py_RETURN_TRUE; if (mpz_cmp_ui(N, 11) == 0) Py_RETURN_TRUE; /* If the input number is larger than 7000 decimal digits we will just return whether it is a BPSW (probable) prime */ NumberLength = mpz_sizeinbase(N, 10); if (NumberLength > 7000) { VALUE_ERROR("value too large to test"); return NULL; } allocate_vars(); mpz_set(TestNbr, N); mpz_set_si(biS, 0); j = PK = PL = PM = 0; for (J = 0; J < PWmax; J++) { /* aiJX[J] = 0; */ mpz_set_ui(aiJX[J], 0); } break_this = 0; /* GetPrimes2Test : */ for (i = 0; i < LEVELmax; i++) { /* biS[0] = 2; */ mpz_set_ui(biS, 2); for (j = 0; j < aiNQ[i]; j++) { Q = aiQ[j]; if (aiT[i]%(Q-1) != 0) continue; U = aiT[i] * Q; do { U /= Q; /* MultBigNbrByLong(biS, Q, biS, NumberLength); */ mpz_mul_ui(biS, biS, Q); } while (U % Q == 0); // Exit loop if S^2 > N. if (CompareSquare(biS, TestNbr) > 0) { /* break GetPrimes2Test; */ break_this = 1; break; } } /* End for j */ if (break_this) break; } /* End for i */ if (i == LEVELmax) { /* too big */ free_vars(); VALUE_ERROR("value too large to test"); return NULL; } LEVELnow = i; TestingQs = j; T = aiT[LEVELnow]; NP = aiNP[LEVELnow]; MainStart: for (;;) { for (i = 0; i < NP; i++) { P = aiP[i]; if (T%P != 0) continue; SW = TestedQs = 0; /* Q = W = (int) BigNbrModLong(TestNbr, P * P); */ Q = W = mpz_fdiv_ui(TestNbr, P * P); for (J = P - 2; J > 0; J--) { W = (W * Q) % (P * P); } if (P > 2 && W != 1) { SW = 1; } for (;;) { for (j = TestedQs; j <= TestingQs; j++) { Q = aiQ[j] - 1; /* G = aiG[j]; */ K = 0; while (Q % P == 0) { K++; Q /= P; } Q = aiQ[j]; if (K == 0) { continue; } PM = 1; for (I = 1; I < K; I++) { PM = PM * P; } PL = (P - 1) * PM; PK = P * PM; for (I = 0; I < PK; I++) { /* aiJ0[I] = aiJ1[I] = 0; */ mpz_set_ui(aiJ0[I], 0); mpz_set_ui(aiJ1[I], 0); } if (P > 2) { JacobiSum(0, P, PL, Q); } else { if (K != 1) { JacobiSum(0, P, PL, Q); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } if (K != 2) { for (I = 0; I < PM; I++) { /* aiJW[I] = aiJ0[I]; */ mpz_set(aiJW[I], aiJ0[I]); } JacobiSum(1, P, PL, Q); for (I = 0; I < PM; I++) { /* aiJS[I] = aiJ0[I]; */ mpz_set(aiJS[I], aiJ0[I]); } JS_JW(PK, PL, PM, P); for (I = 0; I < PM; I++) { /* aiJ1[I] = aiJS[I]; */ mpz_set(aiJ1[I], aiJS[I]); } JacobiSum(2, P, PL, Q); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } for (I = 0; I < PM; I++) { /* aiJS[I] = aiJ0[I]; */ mpz_set(aiJS[I], aiJ0[I]); } JS_2(PK, PL, PM, P); for (I = 0; I < PM; I++) { /* aiJ2[I] = aiJS[I]; */ mpz_set(aiJ2[I], aiJS[I]); } } } } /* aiJ00[0] = aiJ01[0] = 1; */ mpz_set_ui(aiJ00[0], 1); mpz_set_ui(aiJ01[0], 1); for (I = 1; I < PK; I++) { /* aiJ00[I] = aiJ01[I] = 0; */ mpz_set_ui(aiJ00[I], 0); mpz_set_ui(aiJ01[I], 0); } /* VK = (int) BigNbrModLong(TestNbr, PK); */ VK = mpz_fdiv_ui(TestNbr, PK); for (I = 1; I < PK; I++) { if (I % P != 0) { U1 = 1; U3 = I; V1 = 0; V3 = PK; while (V3 != 0) { QQ = U3 / V3; T1 = U1 - V1 * QQ; T3 = U3 - V3 * QQ; U1 = V1; U3 = V3; V1 = T1; V3 = T3; } aiInv[I] = (U1 + PK) % PK; } else { aiInv[I] = 0; } } if (P != 2) { for (IV = 0; IV <= 1; IV++) { for (X = 1; X < PK; X++) { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ0[I]; */ mpz_set(aiJS[I], aiJ0[I]); } if (X % P == 0) { continue; } if (IV == 0) { /* LongToBigNbr(X, biExp, NumberLength); */ mpz_set_ui(biExp, X); } else { /* LongToBigNbr(VK * X / PK, biExp, NumberLength); */ mpz_set_ui(biExp, (VK * X) / PK); if ((VK * X) / PK == 0) { continue; } } JS_E(PK, PL, PM, P); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } InvX = aiInv[X]; for (I = 0; I < PK; I++) { J = (I * InvX) % PK; /* AddBigNbrModN(aiJW[J], aiJS[I], aiJW[J], TestNbr, NumberLength); */ mpz_add(aiJW[J], aiJW[J], aiJS[I]); } NormalizeJW(PK, PL, PM, P); if (IV == 0) { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ00[I]; */ mpz_set(aiJS[I], aiJ00[I]); } } else { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ01[I]; */ mpz_set(aiJS[I], aiJ01[I]); } } JS_JW(PK, PL, PM, P); if (IV == 0) { for (I = 0; I < PK; I++) { /* aiJ00[I] = aiJS[I]; */ mpz_set(aiJ00[I], aiJS[I]); } } else { for (I = 0; I < PK; I++) { /* aiJ01[I] = aiJS[I]; */ mpz_set(aiJ01[I], aiJS[I]); } } } /* end for X */ } /* end for IV */ } else { if (K == 1) { /* MultBigNbrByLongModN(1, Q, aiJ00[0], TestNbr, NumberLength); */ mpz_set_ui(aiJ00[0], Q); /* aiJ01[0] = 1; */ mpz_set_ui(aiJ01[0], 1); } else { if (K == 2) { if (VK == 1) { /* aiJ01[0] = 1; */ mpz_set_ui(aiJ01[0], 1); } /* aiJS[0] = aiJ0[0]; */ /* aiJS[1] = aiJ0[1]; */ mpz_set(aiJS[0], aiJ0[0]); mpz_set(aiJS[1], aiJ0[1]); JS_2(PK, PL, PM, P); if (VK == 3) { /* aiJ01[0] = aiJS[0]; */ /* aiJ01[1] = aiJS[1]; */ mpz_set(aiJ01[0], aiJS[0]); mpz_set(aiJ01[1], aiJS[1]); } /* MultBigNbrByLongModN(aiJS[0], Q, aiJ00[0], TestNbr, NumberLength); */ mpz_mul_ui(aiJ00[0], aiJS[0], Q); /* MultBigNbrByLongModN(aiJS[1], Q, aiJ00[1], TestNbr, NumberLength); */ mpz_mul_ui(aiJ00[1], aiJS[1], Q); } else { for (IV = 0; IV <= 1; IV++) { for (X = 1; X < PK; X += 2) { for (I = 0; I <= PM; I++) { /* aiJS[I] = aiJ1[I]; */ mpz_set(aiJS[I], aiJ1[I]); } if (X % 8 == 5 || X % 8 == 7) { continue; } if (IV == 0) { /* LongToBigNbr(X, biExp, NumberLength); */ mpz_set_ui(biExp, X); } else { /* LongToBigNbr(VK * X / PK, biExp, NumberLength); */ mpz_set_ui(biExp, VK * X / PK); if (VK * X / PK == 0) { continue; } } JS_E(PK, PL, PM, P); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } InvX = aiInv[X]; for (I = 0; I < PK; I++) { J = I * InvX % PK; /* AddBigNbrModN(aiJW[J], aiJS[I], aiJW[J], TestNbr, NumberLength); */ mpz_add(aiJW[J], aiJW[J], aiJS[I]); } NormalizeJW(PK, PL, PM, P); if (IV == 0) { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ00[I]; */ mpz_set(aiJS[I], aiJ00[I]); } } else { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ01[I]; */ mpz_set(aiJS[I], aiJ01[I]); } } NormalizeJS(PK, PL, PM, P); JS_JW(PK, PL, PM, P); if (IV == 0) { for (I = 0; I < PK; I++) { /* aiJ00[I] = aiJS[I]; */ mpz_set(aiJ00[I], aiJS[I]); } } else { for (I = 0; I < PK; I++) { /* aiJ01[I] = aiJS[I]; */ mpz_set(aiJ01[I], aiJS[I]); } } } /* end for X */ if (IV == 0 || VK % 8 == 1 || VK % 8 == 3) { continue; } for (I = 0; I < PM; I++) { /* aiJW[I] = aiJ2[I]; */ /* aiJS[I] = aiJ01[I]; */ mpz_set(aiJW[I], aiJ2[I]); mpz_set(aiJS[I], aiJ01[I]); } for (; I < PK; I++) { /* aiJW[I] = aiJS[I] = 0; */ mpz_set_ui(aiJW[I], 0); mpz_set_ui(aiJS[I], 0); } JS_JW(PK, PL, PM, P); for (I = 0; I < PM; I++) { /* aiJ01[I] = aiJS[I]; */ mpz_set(aiJ01[I], aiJS[I]); } } /* end for IV */ } } } for (I = 0; I < PL; I++) { /* aiJS[I] = aiJ00[I]; */ mpz_set(aiJS[I], aiJ00[I]); } for (; I < PK; I++) { /* aiJS[I] = 0; */ mpz_set_ui(aiJS[I], 0); } /* DivBigNbrByLong(TestNbr, PK, biExp, NumberLength); */ mpz_fdiv_q_ui(biExp, TestNbr, PK); JS_E(PK, PL, PM, P); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } for (I = 0; I < PL; I++) { for (J = 0; J < PL; J++) { /* MontgomeryMult(aiJS[I], aiJ01[J], biTmp); */ /* AddBigNbrModN(biTmp, aiJW[(I + J) % PK], aiJW[(I + J) % PK], TestNbr, NumberLength); */ mpz_mul(biTmp, aiJS[I], aiJ01[J]); mpz_add(aiJW[(I + J) % PK], biTmp, aiJW[(I + J) % PK]); } } NormalizeJW(PK, PL, PM, P); /* MatchingRoot : */ do { H = -1; W = 0; for (I = 0; I < PL; I++) { if (mpz_cmp_ui(aiJW[I], 0) != 0)/* (!BigNbrIsZero(aiJW[I])) */ { /* if (H == -1 && BigNbrAreEqual(aiJW[I], 1)) */ if (H == -1 && (mpz_cmp_ui(aiJW[I], 1) == 0)) { H = I; } else { H = -2; /* AddBigNbrModN(aiJW[I], MontgomeryMultR1, biTmp, TestNbr, NumberLength); */ mpz_add_ui(biTmp, aiJW[I], 1); mpz_mod(biTmp, biTmp, TestNbr); if (mpz_cmp_ui(biTmp, 0) == 0) /* (BigNbrIsZero(biTmp)) */ { W++; } } } } if (H >= 0) { /* break MatchingRoot; */ break; } if (W != P - 1) { /* Not prime */ free_vars(); Py_RETURN_FALSE; } for (I = 0; I < PM; I++) { /* AddBigNbrModN(aiJW[I], 1, biTmp, TestNbr, NumberLength); */ mpz_add_ui(biTmp, aiJW[I], 1); mpz_mod(biTmp, biTmp, TestNbr); if (mpz_cmp_ui(biTmp, 0) == 0) /* (BigNbrIsZero(biTmp)) */ { break; } } if (I == PM) { /* Not prime */ free_vars(); Py_RETURN_FALSE; } for (J = 1; J <= P - 2; J++) { /* AddBigNbrModN(aiJW[I + J * PM], 1, biTmp, TestNbr, NumberLength); */ mpz_add_ui(biTmp, aiJW[I + J * PM], 1); mpz_mod(biTmp, biTmp, TestNbr); if (mpz_cmp_ui(biTmp, 0) != 0)/* (!BigNbrIsZero(biTmp)) */ { /* Not prime */ free_vars(); Py_RETURN_FALSE; } } H = I + PL; } while (0); if (SW == 1 || H % P == 0) { continue; } if (P != 2) { SW = 1; continue; } if (K == 1) { if ((mpz_get_ui(TestNbr) & 3) == 1) { SW = 1; } continue; } // if (Q^((N-1)/2) mod N != N-1), N is not prime. /* MultBigNbrByLongModN(1, Q, biTmp, TestNbr, NumberLength); */ mpz_set_ui(biTmp, Q); mpz_mod(biTmp, biTmp, TestNbr); mpz_sub_ui(biT, TestNbr, 1); /* biT = n-1 */ mpz_divexact_ui(biT, biT, 2); /* biT = (n-1)/2 */ mpz_powm(biR, biTmp, biT, TestNbr); /* biR = Q^((n-1)/2) mod n */ mpz_add_ui(biTmp, biR, 1); mpz_mod(biTmp, biTmp, TestNbr); if (mpz_cmp_ui(biTmp, 0) != 0)/* (!BigNbrIsZero(biTmp)) */ { /* Not prime */ free_vars(); Py_RETURN_FALSE; } SW = 1; } /* end for j */ if (SW == 0) { TestedQs = TestingQs + 1; if (TestingQs < aiNQ[LEVELnow] - 1) { TestingQs++; Q = aiQ[TestingQs]; U = T * Q; do { /* MultBigNbrByLong(biS, Q, biS, NumberLength); */ mpz_mul_ui(biS, biS, Q); U /= Q; } while (U % Q == 0); continue; /* Retry */ } LEVELnow++; if (LEVELnow == LEVELmax) { free_vars(); // return mpz_bpsw_prp(N); /* Cannot tell */ VALUE_ERROR("maximum levels reached"); return NULL; } T = aiT[LEVELnow]; NP = aiNP[LEVELnow]; /* biS = 2; */ mpz_set_ui(biS, 2); for (J = 0; J <= aiNQ[LEVELnow]; J++) { Q = aiQ[J]; if (T%(Q-1) != 0) continue; U = T * Q; do { /* MultBigNbrByLong(biS, Q, biS, NumberLength); */ mpz_mul_ui(biS, biS, Q); U /= Q; } while (U % Q == 0); if (CompareSquare(biS, TestNbr) > 0) { TestingQs = J; /* continue MainStart; */ /* Retry from the beginning */ goto MainStart; } } /* end for J */ free_vars(); VALUE_ERROR("internal failure"); return NULL; } /* end if */ break; } /* end for (;;) */ } /* end for i */ // Final Test /* biR = 1 */ mpz_set_ui(biR, 1); /* biN <- TestNbr mod biS */ /* Compute N mod S */ mpz_fdiv_r(biN, TestNbr, biS); for (U = 1; U <= T; U++) { /* biR <- (biN * biR) mod biS */ mpz_mul(biR, biN, biR); mpz_mod(biR, biR, biS); if (mpz_cmp_ui(biR, 1) == 0) /* biR == 1 */ { /* Number is prime */ free_vars(); Py_RETURN_TRUE; } if (mpz_divisible_p(TestNbr, biR) && mpz_cmp(biR, TestNbr) < 0) /* biR < N and biR | TestNbr */ { /* Number is composite */ free_vars(); Py_RETURN_FALSE; } } /* End for U */ /* This should never be reached. */ free_vars(); SYSTEM_ERROR("Internal error: APR-CL error with final test."); return NULL; } }
static void zp_mul_mpz(element_ptr n, element_ptr a, mpz_ptr z) { mpz_mul(n->data, a->data, z); mpz_mod(n->data, n->data, n->field->order); }
void mpz_gcdext (mpz_ptr g, mpz_ptr s, mpz_ptr t, mpz_srcptr a, mpz_srcptr b) { mp_size_t asize, bsize; mp_ptr tmp_ap, tmp_bp; mp_size_t gsize, ssize, tmp_ssize; mp_ptr gp, tmp_gp, tmp_sp; TMP_DECL; /* mpn_gcdext requires that Usize >= Vsize. Therefore, we often have to swap U and V. The computed cofactor will be the "smallest" one, which is faster to produce. The wanted one will be computed here; this is needed anyway when both are requested. */ asize = ABSIZ (a); bsize = ABSIZ (b); if (asize < bsize) { MPZ_SRCPTR_SWAP (a, b); MP_SIZE_T_SWAP (asize, bsize); MPZ_PTR_SWAP (s, t); } if (bsize == 0) { /* g = |a|, s = sgn(a), t = 0. */ ssize = SIZ (a) >= 0 ? (asize != 0) : -1; gp = MPZ_REALLOC (g, asize); MPN_COPY (gp, PTR (a), asize); SIZ (g) = asize; if (t != NULL) SIZ (t) = 0; if (s != NULL) { SIZ (s) = ssize; PTR (s)[0] = 1; } return; } TMP_MARK; TMP_ALLOC_LIMBS_2 (tmp_ap, asize, tmp_bp, bsize); MPN_COPY (tmp_ap, PTR (a), asize); MPN_COPY (tmp_bp, PTR (b), bsize); TMP_ALLOC_LIMBS_2 (tmp_gp, bsize, tmp_sp, bsize + 1); gsize = mpn_gcdext (tmp_gp, tmp_sp, &tmp_ssize, tmp_ap, asize, tmp_bp, bsize); ssize = ABS (tmp_ssize); tmp_ssize = SIZ (a) >= 0 ? tmp_ssize : -tmp_ssize; if (t != NULL) { mpz_t x; __mpz_struct gtmp, stmp; PTR (>mp) = tmp_gp; SIZ (>mp) = gsize; PTR (&stmp) = tmp_sp; SIZ (&stmp) = tmp_ssize; MPZ_TMP_INIT (x, ssize + asize + 1); mpz_mul (x, &stmp, a); mpz_sub (x, >mp, x); mpz_divexact (t, x, b); } if (s != NULL) { mp_ptr sp; sp = MPZ_REALLOC (s, ssize); MPN_COPY (sp, tmp_sp, ssize); SIZ (s) = tmp_ssize; } gp = MPZ_REALLOC (g, gsize); MPN_COPY (gp, tmp_gp, gsize); SIZ (g) = gsize; TMP_FREE; }
/* If x^y is exactly representable (with maybe a larger precision than z), round it in z and return the (mpc) inexact flag in [0, 10]. If x^y is not exactly representable, return -1. If intermediate computations lead to numbers of more than maxprec bits, then abort and return -2 (in that case, to avoid loops, mpc_pow_exact should be called again with a larger value of maxprec). Assume one of Re(x) or Im(x) is non-zero, and y is non-zero (y is real). */ static int mpc_pow_exact (mpc_ptr z, mpc_srcptr x, mpfr_srcptr y, mpc_rnd_t rnd, mp_prec_t maxprec) { mp_exp_t ec, ed, ey, emin, emax; mpz_t my, a, b, c, d, u; unsigned long int t; int ret = -2; mpz_init (my); mpz_init (a); mpz_init (b); mpz_init (c); mpz_init (d); mpz_init (u); ey = mpfr_get_z_exp (my, y); /* normalize so that my is odd */ t = mpz_scan1 (my, 0); ey += t; mpz_tdiv_q_2exp (my, my, t); if (mpfr_zero_p (MPC_RE(x))) { mpz_set_ui (c, 0); ec = 0; } else ec = mpfr_get_z_exp (c, MPC_RE(x)); if (mpfr_zero_p (MPC_IM(x))) { mpz_set_ui (d, 0); ed = ec; } else { ed = mpfr_get_z_exp (d, MPC_IM(x)); if (mpfr_zero_p (MPC_RE(x))) ec = ed; } /* x = c*2^ec + I * d*2^ed */ /* equalize the exponents of x */ if (ec < ed) { mpz_mul_2exp (d, d, ed - ec); if (mpz_sizeinbase (d, 2) > maxprec) goto end; ed = ec; } else if (ed < ec) { mpz_mul_2exp (c, c, ec - ed); if (mpz_sizeinbase (c, 2) > maxprec) goto end; ec = ed; } /* now ec=ed and x = (c + I * d) * 2^ec */ /* divide by two if possible */ if (mpz_cmp_ui (c, 0) == 0) { t = mpz_scan1 (d, 0); mpz_tdiv_q_2exp (d, d, t); ec += t; } else if (mpz_cmp_ui (d, 0) == 0) { t = mpz_scan1 (c, 0); mpz_tdiv_q_2exp (c, c, t); ec += t; } else /* neither c nor d is zero */ { unsigned long v; t = mpz_scan1 (c, 0); v = mpz_scan1 (d, 0); if (v < t) t = v; mpz_tdiv_q_2exp (c, c, t); mpz_tdiv_q_2exp (d, d, t); ec += t; } /* now either one of c, d is odd */ while (ey < 0) { /* check if x is a square */ if (ec & 1) { mpz_mul_2exp (c, c, 1); mpz_mul_2exp (d, d, 1); ec --; } /* now ec is even */ if (mpc_perfect_square_p (a, b, c, d) == 0) break; mpz_swap (a, c); mpz_swap (b, d); ec /= 2; ey ++; } if (ey < 0) { ret = -1; /* not representable */ goto end; } /* Now ey >= 0, it thus suffices to check that x^my is representable. If my > 0, this is always true. If my < 0, we first try to invert (c+I*d)*2^ec. */ if (mpz_cmp_ui (my, 0) < 0) { /* If my < 0, 1 / (c + I*d) = (c - I*d)/(c^2 + d^2), thus a sufficient condition is that c^2 + d^2 is a power of two, assuming |c| <> |d|. Assume a prime p <> 2 divides c^2 + d^2, then if p does not divide c or d, 1 / (c + I*d) cannot be exact. If p divides both c and d, then we can write c = p*c', d = p*d', and 1 / (c + I*d) = 1/p * 1/(c' + I*d'). This shows that if 1/(c+I*d) is exact, then 1/(c' + I*d') is exact too, and we are back to the previous case. In conclusion, a necessary and sufficient condition is that c^2 + d^2 is a power of two. */ /* FIXME: we could first compute c^2+d^2 mod a limb for example */ mpz_mul (a, c, c); mpz_addmul (a, d, d); t = mpz_scan1 (a, 0); if (mpz_sizeinbase (a, 2) != 1 + t) /* a is not a power of two */ { ret = -1; /* not representable */ goto end; } /* replace (c,d) by (c/(c^2+d^2), -d/(c^2+d^2)) */ mpz_neg (d, d); ec = -ec - t; mpz_neg (my, my); } /* now ey >= 0 and my >= 0, and we want to compute [(c + I * d) * 2^ec] ^ (my * 2^ey). We first compute [(c + I * d) * 2^ec]^my, then square ey times. */ t = mpz_sizeinbase (my, 2) - 1; mpz_set (a, c); mpz_set (b, d); ed = ec; /* invariant: (a + I*b) * 2^ed = ((c + I*d) * 2^ec)^trunc(my/2^t) */ while (t-- > 0) { unsigned long v, w; /* square a + I*b */ mpz_mul (u, a, b); mpz_mul (a, a, a); mpz_submul (a, b, b); mpz_mul_2exp (b, u, 1); ed *= 2; if (mpz_tstbit (my, t)) /* multiply by c + I*d */ { mpz_mul (u, a, c); mpz_submul (u, b, d); /* ac-bd */ mpz_mul (b, b, c); mpz_addmul (b, a, d); /* bc+ad */ mpz_swap (a, u); ed += ec; } /* remove powers of two in (a,b) */ if (mpz_cmp_ui (a, 0) == 0) { w = mpz_scan1 (b, 0); mpz_tdiv_q_2exp (b, b, w); ed += w; } else if (mpz_cmp_ui (b, 0) == 0) { w = mpz_scan1 (a, 0); mpz_tdiv_q_2exp (a, a, w); ed += w; } else { w = mpz_scan1 (a, 0); v = mpz_scan1 (b, 0); if (v < w) w = v; mpz_tdiv_q_2exp (a, a, w); mpz_tdiv_q_2exp (b, b, w); ed += w; } if (mpz_sizeinbase (a, 2) > maxprec || mpz_sizeinbase (b, 2) > maxprec) goto end; } /* now a+I*b = (c+I*d)^my */ while (ey-- > 0) { unsigned long sa, sb; /* square a + I*b */ mpz_mul (u, a, b); mpz_mul (a, a, a); mpz_submul (a, b, b); mpz_mul_2exp (b, u, 1); ed *= 2; /* divide by largest 2^n possible, to avoid many loops for e.g., (2+2*I)^16777216 */ sa = mpz_scan1 (a, 0); sb = mpz_scan1 (b, 0); sa = (sa <= sb) ? sa : sb; mpz_tdiv_q_2exp (a, a, sa); mpz_tdiv_q_2exp (b, b, sa); ed += sa; if (mpz_sizeinbase (a, 2) > maxprec || mpz_sizeinbase (b, 2) > maxprec) goto end; } /* save emin, emax */ emin = mpfr_get_emin (); emax = mpfr_get_emax (); mpfr_set_emin (mpfr_get_emin_min ()); mpfr_set_emax (mpfr_get_emax_max ()); ret = mpfr_set_z (MPC_RE(z), a, MPC_RND_RE(rnd)); ret = MPC_INEX(ret, mpfr_set_z (MPC_IM(z), b, MPC_RND_IM(rnd))); mpfr_mul_2si (MPC_RE(z), MPC_RE(z), ed, MPC_RND_RE(rnd)); mpfr_mul_2si (MPC_IM(z), MPC_IM(z), ed, MPC_RND_IM(rnd)); /* restore emin, emax */ mpfr_set_emin (emin); mpfr_set_emax (emax); end: mpz_clear (my); mpz_clear (a); mpz_clear (b); mpz_clear (c); mpz_clear (d); mpz_clear (u); return ret; }
int main(int argc, char *argv[]) { size_t i; unsigned int password_found; struct SRP_mitm_t mitm; struct server_t s; struct client_t c; mpz_t N, g, k, u, useless_u, x; mpz_t tmp_base, tmp_e, S; uint8_t buf[SHA256_HASH_SIZE]; struct sha256nfo ctx; char *c_salt_str, *s_salt_str, *email, *candidate_p; mpz_init_set_str(N, NIST_N, 16 ); mpz_init_set_str(g, NIST_g, 0 ); mpz_init_set_str(k, NIST_k, 0 ); // Init server server_init(&s, N, g, k, 1); server_add_entry(&s, "*****@*****.**", 16, "password123", 11); // Init client client_init(&c, N, g, k); // Init MITM server_init(&(mitm.s), N, g, k, 1); server_add_entry(&(mitm.s), "*****@*****.**", 16, "uselesspass", 11); client_init(&(mitm.c), N, g, k); /* * MITM client pubkey interception * * S <--A-- MITM <--A-- C * --u--> MITM --u--> C */ email = "*****@*****.**"; c_salt_str = mitm_server_init_shared(&(mitm.s), email, strlen(email), c.srp.pubkey, &u); s_salt_str = server_init_shared(&s, email, strlen(email), mitm.c.srp.pubkey, &useless_u); if (NULL != c_salt_str) { c.salt_str = malloc(strlen(c_salt_str)*sizeof(char)); if (NULL != c.salt_str) { /* * The MITM attacker does not know the client private DH key 'a'. * However sending B == g cirumvent this unknown, since : * S = B**(a + ux) % n <==> S = (g**a).(g**ux) %n * <==> S = A.g**ux %n */ c.salt_len = strlen(c_salt_str); memcpy(c.salt_str, c_salt_str, strlen(c_salt_str)); client_init_shared(&c, "password123", strlen("password123") , mitm.s.srp.pubkey , u); /* * MITM offline dictionnary attack */ i = 0x00; password_found = 0x00; candidate_p = weak_passwords[0]; while (NULL != candidate_p && !password_found) { srp_utils_gen_x(&x, candidate_p, strlen(candidate_p),c_salt_str, strlen(c_salt_str)); // g**(u.x) mpz_init(tmp_base); mpz_init_set(tmp_e, u); mpz_mul(tmp_e, tmp_e, x ); mpz_powm(tmp_base, g, tmp_e, N); mpz_init(S); mpz_mul(S, mitm.c.srp.pubkey, tmp_base ); mpz_mod(S, S, N); srp_utils_gen_shared_key(mitm.c.K, S); mpz_clear(tmp_base); mpz_clear(tmp_e); mpz_clear(S); mpz_clear(x); if (!memcmp(mitm.c.K, c.K, sizeof(c.K))) { printf("Password successfully infered : %s !\n", candidate_p); password_found = 0x01; } else { i++; candidate_p = weak_passwords[i]; } } /* * Final server validation */ if (password_found) { mitm.c.salt_len = strlen(s_salt_str); mitm.c.salt_str = malloc(strlen(s_salt_str)*sizeof(char)); if (NULL == mitm.c.salt_str) return 0x01; memcpy(mitm.c.salt_str, s_salt_str, strlen(s_salt_str)); client_init_shared(&(mitm.c), candidate_p, strlen(candidate_p) , s.srp.pubkey, useless_u); sha256_init_Hmac(&ctx, mitm.c.K, SHA256_HASH_SIZE); sha256_write(&ctx, (uint8_t*) mitm.c.salt_str, mitm.c.salt_len); sha256_result_Hmac(&ctx, buf); if (server_check_password(&s, email, strlen(email), buf)) printf("We have a valid user : %s !\n", email); else printf("The following user is not registered : %s !\n", email); } else printf("The following user is not registered : %s !\n", email); } } else printf("The following user is not registered : %s !\n", email); client_cleanup(&c); server_cleanup(&s); server_cleanup(&(mitm.s)); client_cleanup(&(mitm.c)); mpz_clear(N); mpz_clear(g); mpz_clear(k); return 0x00; }
void zFermat(uint64 limit, uint32 mult, fact_obj_t *fobj) { // Fermat's factorization method with a sieve-based improvement // provided by 'neonsignal' mpz_t a, b2, tmp, multN, a2; int i; int numChars; uint64 reportIt, reportInc; uint64 count; uint64 i64; FILE *flog = NULL; uint32 M = 2 * 2 * 2 * 2 * 3 * 3 * 5 * 5 * 7 * 7; //176400u uint32 M1 = 11 * 17 * 23 * 31; //133331u uint32 M2 = 13 * 19 * 29 * 37; //265031u uint8 *sqr, *sqr1, *sqr2, *mod, *mod1, *mod2; uint16 *skip; uint32 m, mmn, s, d; uint8 masks[8] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; uint8 nmasks[8]; uint32 iM = 0, iM1 = 0, iM2 = 0; if (mpz_even_p(fobj->div_obj.gmp_n)) { mpz_init(tmp); mpz_set_ui(tmp, 2); mpz_tdiv_q_2exp(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, 1); add_to_factor_list(fobj, tmp); mpz_clear(tmp); return; } if (mpz_perfect_square_p(fobj->div_obj.gmp_n)) { //open the log file flog = fopen(fobj->flogname,"a"); if (flog == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open %s for writing\n",fobj->flogname); return; } mpz_sqrt(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n); if (is_mpz_prp(fobj->div_obj.gmp_n)) { logprint(flog, "Fermat method found perfect square factorization:\n"); logprint(flog,"prp%d = %s\n", gmp_base10(fobj->div_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n)); logprint(flog,"prp%d = %s\n", gmp_base10(fobj->div_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n)); } else { logprint(flog, "Fermat method found perfect square factorization:\n"); logprint(flog,"c%d = %s\n", gmp_base10(fobj->div_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n)); logprint(flog,"c%d = %s\n", gmp_base10(fobj->div_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n)); } add_to_factor_list(fobj, fobj->div_obj.gmp_n); add_to_factor_list(fobj, fobj->div_obj.gmp_n); mpz_set_ui(fobj->div_obj.gmp_n, 1); fclose(flog); return; } mpz_init(a); mpz_init(b2); mpz_init(tmp); mpz_init(multN); mpz_init(a2); // apply the user supplied multiplier mpz_mul_ui(multN, fobj->div_obj.gmp_n, mult); // compute ceil(sqrt(multN)) mpz_sqrt(a, multN); // form b^2 mpz_mul(b2, a, a); mpz_sub(b2, b2, multN); // test successive 'a' values using a sieve-based approach. // the idea is that not all 'a' values allow a^2 or b^2 to be square. // we pre-compute allowable 'a' values modulo various smooth numbers and // build tables to allow us to quickly iterate over 'a' values that are // more likely to produce squares. // init sieve structures sqr = (uint8 *)calloc((M / 8 + 1) , sizeof(uint8)); sqr1 = (uint8 *)calloc((M1 / 8 + 1) , sizeof(uint8)); sqr2 = (uint8 *)calloc((M2 / 8 + 1) , sizeof(uint8)); mod = (uint8 *)calloc((M / 8 + 1) , sizeof(uint8)); mod1 = (uint8 *)calloc((M1 / 8 + 1) , sizeof(uint8)); mod2 = (uint8 *)calloc((M2 / 8 + 1) , sizeof(uint8)); skip = (uint16 *)malloc(M * sizeof(uint16)); // test it. This will be good enough if |u*p-v*q| < 2 * N^(1/4), where // mult = u*v count = 0; if (mpz_perfect_square_p(b2)) goto found; for (i=0; i<8; i++) nmasks[i] = ~masks[i]; // marks locations where squares can occur mod M, M1, M2 for (i64 = 0; i64 < M; ++i64) setbit(sqr, (i64*i64)%M); for (i64 = 0; i64 < M1; ++i64) setbit(sqr1, (i64*i64)%M1); for (i64 = 0; i64 < M2; ++i64) setbit(sqr2, (i64*i64)%M2); // for the modular sequence of b*b = a*a - n values // (where b2_2 = b2_1 * 2a + 1), mark locations where // b^2 can be a square m = mpz_mod_ui(tmp, a, M); mmn = mpz_mod_ui(tmp, b2, M); for (i = 0; i < M; ++i) { if (getbit(sqr, mmn)) setbit(mod, i); mmn = (mmn+m+m+1)%M; m = (m+1)%M; } // we only consider locations where the modular sequence mod M can // be square, so compute the distance to the next square location // at each possible value of i mod M. s = 0; d = 0; for (i = 0; !getbit(mod,i); ++i) ++s; for (i = M; i > 0;) { --i; ++s; skip[i] = s; if (s > d) d = s; if (getbit(mod,i)) s = 0; } //printf("maxSkip = %u\n", d); // for the modular sequence of b*b = a*a - n values // (where b2_2 = b2_1 * 2a + 1), mark locations where the // modular sequence can be a square mod M1. These will // generally differ from the sequence mod M. m = mpz_mod_ui(tmp, a, M1); mmn = mpz_mod_ui(tmp, b2, M1); for (i = 0; i < M1; ++i) { if (getbit(sqr1, mmn)) setbit(mod1, i); mmn = (mmn+m+m+1)%M1; m = (m+1)%M1; } // for the modular sequence of b*b = a*a - n values // (where b2_2 = b2_1 * 2a + 1), mark locations where the // modular sequence can be a square mod M2. These will // generally differ from the sequence mod M or M1. m = mpz_mod_ui(tmp, a, M2); mmn = mpz_mod_ui(tmp, b2, M2); for (i = 0; i < M2; ++i) { if (getbit(sqr2, mmn)) setbit(mod2, i); mmn = (mmn+m+m+1)%M2; m = (m+1)%M2; } // loop, checking for perfect squares mpz_mul_2exp(a2, a, 1); count = 0; numChars = 0; reportIt = limit / 100; reportInc = reportIt; do { d = 0; i64 = 0; do { // skip to the next possible square residue of b*b mod M s = skip[iM]; // remember how far we skipped d += s; // update the other residue indices if ((iM1 += s) >= M1) iM1 -= M1; if ((iM2 += s) >= M2) iM2 -= M2; if ((iM += s) >= M) iM -= M; // some multpliers can lead to infinite loops. bail out // if so. if (++i64 > M) goto done; // continue if either of the other residues indicates // non-square. } while (!getbit(mod1,iM1) || !getbit(mod2,iM2)); // form b^2 by incrementing by many factors of 2*a+1 mpz_add_ui(tmp, a2, d); mpz_mul_ui(tmp, tmp, d); mpz_add(b2, b2, tmp); // accumulate so that we can reset d // (and thus keep it single precision) mpz_add_ui(a2, a2, d*2); count += d; if (count > limit) break; //progress report if ((count > reportIt) && (VFLAG > 1)) { for (i=0; i< numChars; i++) printf("\b"); numChars = printf("%" PRIu64 "%%",(uint64)((double)count / (double)limit * 100)); fflush(stdout); reportIt += reportInc; } } while (!mpz_perfect_square_p(b2)); found: // 'count' is how far we had to scan 'a' to find a square b mpz_add_ui(a, a, count); //printf("count is %" PRIu64 "\n", count); if ((mpz_size(b2) > 0) && mpz_perfect_square_p(b2)) { //printf("found square at count = %d: a = %s, b2 = %s",count, // z2decstr(&a,&gstr1),z2decstr(&b2,&gstr2)); mpz_sqrt(tmp, b2); mpz_add(tmp, a, tmp); mpz_gcd(tmp, fobj->div_obj.gmp_n, tmp); flog = fopen(fobj->flogname,"a"); if (flog == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open %s for writing\n",fobj->flogname); goto done; } logprint(flog, "Fermat method found factors:\n"); add_to_factor_list(fobj, tmp); if (is_mpz_prp(tmp)) { logprint(flog,"prp%d = %s\n", gmp_base10(tmp), mpz_conv2str(&gstr1.s, 10, tmp)); } else { logprint(flog,"c%d = %s\n", gmp_base10(tmp), mpz_conv2str(&gstr1.s, 10, tmp)); } mpz_tdiv_q(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, tmp); mpz_sqrt(tmp, b2); mpz_sub(tmp, a, tmp); mpz_gcd(tmp, fobj->div_obj.gmp_n, tmp); add_to_factor_list(fobj, tmp); if (is_mpz_prp(tmp)) { logprint(flog,"prp%d = %s\n", gmp_base10(tmp), mpz_conv2str(&gstr1.s, 10, tmp)); } else { logprint(flog,"c%d = %s\n", gmp_base10(tmp), mpz_conv2str(&gstr1.s, 10, tmp)); } mpz_tdiv_q(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, tmp); } done: mpz_clear(tmp); mpz_clear(a); mpz_clear(b2); mpz_clear(multN); mpz_clear(a2); free(sqr); free(sqr1); free(sqr2); free(mod); free(mod1); free(mod2); free(skip); if (flog != NULL) fclose(flog); return; }
void rsa_generate(unsigned int b_size) { mpz_t p, q, n, d, e, phi; mpz_t phi_p, phi_q, p_mod; int p_size = b_size/2, q_size = b_size - b_size/2; mpz_init(p); mpz_init(q); mpz_init(n); mpz_init(d); mpz_init(e); mpz_init(phi); mpz_init(phi_p); mpz_init(phi_q); mpz_init(p_mod); do { /* prvocisla p,q */ do { do { /* p */ gen_prime(p_size,p); /* q */ gen_prime(q_size,q); } while(mpz_cmp(p,q) == 0);/* p a q sa nerovnaju */ /* phi */ mpz_sub_ui(phi_p,p,1); mpz_sub_ui(phi_q,q,1); mpz_mul(phi,phi_q,phi_p); /* e */ if(mpz_cmp_ui(phi,65537) > 0) { /* phi > 65537 */ mpz_set_ui(e,65537); } else if(mpz_cmp_ui(phi,17) > 0) { /* phi > 17 */ mpz_set_ui(e,17); } else { mpz_set_ui(e,3); } mpz_mod(p_mod,p,e); } while(mpz_cmp_ui(p_mod,1) == 0);/* (p mod e) !=1 */ /* modulus n */ mpz_mul(n,p,q); /* d */ modular_inverse(e,phi,d); } while(mpz_cmp_ui(d,0) == 0); /* dokial nenajdes spravne, pre ktore existuj inverzia */ #ifdef DEBUG gmp_printf("p: %Zd\nq: %Zd\nn: %Zd\nphi: %Zd\ne: %Zd\nd: %Zd\n",p,q,n,phi,e,d); #endif gmp_printf("0x%Zx 0x%Zx 0x%Zx 0x%Zx 0x%Zx\n",p,q,n,e,d); mpz_clear(p); mpz_clear(q); mpz_clear(n); mpz_clear(d); mpz_clear(e); mpz_clear(phi); mpz_clear(phi_p); mpz_clear(phi_q); mpz_clear(p_mod); }
void ecn_mul(mpz_t t1, mpz_t t2, mpz_t s, mpz_t rx, mpz_t ry, mpz_t modulus, mpz_t a, mpz_t b, mpz_t x1, mpz_t y1, mpz_t x2, mpz_t y2) { /* If the first point is the unit element, then we copy the other point. */ if (mpz_cmp_si(x1, -1) == 0) { mpz_set(rx, x2); mpz_set(ry, y2); return; } /* If the second point is the unit element, then we copy the other point. */ if (mpz_cmp_si(x2, -1) == 0) { mpz_set(rx, x1); mpz_set(ry, y1); return; } /* If the second point is inverse of the first point, then we return the unit point. */ mpz_add(t1, y1, y2); if (mpz_cmp(x1, x2) == 0 && mpz_cmp(t1, modulus) == 0) { mpz_set_si(rx, -1); mpz_set_si(ry, -1); return; } /* If the first and second points are identical, then we square it. */ if (mpz_cmp(x1, x2) == 0 && mpz_cmp(y1, y2) == 0) { ecn_square(t1, t2, s, rx, ry, modulus, a, b, x1, x2); return; } /* s = (y1 - y2) / (x1 - x2) */ mpz_sub(t1, y1, y2); mpz_sub(t2, x1, x2); mpz_invert(t2, t2, modulus); mpz_mul(s, t1, t2); /* rx = s^2 - (x1 + x2) */ mpz_mul(t1, s, s); mpz_sub(t1, t1, x1); mpz_sub(t1, t1, x2); /* ry = s(x1 - rx) - y1 */ mpz_sub(t2, x1, t1); mpz_mul(t2, s, t2); mpz_sub(t2, t2, y1); /* We assign the destination parameters in the end to allow them to be identical to the inputs. */ mpz_mod(rx, t1, modulus); mpz_mod(ry, t2, modulus); return; }
int main (int argc, char **argv) { mpz_t base, exp, mod; mpz_t r1, r2, base2; mp_size_t base_size, exp_size, mod_size; unsigned long int exp2; int i; int reps = 100; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; tests_start (); rands = RANDS; mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (base); mpz_init (exp); mpz_init (mod); mpz_init (r1); mpz_init (r2); mpz_init (base2); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 18 + 2; do /* Loop until mathematically well-defined. */ { mpz_urandomb (bs, rands, size_range); base_size = mpz_get_ui (bs); mpz_rrandomb (base, rands, base_size); mpz_urandomb (bs, rands, 6L); exp_size = mpz_get_ui (bs); mpz_rrandomb (exp, rands, exp_size); exp2 = mpz_getlimbn (exp, (mp_size_t) 0); } while (mpz_cmp_ui (base, 0) == 0 && exp2 == 0); do { mpz_urandomb (bs, rands, size_range); mod_size = mpz_get_ui (bs); mpz_rrandomb (mod, rands, mod_size); } while (mpz_cmp_ui (mod, 0) == 0); mpz_urandomb (bs, rands, 2); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (base, base); /* printf ("%ld %ld\n", SIZ (base), SIZ (mod)); */ #if 0 putc ('\n', stderr); debug_mp (base, -16); debug_mp (mod, -16); #endif mpz_powm_ui (r1, base, exp2, mod); MPZ_CHECK_FORMAT (r1); mpz_set_ui (r2, 1); mpz_set (base2, base); mpz_mod (r2, r2, mod); /* needed when exp==0 and mod==1 */ while (exp2 != 0) { if (exp2 % 2 != 0) { mpz_mul (r2, r2, base2); mpz_mod (r2, r2, mod); } mpz_mul (base2, base2, base2); mpz_mod (base2, base2, mod); exp2 = exp2 / 2; } #if 0 debug_mp (r1, -16); debug_mp (r2, -16); #endif if (mpz_cmp (r1, r2) != 0) { fprintf (stderr, "\ntest %d: Incorrect results for operands:\n", i); debug_mp (base, -16); debug_mp (exp, -16); debug_mp (mod, -16); fprintf (stderr, "mpz_powm_ui result:\n"); debug_mp (r1, -16); fprintf (stderr, "reference result:\n"); debug_mp (r2, -16); abort (); } } mpz_clear (bs); mpz_clear (base); mpz_clear (exp); mpz_clear (mod); mpz_clear (r1); mpz_clear (r2); mpz_clear (base2); tests_end (); exit (0); }
int main (int argc, char **argv) { mpz_t dividend, divisor; mpz_t quotient, remainder; mpz_t quotient2, remainder2; mpz_t temp; mp_size_t dividend_size, divisor_size; int i; int reps = 1000; gmp_randstate_t rands; mpz_t bs; unsigned long bsi, size_range; tests_start (); special_tests(); gmp_randinit_default(rands); mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (dividend); mpz_init (divisor); mpz_init (quotient); mpz_init (remainder); mpz_init (quotient2); mpz_init (remainder2); mpz_init (temp); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 16 + 2; /* 0..131071 bit operands */ do { mpz_urandomb (bs, rands, size_range); divisor_size = mpz_get_ui (bs); mpz_rrandomb (divisor, rands, divisor_size); } while (mpz_sgn (divisor) == 0); mpz_urandomb (bs, rands, size_range); dividend_size = mpz_get_ui (bs) + divisor_size; mpz_rrandomb (dividend, rands, dividend_size); mpz_urandomb (bs, rands, 2); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (dividend, dividend); if ((bsi & 2) != 0) mpz_neg (divisor, divisor); /* printf ("%ld %ld\n", SIZ (dividend), SIZ (divisor)); */ mpz_tdiv_qr (quotient, remainder, dividend, divisor); mpz_tdiv_q (quotient2, dividend, divisor); mpz_tdiv_r (remainder2, dividend, divisor); /* First determine that the quotients and remainders computed with different functions are equal. */ if (mpz_cmp (quotient, quotient2) != 0) dump_abort (dividend, divisor); if (mpz_cmp (remainder, remainder2) != 0) dump_abort (dividend, divisor); /* Check if the sign of the quotient is correct. */ if (mpz_cmp_ui (quotient, 0) != 0) if ((mpz_cmp_ui (quotient, 0) < 0) != ((mpz_cmp_ui (dividend, 0) ^ mpz_cmp_ui (divisor, 0)) < 0)) dump_abort (dividend, divisor); /* Check if the remainder has the same sign as the dividend (quotient rounded towards 0). */ if (mpz_cmp_ui (remainder, 0) != 0) if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0)) dump_abort (dividend, divisor); mpz_mul (temp, quotient, divisor); mpz_add (temp, temp, remainder); if (mpz_cmp (temp, dividend) != 0) dump_abort (dividend, divisor); mpz_abs (temp, divisor); mpz_abs (remainder, remainder); if (mpz_cmp (remainder, temp) >= 0) dump_abort (dividend, divisor); } mpz_clear (bs); mpz_clear (dividend); mpz_clear (divisor); mpz_clear (quotient); mpz_clear (remainder); mpz_clear (quotient2); mpz_clear (remainder2); mpz_clear (temp); gmp_randclear(rands); tests_end (); exit (0); }
void spectral_test (mpf_t rop[], unsigned int T, mpz_t a, mpz_t m) { /* Knuth "Seminumerical Algorithms, Third Edition", section 3.3.4 (pp. 101-103). */ /* v[t] = min { sqrt (x[1]^2 + ... + x[t]^2) | x[1] + a*x[2] + ... + pow (a, t-1) * x[t] is congruent to 0 (mod m) } */ /* Variables. */ unsigned int ui_t; unsigned int ui_i, ui_j, ui_k, ui_l; mpf_t f_tmp1, f_tmp2; mpz_t tmp1, tmp2, tmp3; mpz_t U[GMP_SPECT_MAXT][GMP_SPECT_MAXT], V[GMP_SPECT_MAXT][GMP_SPECT_MAXT], X[GMP_SPECT_MAXT], Y[GMP_SPECT_MAXT], Z[GMP_SPECT_MAXT]; mpz_t h, hp, r, s, p, pp, q, u, v; /* GMP inits. */ mpf_init (f_tmp1); mpf_init (f_tmp2); for (ui_i = 0; ui_i < GMP_SPECT_MAXT; ui_i++) { for (ui_j = 0; ui_j < GMP_SPECT_MAXT; ui_j++) { mpz_init_set_ui (U[ui_i][ui_j], 0); mpz_init_set_ui (V[ui_i][ui_j], 0); } mpz_init_set_ui (X[ui_i], 0); mpz_init_set_ui (Y[ui_i], 0); mpz_init (Z[ui_i]); } mpz_init (tmp1); mpz_init (tmp2); mpz_init (tmp3); mpz_init (h); mpz_init (hp); mpz_init (r); mpz_init (s); mpz_init (p); mpz_init (pp); mpz_init (q); mpz_init (u); mpz_init (v); /* Implementation inits. */ if (T > GMP_SPECT_MAXT) T = GMP_SPECT_MAXT; /* FIXME: Lazy. */ /* S1 [Initialize.] */ ui_t = 2 - 1; /* NOTE: `t' in description == ui_t + 1 for easy indexing */ mpz_set (h, a); mpz_set (hp, m); mpz_set_ui (p, 1); mpz_set_ui (pp, 0); mpz_set (r, a); mpz_pow_ui (s, a, 2); mpz_add_ui (s, s, 1); /* s = 1 + a^2 */ /* S2 [Euclidean step.] */ while (1) { if (g_debug > DEBUG_1) { mpz_mul (tmp1, h, pp); mpz_mul (tmp2, hp, p); mpz_sub (tmp1, tmp1, tmp2); if (mpz_cmpabs (m, tmp1)) { printf ("***BUG***: h*pp - hp*p = "); mpz_out_str (stdout, 10, tmp1); printf ("\n"); } } if (g_debug > DEBUG_2) { printf ("hp = "); mpz_out_str (stdout, 10, hp); printf ("\nh = "); mpz_out_str (stdout, 10, h); printf ("\n"); fflush (stdout); } if (mpz_sgn (h)) mpz_tdiv_q (q, hp, h); /* q = floor(hp/h) */ else mpz_set_ui (q, 1); if (g_debug > DEBUG_2) { printf ("q = "); mpz_out_str (stdout, 10, q); printf ("\n"); fflush (stdout); } mpz_mul (tmp1, q, h); mpz_sub (u, hp, tmp1); /* u = hp - q*h */ mpz_mul (tmp1, q, p); mpz_sub (v, pp, tmp1); /* v = pp - q*p */ mpz_pow_ui (tmp1, u, 2); mpz_pow_ui (tmp2, v, 2); mpz_add (tmp1, tmp1, tmp2); if (mpz_cmp (tmp1, s) < 0) { mpz_set (s, tmp1); /* s = u^2 + v^2 */ mpz_set (hp, h); /* hp = h */ mpz_set (h, u); /* h = u */ mpz_set (pp, p); /* pp = p */ mpz_set (p, v); /* p = v */ } else break; } /* S3 [Compute v2.] */ mpz_sub (u, u, h); mpz_sub (v, v, p); mpz_pow_ui (tmp1, u, 2); mpz_pow_ui (tmp2, v, 2); mpz_add (tmp1, tmp1, tmp2); if (mpz_cmp (tmp1, s) < 0) { mpz_set (s, tmp1); /* s = u^2 + v^2 */ mpz_set (hp, u); mpz_set (pp, v); } mpf_set_z (f_tmp1, s); mpf_sqrt (rop[ui_t - 1], f_tmp1); /* S4 [Advance t.] */ mpz_neg (U[0][0], h); mpz_set (U[0][1], p); mpz_neg (U[1][0], hp); mpz_set (U[1][1], pp); mpz_set (V[0][0], pp); mpz_set (V[0][1], hp); mpz_neg (V[1][0], p); mpz_neg (V[1][1], h); if (mpz_cmp_ui (pp, 0) > 0) { mpz_neg (V[0][0], V[0][0]); mpz_neg (V[0][1], V[0][1]); mpz_neg (V[1][0], V[1][0]); mpz_neg (V[1][1], V[1][1]); } while (ui_t + 1 != T) /* S4 loop */ { ui_t++; mpz_mul (r, a, r); mpz_mod (r, r, m); /* Add new row and column to U and V. They are initialized with all elements set to zero, so clearing is not necessary. */ mpz_neg (U[ui_t][0], r); /* U: First col in new row. */ mpz_set_ui (U[ui_t][ui_t], 1); /* U: Last col in new row. */ mpz_set (V[ui_t][ui_t], m); /* V: Last col in new row. */ /* "Finally, for 1 <= i < t, set q = round (vi1 * r / m), vit = vi1*r - q*m, and Ut=Ut+q*Ui */ for (ui_i = 0; ui_i < ui_t; ui_i++) { mpz_mul (tmp1, V[ui_i][0], r); /* tmp1=vi1*r */ zdiv_round (q, tmp1, m); /* q=round(vi1*r/m) */ mpz_mul (tmp2, q, m); /* tmp2=q*m */ mpz_sub (V[ui_i][ui_t], tmp1, tmp2); for (ui_j = 0; ui_j <= ui_t; ui_j++) /* U[t] = U[t] + q*U[i] */ { mpz_mul (tmp1, q, U[ui_i][ui_j]); /* tmp=q*uij */ mpz_add (U[ui_t][ui_j], U[ui_t][ui_j], tmp1); /* utj = utj + q*uij */ } } /* s = min (s, zdot (U[t], U[t]) */ vz_dot (tmp1, U[ui_t], U[ui_t], ui_t + 1); if (mpz_cmp (tmp1, s) < 0) mpz_set (s, tmp1); ui_k = ui_t; ui_j = 0; /* WARNING: ui_j no longer a temp. */ /* S5 [Transform.] */ if (g_debug > DEBUG_2) printf ("(t, k, j, q1, q2, ...)\n"); do { if (g_debug > DEBUG_2) printf ("(%u, %u, %u", ui_t + 1, ui_k + 1, ui_j + 1); for (ui_i = 0; ui_i <= ui_t; ui_i++) { if (ui_i != ui_j) { vz_dot (tmp1, V[ui_i], V[ui_j], ui_t + 1); /* tmp1=dot(Vi,Vj). */ mpz_abs (tmp2, tmp1); mpz_mul_ui (tmp2, tmp2, 2); /* tmp2 = 2*abs(dot(Vi,Vj) */ vz_dot (tmp3, V[ui_j], V[ui_j], ui_t + 1); /* tmp3=dot(Vj,Vj). */ if (mpz_cmp (tmp2, tmp3) > 0) { zdiv_round (q, tmp1, tmp3); /* q=round(Vi.Vj/Vj.Vj) */ if (g_debug > DEBUG_2) { printf (", "); mpz_out_str (stdout, 10, q); } for (ui_l = 0; ui_l <= ui_t; ui_l++) { mpz_mul (tmp1, q, V[ui_j][ui_l]); mpz_sub (V[ui_i][ui_l], V[ui_i][ui_l], tmp1); /* Vi=Vi-q*Vj */ mpz_mul (tmp1, q, U[ui_i][ui_l]); mpz_add (U[ui_j][ui_l], U[ui_j][ui_l], tmp1); /* Uj=Uj+q*Ui */ } vz_dot (tmp1, U[ui_j], U[ui_j], ui_t + 1); /* tmp1=dot(Uj,Uj) */ if (mpz_cmp (tmp1, s) < 0) /* s = min(s,dot(Uj,Uj)) */ mpz_set (s, tmp1); ui_k = ui_j; } else if (g_debug > DEBUG_2) printf (", #"); /* 2|Vi.Vj| <= Vj.Vj */ } else if (g_debug > DEBUG_2) printf (", *"); /* i == j */ } if (g_debug > DEBUG_2) printf (")\n"); /* S6 [Advance j.] */ if (ui_j == ui_t) ui_j = 0; else ui_j++; } while (ui_j != ui_k); /* S5 */ /* From Knuth p. 104: "The exhaustive search in steps S8-S10 reduces the value of s only rarely." */ #ifdef DO_SEARCH /* S7 [Prepare for search.] */ /* Find minimum in (x[1], ..., x[t]) satisfying condition x[k]^2 <= f(y[1], ...,y[t]) * dot(V[k],V[k]) */ ui_k = ui_t; if (g_debug > DEBUG_2) { printf ("searching..."); /*for (f = 0; f < ui_t*/ fflush (stdout); } /* Z[i] = floor (sqrt (floor (dot(V[i],V[i]) * s / m^2))); */ mpz_pow_ui (tmp1, m, 2); mpf_set_z (f_tmp1, tmp1); mpf_set_z (f_tmp2, s); mpf_div (f_tmp1, f_tmp2, f_tmp1); /* f_tmp1 = s/m^2 */ for (ui_i = 0; ui_i <= ui_t; ui_i++) { vz_dot (tmp1, V[ui_i], V[ui_i], ui_t + 1); mpf_set_z (f_tmp2, tmp1); mpf_mul (f_tmp2, f_tmp2, f_tmp1); f_floor (f_tmp2, f_tmp2); mpf_sqrt (f_tmp2, f_tmp2); mpz_set_f (Z[ui_i], f_tmp2); } /* S8 [Advance X[k].] */ do { if (g_debug > DEBUG_2) { printf ("X[%u] = ", ui_k); mpz_out_str (stdout, 10, X[ui_k]); printf ("\tZ[%u] = ", ui_k); mpz_out_str (stdout, 10, Z[ui_k]); printf ("\n"); fflush (stdout); } if (mpz_cmp (X[ui_k], Z[ui_k])) { mpz_add_ui (X[ui_k], X[ui_k], 1); for (ui_i = 0; ui_i <= ui_t; ui_i++) mpz_add (Y[ui_i], Y[ui_i], U[ui_k][ui_i]); /* S9 [Advance k.] */ while (++ui_k <= ui_t) { mpz_neg (X[ui_k], Z[ui_k]); mpz_mul_ui (tmp1, Z[ui_k], 2); for (ui_i = 0; ui_i <= ui_t; ui_i++) { mpz_mul (tmp2, tmp1, U[ui_k][ui_i]); mpz_sub (Y[ui_i], Y[ui_i], tmp2); } } vz_dot (tmp1, Y, Y, ui_t + 1); if (mpz_cmp (tmp1, s) < 0) mpz_set (s, tmp1); } } while (--ui_k); #endif /* DO_SEARCH */ mpf_set_z (f_tmp1, s); mpf_sqrt (rop[ui_t - 1], f_tmp1); #ifdef DO_SEARCH if (g_debug > DEBUG_2) printf ("done.\n"); #endif /* DO_SEARCH */ } /* S4 loop */ /* Clear GMP variables. */ mpf_clear (f_tmp1); mpf_clear (f_tmp2); for (ui_i = 0; ui_i < GMP_SPECT_MAXT; ui_i++) { for (ui_j = 0; ui_j < GMP_SPECT_MAXT; ui_j++) { mpz_clear (U[ui_i][ui_j]); mpz_clear (V[ui_i][ui_j]); } mpz_clear (X[ui_i]); mpz_clear (Y[ui_i]); mpz_clear (Z[ui_i]); } mpz_clear (tmp1); mpz_clear (tmp2); mpz_clear (tmp3); mpz_clear (h); mpz_clear (hp); mpz_clear (r); mpz_clear (s); mpz_clear (p); mpz_clear (pp); mpz_clear (q); mpz_clear (u); mpz_clear (v); return; }
int main (int argc, char **argv) { mpz_t op1, op2; mpz_t prod, quot; mp_size_t size; int i; int reps = 20000; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; tests_start (); rands = RANDS; mp_trace_base = -16; mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (op1); mpz_init (op2); mpz_init (prod); mpz_init (quot); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 10 + 2; /* 0..2047 bit operands */ mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (op1, rands, size); do { mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (op2, rands, size); } while (mpz_sgn (op2) == 0); mpz_urandomb (bs, rands, 2); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (op1, op1); if ((bsi & 2) != 0) mpz_neg (op2, op2); mpz_mul (prod, op1, op2); mpz_divexact (quot, prod, op2); MPZ_CHECK_FORMAT (quot); if (mpz_cmp (quot, op1) != 0) { printf ("Wrong results:\n"); mpz_trace (" got ", quot); mpz_trace (" want ", op1); mpz_trace (" dividend", prod); mpz_trace (" divisor ", op2); abort (); } } mpz_clear (bs); mpz_clear (op1); mpz_clear (op2); mpz_clear (prod); mpz_clear (quot); tests_end (); exit (0); }
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); }
// set op to (op1 * op2) mod d, using tmp for the calculation inline static void mpz_mulm( mpz_t op, const mpz_t op1, const mpz_t op2, const mpz_t d, mpz_t tmp) { mpz_mul(tmp, op1, op2); mpz_mod(op, tmp, d); }
/* NOTE: Assumes mpz_t's are initted in ku and kp */ void generate_keys(private_key* ku, public_key* kp) { char buf[BUFFER_SIZE]; int i; mpz_t phi; mpz_init(phi); mpz_t tmp1; mpz_init(tmp1); mpz_t tmp2; mpz_init(tmp2); srand(time(NULL)); /* Insetead of selecting e st. gcd(phi, e) = 1; 1 < e < phi, lets choose e * first then pick p,q st. gcd(e, p-1) = gcd(e, q-1) = 1 */ // We'll set e globally. I've seen suggestions to use primes like 3, 17 or // 65537, as they make coming calculations faster. Lets use 3. mpz_set_ui(ku->e, 3); /* Select p and q */ /* Start with p */ // Set the bits of tmp randomly for(i = 0; i < BUFFER_SIZE; i++) buf[i] = rand() % 0xFF; // Set the top two bits to 1 to ensure int(tmp) is relatively large buf[0] |= 0xC0; // Set the bottom bit to 1 to ensure int(tmp) is odd (better for finding primes) buf[BUFFER_SIZE - 1] |= 0x01; // Interpret this char buffer as an int mpz_import(tmp1, BUFFER_SIZE, 1, sizeof(buf[0]), 0, 0, buf); // Pick the next prime starting from that random number mpz_nextprime(ku->p, tmp1); /* Make sure this is a good choice*/ mpz_mod(tmp2, ku->p, ku->e); /* If p mod e == 1, gcd(phi, e) != 1 */ while(!mpz_cmp_ui(tmp2, 1)) { mpz_nextprime(ku->p, ku->p); /* so choose the next prime */ mpz_mod(tmp2, ku->p, ku->e); } /* Now select q */ do { for(i = 0; i < BUFFER_SIZE; i++) buf[i] = rand() % 0xFF; // Set the top two bits to 1 to ensure int(tmp) is relatively large buf[0] |= 0xC0; // Set the bottom bit to 1 to ensure int(tmp) is odd buf[BUFFER_SIZE - 1] |= 0x01; // Interpret this char buffer as an int mpz_import(tmp1, (BUFFER_SIZE), 1, sizeof(buf[0]), 0, 0, buf); // Pick the next prime starting from that random number mpz_nextprime(ku->q, tmp1); mpz_mod(tmp2, ku->q, ku->e); while(!mpz_cmp_ui(tmp2, 1)) { mpz_nextprime(ku->q, ku->q); mpz_mod(tmp2, ku->q, ku->e); } } while(mpz_cmp(ku->p, ku->q) == 0); /* If we have identical primes (unlikely), try again */ /* Calculate n = p x q */ mpz_mul(ku->n, ku->p, ku->q); /* Compute phi(n) = (p-1)(q-1) */ mpz_sub_ui(tmp1, ku->p, 1); mpz_sub_ui(tmp2, ku->q, 1); mpz_mul(phi, tmp1, tmp2); /* Calculate d (multiplicative inverse of e mod phi) */ if(mpz_invert(ku->d, ku->e, phi) == 0) { mpz_gcd(tmp1, ku->e, phi); printf("gcd(e, phi) = [%s]\n", mpz_get_str(NULL, 16, tmp1)); printf("Invert failed\n"); } /* Set public key */ mpz_set(kp->e, ku->e); mpz_set(kp->n, ku->n); return; }
/* Output: bytes_M. Buffer length is SHA512_DIGEST_LENGTH */ void srp_user_process_challenge(struct SRPUser *usr, const unsigned char *bytes_s, size_t len_s, const unsigned char *bytes_B, size_t len_B, unsigned char **bytes_M, size_t *len_M) { mpz_t B; mpz_init(B); mpz_from_bin(bytes_B, len_B, B); mpz_t u; mpz_init(u); mpz_t x; mpz_init(x); mpz_t k; mpz_init(k); mpz_t v; mpz_init(v); mpz_t tmp1; mpz_init(tmp1); mpz_t tmp2; mpz_init(tmp2); mpz_t tmp3; mpz_init(tmp3); mpz_t tmp4; mpz_init(tmp4); // clang-format on *len_M = 0; *bytes_M = 0; if (!H_nn(u, usr->hash_alg, usr->ng->N, usr->A, B)) goto cleanup_and_exit; srp_dbg_num(u, "Client calculated u: "); if (!calculate_x(x, usr->hash_alg, bytes_s, len_s, usr->username_verifier, usr->password, usr->password_len)) goto cleanup_and_exit; srp_dbg_num(x, "Client calculated x: "); if (!H_nn(k, usr->hash_alg, usr->ng->N, usr->ng->N, usr->ng->g)) goto cleanup_and_exit; /* SRP-6a safety check */ if (mpz_sgn(B) != 0 && mpz_sgn(u) != 0) { mpz_powm(v, usr->ng->g, x, usr->ng->N); srp_dbg_num(v, "Client calculated v: "); // clang-format off /* S = (B - k*(g^x)) ^ (a + ux) */ mpz_mul(tmp1, u, x); mpz_add(tmp2, usr->a, tmp1); /* tmp2 = (a + ux) */ mpz_powm(tmp1, usr->ng->g, x, usr->ng->N); /* tmp1 = g^x */ mpz_mulm(tmp3, k, tmp1, usr->ng->N, tmp4); /* tmp3 = k*(g^x) */ mpz_subm(tmp1, B, tmp3, usr->ng->N, tmp4); /* tmp1 = (B - K*(g^x)) */ mpz_powm(usr->S, tmp1, tmp2, usr->ng->N); // clang-format on if (!hash_num(usr->hash_alg, usr->S, usr->session_key)) goto cleanup_and_exit; if (!calculate_M(usr->hash_alg, usr->ng, usr->M, usr->username, bytes_s, len_s, usr->A, B, usr->session_key)) goto cleanup_and_exit; if (!calculate_H_AMK(usr->hash_alg, usr->H_AMK, usr->A, usr->M, usr->session_key)) goto cleanup_and_exit; *bytes_M = usr->M; if (len_M) *len_M = hash_length(usr->hash_alg); } else { *bytes_M = NULL; if (len_M) *len_M = 0; } cleanup_and_exit: mpz_clear(B); mpz_clear(u); mpz_clear(x); mpz_clear(k); mpz_clear(v); mpz_clear(tmp1); mpz_clear(tmp2); mpz_clear(tmp3); mpz_clear(tmp4); }
static int mpfr_rem1 (mpfr_ptr rem, long *quo, mpfr_rnd_t rnd_q, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd) { mpfr_exp_t ex, ey; int compare, inex, q_is_odd, sign, signx = MPFR_SIGN (x); mpz_t mx, my, r; int tiny = 0; MPFR_ASSERTD (rnd_q == MPFR_RNDN || rnd_q == MPFR_RNDZ); if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x) || MPFR_IS_SINGULAR (y))) { if (MPFR_IS_NAN (x) || MPFR_IS_NAN (y) || MPFR_IS_INF (x) || MPFR_IS_ZERO (y)) { /* for remquo, quo is undefined */ MPFR_SET_NAN (rem); MPFR_RET_NAN; } else /* either y is Inf and x is 0 or non-special, or x is 0 and y is non-special, in both cases the quotient is zero. */ { if (quo) *quo = 0; return mpfr_set (rem, x, rnd); } } /* now neither x nor y is NaN, Inf or zero */ mpz_init (mx); mpz_init (my); mpz_init (r); ex = mpfr_get_z_2exp (mx, x); /* x = mx*2^ex */ ey = mpfr_get_z_2exp (my, y); /* y = my*2^ey */ /* to get rid of sign problems, we compute it separately: quo(-x,-y) = quo(x,y), rem(-x,-y) = -rem(x,y) quo(-x,y) = -quo(x,y), rem(-x,y) = -rem(x,y) thus quo = sign(x/y)*quo(|x|,|y|), rem = sign(x)*rem(|x|,|y|) */ sign = (signx == MPFR_SIGN (y)) ? 1 : -1; mpz_abs (mx, mx); mpz_abs (my, my); q_is_odd = 0; /* divide my by 2^k if possible to make operations mod my easier */ { unsigned long k = mpz_scan1 (my, 0); ey += k; mpz_fdiv_q_2exp (my, my, k); } if (ex <= ey) { /* q = x/y = mx/(my*2^(ey-ex)) */ /* First detect cases where q=0, to avoid creating a huge number my*2^(ey-ex): if sx = mpz_sizeinbase (mx, 2) and sy = mpz_sizeinbase (my, 2), we have x < 2^(ex + sx) and y >= 2^(ey + sy - 1), thus if ex + sx <= ey + sy - 1 the quotient is 0 */ if (ex + (mpfr_exp_t) mpz_sizeinbase (mx, 2) < ey + (mpfr_exp_t) mpz_sizeinbase (my, 2)) { tiny = 1; mpz_set (r, mx); mpz_set_ui (mx, 0); } else { mpz_mul_2exp (my, my, ey - ex); /* divide mx by my*2^(ey-ex) */ /* since mx > 0 and my > 0, we can use mpz_tdiv_qr in all cases */ mpz_tdiv_qr (mx, r, mx, my); /* 0 <= |r| <= |my|, r has the same sign as mx */ } if (rnd_q == MPFR_RNDN) q_is_odd = mpz_tstbit (mx, 0); if (quo) /* mx is the quotient */ { mpz_tdiv_r_2exp (mx, mx, WANTED_BITS); *quo = mpz_get_si (mx); } } else /* ex > ey */ { if (quo) /* remquo case */ /* for remquo, to get the low WANTED_BITS more bits of the quotient, we first compute R = X mod Y*2^WANTED_BITS, where X and Y are defined below. Then the low WANTED_BITS of the quotient are floor(R/Y). */ mpz_mul_2exp (my, my, WANTED_BITS); /* 2^WANTED_BITS*Y */ else if (rnd_q == MPFR_RNDN) /* remainder case */ /* Let X = mx*2^(ex-ey) and Y = my. Then both X and Y are integers. Assume X = R mod Y, then x = X*2^ey = R*2^ey mod (Y*2^ey=y). To be able to perform the rounding, we need the least significant bit of the quotient, i.e., one more bit in the remainder, which is obtained by dividing by 2Y. */ mpz_mul_2exp (my, my, 1); /* 2Y */ mpz_set_ui (r, 2); mpz_powm_ui (r, r, ex - ey, my); /* 2^(ex-ey) mod my */ mpz_mul (r, r, mx); mpz_mod (r, r, my); if (quo) /* now 0 <= r < 2^WANTED_BITS*Y */ { mpz_fdiv_q_2exp (my, my, WANTED_BITS); /* back to Y */ mpz_tdiv_qr (mx, r, r, my); /* oldr = mx*my + newr */ *quo = mpz_get_si (mx); q_is_odd = *quo & 1; } else if (rnd_q == MPFR_RNDN) /* now 0 <= r < 2Y in the remainder case */ { mpz_fdiv_q_2exp (my, my, 1); /* back to Y */ /* least significant bit of q */ q_is_odd = mpz_cmpabs (r, my) >= 0; if (q_is_odd) mpz_sub (r, r, my); } /* now 0 <= |r| < |my|, and if needed, q_is_odd is the least significant bit of q */ } if (mpz_cmp_ui (r, 0) == 0) { inex = mpfr_set_ui (rem, 0, MPFR_RNDN); /* take into account sign of x */ if (signx < 0) mpfr_neg (rem, rem, MPFR_RNDN); } else { if (rnd_q == MPFR_RNDN) { /* FIXME: the comparison 2*r < my could be done more efficiently at the mpn level */ mpz_mul_2exp (r, r, 1); /* if tiny=1, we should compare r with my*2^(ey-ex) */ if (tiny) { if (ex + (mpfr_exp_t) mpz_sizeinbase (r, 2) < ey + (mpfr_exp_t) mpz_sizeinbase (my, 2)) compare = 0; /* r*2^ex < my*2^ey */ else { mpz_mul_2exp (my, my, ey - ex); compare = mpz_cmpabs (r, my); } } else compare = mpz_cmpabs (r, my); mpz_fdiv_q_2exp (r, r, 1); compare = ((compare > 0) || ((rnd_q == MPFR_RNDN) && (compare == 0) && q_is_odd)); /* if compare != 0, we need to subtract my to r, and add 1 to quo */ if (compare) { mpz_sub (r, r, my); if (quo && (rnd_q == MPFR_RNDN)) *quo += 1; } } /* take into account sign of x */ if (signx < 0) mpz_neg (r, r); inex = mpfr_set_z_2exp (rem, r, ex > ey ? ey : ex, rnd); } if (quo) *quo *= sign; mpz_clear (mx); mpz_clear (my); mpz_clear (r); return inex; }
// Algorithm 13.2 [PDF page 17](http://cr.yp.to/lineartime/dcba-20040404.pdf) // // See [appendcb test](test-appendcb.html) for basic usage. void append_cb(mpz_array *out, const mpz_t a, const mpz_t b) { mpz_t r, g, h, c, c0, x, y, d, b1, b2, a1; unsigned long long n; /* gmp_printf("enter append_cb(%Zd, %Zd)\n", a, b); */ // **Step 1** // // If `b == 1` and `a == 1` add `a` to the array. If `b == 1` return. // This is the break condition of the recursive function. if (mpz_cmp_ui(b, 1) == 0) { if (mpz_cmp_ui(a, 1) != 0) { array_add(out, a); } return; } mpz_init(r); mpz_init(g); mpz_init(a1); // **Step 2** // // Store ppi in `a1` and ppo in `r`. Use `a1` and not `a` to keep the input `const` // and handle the case that one parameter is used twice. ppi_ppo(a1, r, a, b); // **Step 3** // // If `r` (ppo) is **not** one add it to the array. if (mpz_cmp_ui(r, 1) != 0) { array_add(out, r); } mpz_init(h); mpz_init(c); // **Step 4** // // Caluclate the gcd, ppg and pple. gcd_ppg_pple(g, h, c, a1, b); // **Step 5** // // Store pple in `c0` and `x`. mpz_init_set(c0, c); mpz_init_set(x, c0); // **Step 6** // // Set `n` to one. n = 1; mpz_init(b1); mpz_init(b2); mpz_init(d); mpz_init(y); // Start while loop to be able to return to step 7. while(1) { // **Step 7** // // Compute (g, h, c) ← (gcd,ppg,pple)(h,g^2) mpz_mul(b1, g, g); mpz_set(b2, h); gcd_ppg_pple(g, h, c, b2, b1); // **Step 8** // // Compute d ← gcd(c, b) mpz_gcd(d, c, b); // **Step 9** // // Set x ← xd mpz_mul(x, x, d); // **Sep 10** // // Compute y ← d^2^ n−1. mpz_set(y, d); two_power(y, n - 1); // **Sep 11** // // Recursively apply (c/y,d). mpz_fdiv_q(b1, c, y); /* gmp_printf("rec call append_cb(%Zd, %Zd)\n", b1, d); */ append_cb(out, b1, d); // **Sep 12** // // If h is not 1: Set n ← n+1. Return to Step 7. if (mpz_cmp_ui(h, 1) == 0) break; n = n + 1; } // **Step 13** // // Recursively apply (b/x, c0). mpz_fdiv_q(b1, b, x); append_cb(out, b1, c0); // Free the memory. mpz_clear(r); mpz_clear(g); mpz_clear(h); mpz_clear(c); mpz_clear(c0); mpz_clear(x); mpz_clear(y); mpz_clear(d); mpz_clear(b1); mpz_clear(b2); mpz_clear(a1); }
static void zp_mul(element_ptr n, element_ptr a, element_ptr b) { mpz_mul(n->data, a->data, b->data); mpz_mod(n->data, n->data, n->field->order); }
// The result is stored in the parameter `mpz_t rot`. // This parameter has to be **initialized** on invocation. // The function operates on a single (input & output) integer. // // Algorithm 10.1 [PDF page 13](http://cr.yp.to/lineartime/dcba-20040404.pdf) // // See [twopower test](test-twopower.html) for basic usage. void two_power(mpz_t rot, unsigned long long n) { while(n > 0) { mpz_mul(rot, rot, rot); n--; } }
int main(int argc, char* argv[]) { int i; u8 ecount_buf[0x10], iv[0x10]; size_t countp; int num; if(argc < 4) { printf("usage: %s input.elf output.self keytype keysuffix\n", argv[0]); return -1; } Elf64_Ehdr input_elf_header; FILE *input_elf_file = fopen(argv[1], "rb"); fseek(input_elf_file, 0, SEEK_END); int nlen = ftell(input_elf_file); fseek(input_elf_file, 0, SEEK_SET); input_elf_data = (u8*)malloc(nlen); fread(input_elf_data, 1, nlen, input_elf_file); fclose(input_elf_file); memcpy(&input_elf_header, input_elf_data, sizeof(input_elf_header)); FILE *output_self_file = fopen(argv[2], "wb"); printf("ELF header size @ %x\n", get_u16(&(input_elf_header.e_ehsize)) ); printf("%d program headers @ %64llX\n", get_u16(&(input_elf_header.e_phnum)), get_u64(&(input_elf_header.e_phoff))); printf("%d section headers @ %64llX\n", get_u16(&(input_elf_header.e_shnum)), get_u64(&(input_elf_header.e_shoff))); Self_Shdr output_self_header; memset(&output_self_header, 0, sizeof(output_self_header)); Self_Ehdr output_extended_self_header; memset(&output_extended_self_header, 0, sizeof(output_extended_self_header)); Self_Ihdr output_self_info_header; memset(&output_self_info_header, 0, sizeof(output_self_info_header)); set_u32(&(output_self_header.s_magic), 0x53434500); set_u32(&(output_self_header.s_hdrversion), 2); set_u16(&(output_self_header.s_flags), 1); set_u16(&(output_self_header.s_hdrtype), 1); // header size and file size aren't known yet set_u64(&(output_extended_self_header.e_magic), 3); set_u64(&(output_extended_self_header.e_ihoff), sizeof(Self_Shdr)+sizeof(Self_Ehdr)); set_u64(&(output_extended_self_header.e_ehoff), sizeof(Self_Shdr)+sizeof(Self_Ehdr)+sizeof(Self_Ihdr)); set_u64(&(output_extended_self_header.e_phoff), sizeof(Self_Shdr)+sizeof(Self_Ehdr)+sizeof(Self_Ihdr)+get_u64(&(input_elf_header.e_phoff))); // section header offset unknown set_u64(&(output_self_info_header.i_authid), 0x1070000500000001LL); set_u32(&(output_self_info_header.i_magic), 0x01000002); set_u32(&(output_self_info_header.i_apptype), 4); set_u64(&(output_self_info_header.i_version), 0x0003000000000000LL); // set static data int phnum = get_u16(&(input_elf_header.e_phnum)); u32 phsize = (sizeof(Elf64_Phdr)*get_u16(&(input_elf_header.e_phnum))); Self_SDKversion sdkversion; Self_Cflags cflags; memcpy(&sdkversion, sdkversion_static, sizeof(Self_SDKversion)); memcpy(&cflags, cflags_static, sizeof(Self_Cflags)); int running_size = (sizeof(output_self_header)+sizeof(output_extended_self_header)+sizeof(output_self_info_header)+sizeof(input_elf_header)+phsize+0xF)&0xFFFFFFF0; set_u64(&(output_extended_self_header.e_pmoff), running_size); running_size += phnum*sizeof(Self_PMhdr); set_u64(&(output_extended_self_header.e_svoff), running_size); running_size += sizeof(Self_SDKversion); set_u64(&(output_extended_self_header.e_cfoff), running_size); running_size += sizeof(Self_Cflags); set_u64(&(output_extended_self_header.e_cfsize), sizeof(Self_Cflags)); set_u32(&(output_self_header.s_esize), running_size - sizeof(output_self_header)); printf("running size is %X\n", running_size); int maxsection = 6; running_size += sizeof(metadata_crypt_header)+sizeof(segment_certification_header)+maxsection*(sizeof(segment_certification_segment)+sizeof(segment_certification_crypt_encrypted))+sizeof(segment_certification_sign)+sizeof(nubpadding_static); printf("running size is %X\n", running_size); set_u64(&(output_self_header.s_shsize), running_size); // init randomness gmp_randstate_t r_state; gmp_randinit_default(r_state); gmp_randseed_ui(r_state, time(NULL)); // loop through the sections segment_certification_header segment_header; memset(&segment_header, 0, sizeof(segment_header)); Self_Section first_section; Self_Section* section_ptr = &first_section; set_u64(&(segment_header.signature_offset), running_size-sizeof(segment_certification_sign)); set_u32(&(segment_header.unknown1), 1); set_u32(&(segment_header.segment_count), phnum); set_u32(&(segment_header.crypt_len), (phnum*sizeof(segment_certification_crypt_encrypted))/0x10); Elf64_Phdr* elf_segment = (Elf64_Phdr*)(&input_elf_data[get_u64(&(input_elf_header.e_phoff))]); for(i=0;i<phnum;i++) { memset(section_ptr, 0, sizeof(Self_Section)); //set_u64(&(section_ptr->enc_segment.segment_offset), get_u64(&(elf_segment->p_vaddr))); set_u64(&(section_ptr->enc_segment.segment_offset), running_size); set_u64(&(section_ptr->enc_segment.segment_size), get_u64(&(elf_segment->p_filesz))); set_u32(&(section_ptr->enc_segment.segment_crypt_flag), 2); set_u32(&(section_ptr->enc_segment.segment_sha1_index), i*8); set_u32(&(section_ptr->enc_segment.segment_erk_index), i*8+6); set_u32(&(section_ptr->enc_segment.segment_riv_index), i*8+7); set_u32(&(section_ptr->enc_segment.segment_number), i); set_u32(&(section_ptr->enc_segment.unknown2), 2); set_u32(&(section_ptr->enc_segment.unknown3), 3); set_u32(&(section_ptr->enc_segment.unknown4), 2); set_u64(&(section_ptr->pmhdr.pm_offset), running_size); set_u64(&(section_ptr->pmhdr.pm_size), get_u64(&(elf_segment->p_filesz))); set_u32(&(section_ptr->pmhdr.pm_compressed), 1); set_u32(&(section_ptr->pmhdr.pm_encrypted), 1); mpz_t riv, erk, hmac; mpz_init(riv); mpz_init(erk); mpz_init(hmac); mpz_urandomb(erk, r_state, 128); mpz_urandomb(riv, r_state, 128); mpz_urandomb(hmac, r_state, 512); mpz_export(section_ptr->crypt_segment.erk, &countp, 1, 0x10, 1, 0, erk); mpz_export(section_ptr->crypt_segment.riv, &countp, 1, 0x10, 1, 0, riv); mpz_export(section_ptr->crypt_segment.hmac, &countp, 1, 0x40, 1, 0, hmac); section_ptr->rlen = get_u64(&(elf_segment->p_filesz)); section_ptr->len = ((section_ptr->rlen)+0xF)&0xFFFFFFF0; section_ptr->data = (u8*)malloc(section_ptr->len); u32 in_data_offset = get_u64(&(elf_segment->p_offset)); // + get_u16(&(input_elf_header.e_ehsize)) + (sizeof(Elf64_Phdr)*get_u16(&(input_elf_header.e_phnum))); u8* in_data = &input_elf_data[in_data_offset]; printf("processing segment %d with len %x offset %x\n", i, section_ptr->len, in_data_offset); //hexdump((u8*)elf_segment, sizeof(Elf64_Phdr)); /*SHA_CTX c; SHA1_ghetto_init(&c, section_ptr->crypt_segment.hmac); SHA1_Update(&c, in_data, section_ptr->rlen); SHA1_ghetto_final(section_ptr->crypt_segment.sha1, &c, section_ptr->crypt_segment.hmac);*/ sha1_hmac(section_ptr->crypt_segment.hmac, in_data, section_ptr->rlen, section_ptr->crypt_segment.sha1); memset(ecount_buf, 0, 16); num=0; AES_set_encrypt_key(section_ptr->crypt_segment.erk, 128, &aes_key); memcpy(iv, section_ptr->crypt_segment.riv, 16); #ifdef NO_CRYPT memcpy(section_ptr->data, in_data, section_ptr->len); #else //AES_ctr128_encrypt(in_data, section_ptr->data, section_ptr->len, &aes_key, iv, ecount_buf, &num); aes128ctr((u8*)&aes_key, iv, in_data, section_ptr->len, section_ptr->data); #endif running_size += section_ptr->len; // next if(i != phnum-1) { section_ptr->next_section = malloc(sizeof(Self_Section)); } elf_segment += 1; // 1 is sizeof(Elf64_Phdr) section_ptr = section_ptr->next_section; } printf("segment processing done\n"); // section table offset set_u64(&(output_extended_self_header.e_shoff), running_size); // lay out the metadata u8 metadata[0x2000]; memset(metadata, 0, 0x2000); u32 metadata_len = 0; memcpy(&metadata[metadata_len], &output_self_header, sizeof(output_self_header)); metadata_len += sizeof(output_self_header); memcpy(&metadata[metadata_len], &output_extended_self_header, sizeof(output_extended_self_header)); metadata_len += sizeof(output_extended_self_header); memcpy(&metadata[metadata_len], &output_self_info_header, sizeof(output_self_info_header)); metadata_len += sizeof(output_self_info_header); memcpy(&metadata[metadata_len], &input_elf_header, sizeof(input_elf_header)); metadata_len += sizeof(input_elf_header); memcpy(&metadata[metadata_len], &input_elf_data[get_u64(&(input_elf_header.e_phoff))], phsize); metadata_len += phsize; metadata_len = (metadata_len+0xF)&0xFFFFFFF0; section_ptr = &first_section; while(section_ptr != NULL) { memcpy(&metadata[metadata_len], &(section_ptr->pmhdr), sizeof(section_ptr->pmhdr)); metadata_len += sizeof(section_ptr->pmhdr); section_ptr = section_ptr->next_section; } memcpy(&metadata[metadata_len], &sdkversion, sizeof(sdkversion)); metadata_len += sizeof(sdkversion); memcpy(&metadata[metadata_len], &cflags, sizeof(cflags)); metadata_len += sizeof(cflags); printf("top half of metadata ready\n"); // generate metadata encryption keys mpz_t bigriv, bigerk; mpz_init(bigriv); mpz_init(bigerk); mpz_urandomb(bigerk, r_state, 128); mpz_urandomb(bigriv, r_state, 128); metadata_crypt_header md_header; mpz_export(md_header.erk, &countp, 1, 0x10, 1, 0, bigerk); mpz_export(md_header.riv, &countp, 1, 0x10, 1, 0, bigriv); memcpy(&metadata[metadata_len], &md_header, sizeof(md_header)); metadata_len += sizeof(md_header); memcpy(&metadata[metadata_len], &segment_header, sizeof(segment_header)); metadata_len += sizeof(segment_header); // copy section data int csection; csection = 0; section_ptr = &first_section; while(section_ptr != NULL) { memcpy(&metadata[metadata_len], &(section_ptr->enc_segment), sizeof(section_ptr->enc_segment)); metadata_len += sizeof(section_ptr->enc_segment); section_ptr = section_ptr->next_section; if((++csection) == maxsection) break; } csection = 0; section_ptr = &first_section; while(section_ptr != NULL) { memcpy(&metadata[metadata_len], &(section_ptr->crypt_segment), sizeof(section_ptr->crypt_segment)); metadata_len += sizeof(section_ptr->crypt_segment); section_ptr = section_ptr->next_section; if((++csection) == maxsection) break; } // nubpadding time memcpy(&metadata[metadata_len], nubpadding_static, sizeof(nubpadding_static)); metadata_len += sizeof(nubpadding_static); // sign shit u8 digest[0x14]; sha1(metadata, metadata_len, digest); printf("metadata len is %X\n", metadata_len); //hexdump(metadata, metadata_len); //hexdump_nl(digest, 0x14); segment_certification_sign all_signed; memset(&all_signed, 0, sizeof(all_signed)); #ifdef GEOHOT_SIGN mpz_t n,k,da,kinv,r,cs,z; mpz_init(n); mpz_init(k); mpz_init(da); mpz_init(r); mpz_init(cs); mpz_init(z); mpz_init(kinv); mpz_import(r, 0x14, 1, 1, 0, 0, appold_R); mpz_import(n, 0x14, 1, 1, 0, 0, appold_n); mpz_import(k, 0x14, 1, 1, 0, 0, appold_K); mpz_import(da, 0x14, 1, 1, 0, 0, appold_Da); mpz_invert(kinv, k, n); mpz_import(z, 0x14, 1, 1, 0, 0, digest); mpz_mul(cs, r, da); mpz_mod(cs, cs, n); mpz_add(cs, cs, z); mpz_mod(cs, cs, n); mpz_mul(cs, cs, kinv); mpz_mod(cs, cs, n); mpz_export(all_signed.R, &countp, 1, 0x14, 1, 0, r); mpz_export(all_signed.S, &countp, 1, 0x14, 1, 0, cs); #else get_keys(argv[3], argv[4]); //ecdsa_set_curve(appnew_ctype); //ecdsa_set_pub(appnew_pub); //ecdsa_set_priv(appnew_priv); //ecdsa_sign(digest, all_signed.R, all_signed.S); #endif memcpy(&metadata[metadata_len], &all_signed, sizeof(all_signed)); metadata_len += sizeof(all_signed); // encrypt metadata int metadata_offset = get_u32(&(output_self_header.s_esize)) + sizeof(Self_Shdr); #ifndef NO_CRYPT /*memset(ecount_buf, 0, 16); num=0; AES_set_encrypt_key(&metadata[metadata_offset], 128, &aes_key); memcpy(iv, &metadata[metadata_offset+0x20], 16); //AES_ctr128_encrypt(&metadata[0x40+metadata_offset], &metadata[0x40+metadata_offset], metadata_len-metadata_offset-0x40, &aes_key, iv, ecount_buf, &num); aes128ctr(&metadata[0x20+metadata_offset], &metadata[0x40+metadata_offset], &metadata[0x60+metadata_offset], metadata_len-metadata_offset-0x60, &metadata[0x60+metadata_offset]); printf("encrypted metadata\n"); //AES_set_encrypt_key(appold_erk, 256, &aes_key); //memcpy(iv, appold_riv, 16); AES_set_encrypt_key(appnew_erk, 256, &aes_key); memcpy(iv, appnew_riv, 16); //AES_cbc_encrypt(&metadata[metadata_offset], &metadata[metadata_offset], 0x40, &aes_key, iv, AES_ENCRYPT); aes256cbc_enc(appnew_erk, appnew_riv, &metadata[metadata_offset], 0x40, &metadata[metadata_offset]); printf("encrypted keys\n");*/ //k.key = appnew_erk; //k.iv = appnew_riv; sce_encrypt_header(metadata, &ks); #endif // write the output self fwrite(metadata, 1, metadata_len, output_self_file); csection = 0; section_ptr = &first_section; while(section_ptr != 0) { printf("writing section with size %X\n", section_ptr->len); fwrite(section_ptr->data, 1, section_ptr->len, output_self_file); section_ptr = section_ptr->next_section; if((++csection) == maxsection) break; } fwrite(&input_elf_data[get_u64(&(input_elf_header.e_shoff))], sizeof(Elf64_Shdr), get_u16(&(input_elf_header.e_shnum)), output_self_file); fclose(output_self_file); }
static PyObject * GMPY_mpz_lucasv_mod(PyObject *self, PyObject *args) { /* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf * calculate v[k] (modulo n) of Lucas V sequence for p,q. * Note: p^2-4q=0 is not tested, not a proper Lucas sequence!! */ MPZ_Object *result = 0, *p, *q, *k, *n; size_t s = 0, j = 0; mpz_t vl, vh, ql, qh, tmp; if (PyTuple_Size(args) != 4) { TYPE_ERROR("lucasv_mod() requires 4 integer arguments"); return NULL; } mpz_init(vl); mpz_init(vh); mpz_init(ql); mpz_init(qh); mpz_init(tmp); p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); k = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL); n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 3), NULL); if (!p || !q || !k || !n) { TYPE_ERROR("lucasv_mod() requires 4 integer arguments"); goto cleanup; } /* Check if p*p - 4*q == 0. */ mpz_mul(tmp, p->z, p->z); mpz_mul_ui(qh, q->z, 4); mpz_sub(tmp, tmp, qh); if (mpz_sgn(tmp) == 0) { VALUE_ERROR("invalid values for p,q in lucasv_mod()"); goto cleanup; } /* Check if k < 0. */ if (mpz_sgn(k->z) < 0) { VALUE_ERROR("invalid value for k in lucasv_mod()"); goto cleanup; } /* Check if n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("invalid value for n in lucasv_mod()"); goto cleanup; } mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); s = mpz_scan1(k->z, 0); for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(k->z,j) == 1) { /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); } if (!(result = GMPy_MPZ_New(NULL))) goto cleanup; /* vl contains our return value */ mpz_mod(result->z, vl, n->z); cleanup: mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)q); Py_XDECREF((PyObject*)k); Py_XDECREF((PyObject*)n); return (PyObject*)result; }
static int ec_add(mpz_t xr, mpz_t yr, mpz_t x1, mpz_t y1, int z1, mpz_t x2, mpz_t y2, int z2, unsigned long n, mpz_t a) { /* add two points of an elliptic curve by matching an addition rule, * in non-trivial cases producing a secant connecting the points (or a * tangent in case of overlapping points), finding the third intersection * point and mirroring it to the x axis */ if (0 == z1 && 0 == z2) /* 0 + 0 = 0 */ { mpz_set_ui(xr, 0); mpz_set_ui(yr, 1); return 0; } else if (0 == z2) /* P + 0 = P */ { mpz_set(xr, x1); mpz_set(yr, y1); return 1; } else if (0 == z1) /* 0 + Q = Q */ { mpz_set(xr, x2); mpz_set(yr, y2); return 1; } else if (0 != mpz_cmp(x1, x2)) /* P + Q, P != Q */ { /* m = (y2 - y1) / (x2 - x1) * xr = m^2 - x1 - x2 * yr = m * (x1 - x3) - y1 */ mpz_t xt, yt, tmp; mpz_init(xt); mpz_init(yt); mpz_init_set_ui(tmp, n); mpz_sub(yt, y2, y1); mpz_sub(xt, x2, x1); { /* multiplicative inverse over GF(n) using the Extended Euclidean * Algorithm * 1 = g = s * (x2 - x1) + t * n = s * (x2 - x1) */ mpz_t s, t, g; mpz_init(s); mpz_init(t); mpz_init(g); mpz_gcdext(g, s, t, xt, tmp); mpz_mul(xt, s, yt); mpz_mod_ui(xt, xt, n); mpz_set(yt, xt); mpz_clear(s); mpz_clear(t); mpz_clear(g); } mpz_mul(xt, xt, xt); mpz_sub(xt, xt, x1); mpz_sub(xt, xt, x2); mpz_mod_ui(xt, xt, n); mpz_sub(tmp, x1, xt); mpz_mul(yt, yt, tmp); mpz_sub(yt, yt, y1); mpz_mod_ui(yt, yt, n); mpz_set(xr, xt); mpz_set(yr, yt); mpz_clear(xt); mpz_clear(yt); mpz_clear(tmp); return 1; } else if (0 != mpz_cmp(y1, y2)) /* P + (-P) = 0 */ { mpz_set_ui(xr, 0); mpz_set_ui(yr, 1); return 0; } else /* P + P */ { /* m = (3 * x1^2 + a) / (2 * y1) * xr = m^2 - 2 * x1 * yr = m * (x1 - x3) - y1 */ mpz_t xt, yt, tmp; mpz_init(xt); mpz_init(yt); mpz_init_set_ui(tmp, n); mpz_mul(xt, x1, x1); mpz_mul_ui(xt, xt, 3); mpz_add(xt, xt, a); mpz_add(yt, y1, y1); { /* multiplicative inverse over GF(n) using the Extended Euclidean * Algorithm * 1 = g = s * (2 * y1) + t * n = s * (2 * y1) */ mpz_t s, t, g; mpz_init(s); mpz_init(t); mpz_init(g); mpz_gcdext(g, s, t, yt, tmp); mpz_mul(xt, s, xt); mpz_mod_ui(xt, xt, n); mpz_set(yt, xt); mpz_clear(s); mpz_clear(t); mpz_clear(g); } mpz_mul(xt, xt, xt); mpz_sub(xt, xt, x1); mpz_sub(xt, xt, x1); mpz_mod_ui(xt, xt, n); mpz_sub(tmp, x1, xt); mpz_mul(yt, yt, tmp); mpz_sub(yt, yt, y1); mpz_mod_ui(yt, yt, n); mpz_set(xr, xt); mpz_set(yr, yt); mpz_clear(xt); mpz_clear(yt); mpz_clear(tmp); return 1; } }
int rsa_generate_keypair(struct rsa_public_key *pub, struct rsa_private_key *key, void *random_ctx, nettle_random_func *random, void *progress_ctx, nettle_progress_func *progress, unsigned n_size, unsigned e_size) { mpz_t p1; mpz_t q1; mpz_t phi; mpz_t tmp; if (e_size) { /* We should choose e randomly. Is the size reasonable? */ if ((e_size < 16) || (e_size >= n_size) ) return 0; } else { /* We have a fixed e. Check that it makes sense */ /* It must be odd */ if (!mpz_tstbit(pub->e, 0)) return 0; /* And 3 or larger */ if (mpz_cmp_ui(pub->e, 3) < 0) return 0; /* And size less than n */ if (mpz_sizeinbase(pub->e, 2) >= n_size) return 0; } if (n_size < RSA_MINIMUM_N_BITS) return 0; mpz_init(p1); mpz_init(q1); mpz_init(phi); mpz_init(tmp); /* Generate primes */ for (;;) { /* Generate p, such that gcd(p-1, e) = 1 */ for (;;) { nettle_random_prime(key->p, (n_size+1)/2, 1, random_ctx, random, progress_ctx, progress); mpz_sub_ui(p1, key->p, 1); /* If e was given, we must chose p such that p-1 has no factors in * common with e. */ if (e_size) break; mpz_gcd(tmp, pub->e, p1); if (mpz_cmp_ui(tmp, 1) == 0) break; else if (progress) progress(progress_ctx, 'c'); } if (progress) progress(progress_ctx, '\n'); /* Generate q, such that gcd(q-1, e) = 1 */ for (;;) { nettle_random_prime(key->q, n_size/2, 1, random_ctx, random, progress_ctx, progress); /* Very unlikely. */ if (mpz_cmp (key->q, key->p) == 0) continue; mpz_sub_ui(q1, key->q, 1); /* If e was given, we must chose q such that q-1 has no factors in * common with e. */ if (e_size) break; mpz_gcd(tmp, pub->e, q1); if (mpz_cmp_ui(tmp, 1) == 0) break; else if (progress) progress(progress_ctx, 'c'); } /* Now we have the primes. Is the product of the right size? */ mpz_mul(pub->n, key->p, key->q); assert (mpz_sizeinbase(pub->n, 2) == n_size); if (progress) progress(progress_ctx, '\n'); /* c = q^{-1} (mod p) */ if (mpz_invert(key->c, key->q, key->p)) /* This should succeed everytime. But if it doesn't, * we try again. */ break; else if (progress) progress(progress_ctx, '?'); } mpz_mul(phi, p1, q1); /* If we didn't have a given e, generate one now. */ if (e_size) { int retried = 0; for (;;) { nettle_mpz_random_size(pub->e, random_ctx, random, e_size); /* Make sure it's odd and that the most significant bit is * set */ mpz_setbit(pub->e, 0); mpz_setbit(pub->e, e_size - 1); /* Needs gmp-3, or inverse might be negative. */ if (mpz_invert(key->d, pub->e, phi)) break; if (progress) progress(progress_ctx, 'e'); retried = 1; } if (retried && progress) progress(progress_ctx, '\n'); } else { /* Must always succeed, as we already that e * doesn't have any common factor with p-1 or q-1. */ int res = mpz_invert(key->d, pub->e, phi); assert(res); } /* Done! Almost, we must compute the auxillary private values. */ /* a = d % (p-1) */ mpz_fdiv_r(key->a, key->d, p1); /* b = d % (q-1) */ mpz_fdiv_r(key->b, key->d, q1); /* c was computed earlier */ pub->size = key->size = (n_size + 7) / 8; assert(pub->size >= RSA_MINIMUM_N_OCTETS); mpz_clear(p1); mpz_clear(q1); mpz_clear(phi); mpz_clear(tmp); return 1; }
void test_rsa_key(struct rsa_public_key *pub, struct rsa_private_key *key) { mpz_t tmp; mpz_t phi; mpz_init(tmp); mpz_init(phi); if (verbose) { /* FIXME: Use gmp_printf */ fprintf(stderr, "Public key: n="); mpz_out_str(stderr, 16, pub->n); fprintf(stderr, "\n e="); mpz_out_str(stderr, 16, pub->e); fprintf(stderr, "\n\nPrivate key: d="); mpz_out_str(stderr, 16, key->d); fprintf(stderr, "\n p="); mpz_out_str(stderr, 16, key->p); fprintf(stderr, "\n q="); mpz_out_str(stderr, 16, key->q); fprintf(stderr, "\n a="); mpz_out_str(stderr, 16, key->a); fprintf(stderr, "\n b="); mpz_out_str(stderr, 16, key->b); fprintf(stderr, "\n c="); mpz_out_str(stderr, 16, key->c); fprintf(stderr, "\n\n"); } /* Check n = p q */ mpz_mul(tmp, key->p, key->q); ASSERT (mpz_cmp(tmp, pub->n)== 0); /* Check c q = 1 mod p */ mpz_mul(tmp, key->c, key->q); mpz_fdiv_r(tmp, tmp, key->p); ASSERT (mpz_cmp_ui(tmp, 1) == 0); /* Check ed = 1 (mod phi) */ mpz_sub_ui(phi, key->p, 1); mpz_sub_ui(tmp, key->q, 1); mpz_mul(phi, phi, tmp); mpz_mul(tmp, pub->e, key->d); mpz_fdiv_r(tmp, tmp, phi); ASSERT (mpz_cmp_ui(tmp, 1) == 0); /* Check a e = 1 (mod (p-1) ) */ mpz_sub_ui(phi, key->p, 1); mpz_mul(tmp, pub->e, key->a); mpz_fdiv_r(tmp, tmp, phi); ASSERT (mpz_cmp_ui(tmp, 1) == 0); /* Check b e = 1 (mod (q-1) ) */ mpz_sub_ui(phi, key->q, 1); mpz_mul(tmp, pub->e, key->b); mpz_fdiv_r(tmp, tmp, phi); ASSERT (mpz_cmp_ui(tmp, 1) == 0); mpz_clear(tmp); mpz_clear(phi); }
int main(int argc, char *argv[]) { KryState state = STATE_BADARG; long mod_bits; if (argc == 3 && !strcmp(argv[1], "-g")) { // Key generation state = STATE_KEYGEN; mod_bits = strtol(argv[2], NULL, 10); if (mod_bits < 16) { state = STATE_BADARG; fprintf(stderr, "Too small key length\n"); } } else if (argc == 5 && !strcmp(argv[1], "-e")) { // Encryption state = STATE_ENCRYPTION; } else if (argc == 5 && !strcmp(argv[1], "-d")) { // Decryption state = STATE_DECRYPTION; } else if (argc == 5 && !strcmp(argv[1], "-b")) { // RSA cracking state = STATE_CRACKING; } if (state == STATE_BADARG) { // Someting is messed up print_help(argv[0]); return EXIT_FAILURE; } // Prepare pseudo number generator stuff gmp_randstate_t randstate; gmp_randinit_default(randstate); //gmp_randseed_ui(randstate, 1); gmp_randseed_ui(randstate, time(NULL)); int rc = EXIT_SUCCESS; mpz_t res; mpz_init(res); switch (state) { case STATE_KEYGEN: { mpz_t p, q, n, e; // For d use res var mpz_init(p); mpz_init(q); mpz_init(n); mpz_init(e); rc = keygen(p, q, n, e, res, mod_bits, randstate); gmp_printf("0x%Zx 0x%Zx 0x%Zx 0x%Zx 0x%Zx\n", p, q, n, e, res); mpz_clear(p); mpz_clear(q); mpz_clear(n); mpz_clear(e); break; } case STATE_ENCRYPTION: // Argv: [2]=e; [3]=n; [4]=m; rc = encrypt(res, argv[2], argv[3], argv[4]); gmp_printf("0x%Zx\n", res); break; case STATE_DECRYPTION: // Argv: [2]=d; [3]=n; [4]=c; rc = decrypt(res, argv[2], argv[3], argv[4]); gmp_printf("0x%Zx\n", res); break; case STATE_CRACKING: { // Argv: [2]=e; [3]=n; [4]=c; mpz_t p, q, p_, q_, e, d; mpz_init(p); mpz_init(q); mpz_init(p_); mpz_init(q_); mpz_init(e); mpz_init(d); rc = factorization(p, q, argv[3]); if (rc != 0) goto cracking_cleanup; // phi = (p-1) * (q-1) mpz_sub_ui(p_, p, 1L); mpz_sub_ui(q_, q, 1L); mpz_mul(res, p_, q_); // d = e^1 mod phi mpz_set_str(e, argv[2], 0); modinv(d, e, res); rc = decrypt_mpz_d(res, d, argv[3], argv[4]); gmp_printf("0x%Zx 0x%Zx 0x%Zx\n", p, q, res); cracking_cleanup: mpz_clear(p); mpz_clear(q); mpz_clear(p_); mpz_clear(q_); mpz_clear(e); mpz_clear(d); break; } case STATE_BADARG: break; } mpz_clear(res); gmp_randclear(randstate); return rc; }
void gfc_advance_section (mpz_t *section_index, gfc_array_ref *ar, mpz_t *offset_ret) { int i; mpz_t delta; mpz_t tmp; bool forwards; int cmp; for (i = 0; i < ar->dimen; i++) { if (ar->dimen_type[i] != DIMEN_RANGE) continue; if (ar->stride[i]) { mpz_add (section_index[i], section_index[i], ar->stride[i]->value.integer); if (mpz_cmp_si (ar->stride[i]->value.integer, 0) >= 0) forwards = true; else forwards = false; } else { mpz_add_ui (section_index[i], section_index[i], 1); forwards = true; } if (ar->end[i]) cmp = mpz_cmp (section_index[i], ar->end[i]->value.integer); else cmp = mpz_cmp (section_index[i], ar->as->upper[i]->value.integer); if ((cmp > 0 && forwards) || (cmp < 0 && !forwards)) { /* Reset index to start, then loop to advance the next index. */ if (ar->start[i]) mpz_set (section_index[i], ar->start[i]->value.integer); else mpz_set (section_index[i], ar->as->lower[i]->value.integer); } else break; } mpz_set_si (*offset_ret, 0); mpz_init_set_si (delta, 1); mpz_init (tmp); for (i = 0; i < ar->dimen; i++) { mpz_sub (tmp, section_index[i], ar->as->lower[i]->value.integer); mpz_mul (tmp, tmp, delta); mpz_add (*offset_ret, tmp, *offset_ret); mpz_sub (tmp, ar->as->upper[i]->value.integer, ar->as->lower[i]->value.integer); mpz_add_ui (tmp, tmp, 1); mpz_mul (delta, tmp, delta); } mpz_clear (tmp); mpz_clear (delta); }
/* sqrtmod_prime */ static int sqrtmod_prime(void *n, void *prime, void *ret) { int res, legendre, i; mpz_t t1, C, Q, S, Z, M, T, R, two; LTC_ARGCHK(n != NULL); LTC_ARGCHK(prime != NULL); LTC_ARGCHK(ret != NULL); /* first handle the simple cases */ if (mpz_cmp_ui(((__mpz_struct *)n), 0) == 0) { mpz_set_ui(ret, 0); return CRYPT_OK; } if (mpz_cmp_ui(((__mpz_struct *)prime), 2) == 0) return CRYPT_ERROR; /* prime must be odd */ legendre = mpz_legendre(n, prime); if (legendre == -1) return CRYPT_ERROR; /* quadratic non-residue mod prime */ mpz_init(t1); mpz_init(C); mpz_init(Q); mpz_init(S); mpz_init(Z); mpz_init(M); mpz_init(T); mpz_init(R); mpz_init(two); /* SPECIAL CASE: if prime mod 4 == 3 * compute directly: res = n^(prime+1)/4 mod prime * Handbook of Applied Cryptography algorithm 3.36 */ i = mpz_mod_ui(t1, prime, 4); /* t1 is ignored here */ if (i == 3) { mpz_add_ui(t1, prime, 1); mpz_fdiv_q_2exp(t1, t1, 2); mpz_powm(ret, n, t1, prime); res = CRYPT_OK; goto cleanup; } /* NOW: Tonelli-Shanks algorithm */ /* factor out powers of 2 from prime-1, defining Q and S as: prime-1 = Q*2^S */ mpz_set(Q, prime); mpz_sub_ui(Q, Q, 1); /* Q = prime - 1 */ mpz_set_ui(S, 0); /* S = 0 */ while (mpz_even_p(Q)) { mpz_fdiv_q_2exp(Q, Q, 1); /* Q = Q / 2 */ mpz_add_ui(S, S, 1); /* S = S + 1 */ } /* find a Z such that the Legendre symbol (Z|prime) == -1 */ mpz_set_ui(Z, 2); /* Z = 2 */ while(1) { legendre = mpz_legendre(Z, prime); if (legendre == -1) break; mpz_add_ui(Z, Z, 1); /* Z = Z + 1 */ } mpz_powm(C, Z, Q, prime); /* C = Z ^ Q mod prime */ mpz_add_ui(t1, Q, 1); mpz_fdiv_q_2exp(t1, t1, 1); /* t1 = (Q + 1) / 2 */ mpz_powm(R, n, t1, prime); /* R = n ^ ((Q + 1) / 2) mod prime */ mpz_powm(T, n, Q, prime); /* T = n ^ Q mod prime */ mpz_set(M, S); /* M = S */ mpz_set_ui(two, 2); while (1) { mpz_set(t1, T); i = 0; while (1) { if (mpz_cmp_ui(((__mpz_struct *)t1), 1) == 0) break; mpz_powm(t1, t1, two, prime); i++; } if (i == 0) { mpz_set(ret, R); res = CRYPT_OK; goto cleanup; } mpz_sub_ui(t1, M, i); mpz_sub_ui(t1, t1, 1); mpz_powm(t1, two, t1, prime); /* t1 = 2 ^ (M - i - 1) */ mpz_powm(t1, C, t1, prime); /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */ mpz_mul(C, t1, t1); mpz_mod(C, C, prime); /* C = (t1 * t1) mod prime */ mpz_mul(R, R, t1); mpz_mod(R, R, prime); /* R = (R * t1) mod prime */ mpz_mul(T, T, C); mpz_mod(T, T, prime); /* T = (T * C) mod prime */ mpz_set_ui(M, i); /* M = i */ } cleanup: mpz_clear(t1); mpz_clear(C); mpz_clear(Q); mpz_clear(S); mpz_clear(Z); mpz_clear(M); mpz_clear(T); mpz_clear(R); mpz_clear(two); return res; }