1 /* Generates provable primes
3 * See http://iahu.ca:8080/papers/pp.pdf for more info.
5 * Tom St Denis, tomstdenis@iahu.ca, http://tom.iahu.ca
10 /* fast square root */
19 x2 = x1 - ((x1 * x1) - x) / (2 * x1);
30 /* generates a prime digit */
34 mp_digit r, x, y, next;
36 /* make a DIGIT_BIT-bit random number */
37 for (r = x = 0; x < DIGIT_BIT; x++) {
38 r = (r << 1) | (rand () & 1);
41 /* now force it odd */
44 /* force it to be >30 */
49 /* get square root, since if 'r' is composite its factors must be < than this */
51 next = (y + 1) * (y + 1);
54 r += 2; /* next candidate */
59 next = (y + 1) * (y + 1);
62 /* loop if divisible by 3,5,7,11,13,17,19,23,29 */
100 /* now check if r is divisible by x + k={1,7,11,13,17,19,23,29} */
101 for (x = 30; x <= y; x += 30) {
102 if ((r % (x + 1)) == 0) {
106 if ((r % (x + 7)) == 0) {
110 if ((r % (x + 11)) == 0) {
114 if ((r % (x + 13)) == 0) {
118 if ((r % (x + 17)) == 0) {
122 if ((r % (x + 19)) == 0) {
126 if ((r % (x + 23)) == 0) {
130 if ((r % (x + 29)) == 0) {
140 /* makes a prime of at least k bits */
142 pprime (int k, int li, mp_int * p, mp_int * q)
144 mp_int a, b, c, n, x, y, z, v;
146 static const mp_digit bases[] = { 2, 3, 5, 7, 11, 13, 17, 19 };
149 if (k <= (int) DIGIT_BIT) {
150 mp_set (p, prime_digit ());
154 if ((res = mp_init (&c)) != MP_OKAY) {
158 if ((res = mp_init (&v)) != MP_OKAY) {
162 /* product of first 50 primes */
165 "19078266889580195013601891820992757757219839668357012055907516904309700014933909014729740190",
170 if ((res = mp_init (&a)) != MP_OKAY) {
175 mp_set (&a, prime_digit ());
177 if ((res = mp_init (&b)) != MP_OKAY) {
181 if ((res = mp_init (&n)) != MP_OKAY) {
185 if ((res = mp_init (&x)) != MP_OKAY) {
189 if ((res = mp_init (&y)) != MP_OKAY) {
193 if ((res = mp_init (&z)) != MP_OKAY) {
197 /* now loop making the single digit */
198 while (mp_count_bits (&a) < k) {
199 printf ("prime has %4d bits left\r", k - mp_count_bits (&a));
202 mp_set (&b, prime_digit ());
204 /* now compute z = a * b * 2 */
205 if ((res = mp_mul (&a, &b, &z)) != MP_OKAY) { /* z = a * b */
209 if ((res = mp_copy (&z, &c)) != MP_OKAY) { /* c = a * b */
213 if ((res = mp_mul_2 (&z, &z)) != MP_OKAY) { /* z = 2 * a * b */
218 if ((res = mp_add_d (&z, 1, &n)) != MP_OKAY) { /* n = z + 1 */
222 /* check (n, v) == 1 */
223 if ((res = mp_gcd (&n, &v, &y)) != MP_OKAY) { /* y = (n, v) */
227 if (mp_cmp_d (&y, 1) != MP_EQ)
230 /* now try base x=bases[ii] */
231 for (ii = 0; ii < li; ii++) {
232 mp_set (&x, bases[ii]);
234 /* compute x^a mod n */
235 if ((res = mp_exptmod (&x, &a, &n, &y)) != MP_OKAY) { /* y = x^a mod n */
240 if (mp_cmp_d (&y, 1) == MP_EQ)
244 if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2a mod n */
248 if (mp_cmp_d (&y, 1) == MP_EQ)
251 /* compute x^b mod n */
252 if ((res = mp_exptmod (&x, &b, &n, &y)) != MP_OKAY) { /* y = x^b mod n */
257 if (mp_cmp_d (&y, 1) == MP_EQ)
261 if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2b mod n */
265 if (mp_cmp_d (&y, 1) == MP_EQ)
268 /* compute x^c mod n == x^ab mod n */
269 if ((res = mp_exptmod (&x, &c, &n, &y)) != MP_OKAY) { /* y = x^ab mod n */
274 if (mp_cmp_d (&y, 1) == MP_EQ)
277 /* now compute (x^c mod n)^2 */
278 if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2ab mod n */
283 if (mp_cmp_d (&y, 1) != MP_EQ)
288 /* no bases worked? */
296 mp_toradix(&n, buf, 10);
297 printf("Certificate of primality for:\n%s\n\n", buf);
298 mp_toradix(&a, buf, 10);
299 printf("A == \n%s\n\n", buf);
300 mp_toradix(&b, buf, 10);
301 printf("B == \n%s\n", buf);
302 printf("----------------------------------------------------------------\n");
309 /* get q to be the order of the large prime subgroup */
312 mp_div (q, &b, q, NULL);
339 printf ("Enter # of bits: \n");
340 fgets (buf, sizeof (buf), stdin);
341 sscanf (buf, "%d", &k);
343 printf ("Enter number of bases to try (1 to 8):\n");
344 fgets (buf, sizeof (buf), stdin);
345 sscanf (buf, "%d", &li);
352 pprime (k, li, &p, &q);
355 printf ("\n\nTook %ld ticks, %d bits\n", t1, mp_count_bits (&p));
357 mp_toradix (&p, buf, 10);
358 printf ("P == %s\n", buf);
359 mp_toradix (&q, buf, 10);
360 printf ("Q == %s\n", buf);