Mercurial > dropbear
view libtommath/etc/pprime.c @ 1156:a8f4dade70e5
avoid getpass when not used
some systems (like android's bionic) do not provide getpass. you can
disable ENABLE_CLI_PASSWORD_AUTH & ENABLE_CLI_INTERACT_AUTH to avoid
its use (and rely on pubkey auth), but the link still fails because
the support file calls getpass. do not define this func if both of
those auth methods are not used.
author | Mike Frysinger <vapier@gentoo.org> |
---|---|
date | Wed, 21 Oct 2015 22:39:55 +0800 |
parents | 5ff8218bcee9 |
children | 60fc6476e044 |
line wrap: on
line source
/* Generates provable primes * * See http://gmail.com:8080/papers/pp.pdf for more info. * * Tom St Denis, [email protected], http://tom.gmail.com */ #include <time.h> #include "tommath.h" int n_prime; FILE *primes; /* fast square root */ static mp_digit i_sqrt (mp_word x) { mp_word x1, x2; x2 = x; do { x1 = x2; x2 = x1 - ((x1 * x1) - x) / (2 * x1); } while (x1 != x2); if (x1 * x1 > x) { --x1; } return x1; } /* generates a prime digit */ static void gen_prime (void) { mp_digit r, x, y, next; FILE *out; out = fopen("pprime.dat", "wb"); /* write first set of primes */ r = 3; fwrite(&r, 1, sizeof(mp_digit), out); r = 5; fwrite(&r, 1, sizeof(mp_digit), out); r = 7; fwrite(&r, 1, sizeof(mp_digit), out); r = 11; fwrite(&r, 1, sizeof(mp_digit), out); r = 13; fwrite(&r, 1, sizeof(mp_digit), out); r = 17; fwrite(&r, 1, sizeof(mp_digit), out); r = 19; fwrite(&r, 1, sizeof(mp_digit), out); r = 23; fwrite(&r, 1, sizeof(mp_digit), out); r = 29; fwrite(&r, 1, sizeof(mp_digit), out); r = 31; fwrite(&r, 1, sizeof(mp_digit), out); /* get square root, since if 'r' is composite its factors must be < than this */ y = i_sqrt (r); next = (y + 1) * (y + 1); for (;;) { do { r += 2; /* next candidate */ r &= MP_MASK; if (r < 31) break; /* update sqrt ? */ if (next <= r) { ++y; next = (y + 1) * (y + 1); } /* loop if divisible by 3,5,7,11,13,17,19,23,29 */ if ((r % 3) == 0) { x = 0; continue; } if ((r % 5) == 0) { x = 0; continue; } if ((r % 7) == 0) { x = 0; continue; } if ((r % 11) == 0) { x = 0; continue; } if ((r % 13) == 0) { x = 0; continue; } if ((r % 17) == 0) { x = 0; continue; } if ((r % 19) == 0) { x = 0; continue; } if ((r % 23) == 0) { x = 0; continue; } if ((r % 29) == 0) { x = 0; continue; } /* now check if r is divisible by x + k={1,7,11,13,17,19,23,29} */ for (x = 30; x <= y; x += 30) { if ((r % (x + 1)) == 0) { x = 0; break; } if ((r % (x + 7)) == 0) { x = 0; break; } if ((r % (x + 11)) == 0) { x = 0; break; } if ((r % (x + 13)) == 0) { x = 0; break; } if ((r % (x + 17)) == 0) { x = 0; break; } if ((r % (x + 19)) == 0) { x = 0; break; } if ((r % (x + 23)) == 0) { x = 0; break; } if ((r % (x + 29)) == 0) { x = 0; break; } } } while (x == 0); if (r > 31) { fwrite(&r, 1, sizeof(mp_digit), out); printf("%9d\r", r); fflush(stdout); } if (r < 31) break; } fclose(out); } void load_tab(void) { primes = fopen("pprime.dat", "rb"); if (primes == NULL) { gen_prime(); primes = fopen("pprime.dat", "rb"); } fseek(primes, 0, SEEK_END); n_prime = ftell(primes) / sizeof(mp_digit); } mp_digit prime_digit(void) { int n; mp_digit d; n = abs(rand()) % n_prime; fseek(primes, n * sizeof(mp_digit), SEEK_SET); fread(&d, 1, sizeof(mp_digit), primes); return d; } /* makes a prime of at least k bits */ int pprime (int k, int li, mp_int * p, mp_int * q) { mp_int a, b, c, n, x, y, z, v; int res, ii; static const mp_digit bases[] = { 2, 3, 5, 7, 11, 13, 17, 19 }; /* single digit ? */ if (k <= (int) DIGIT_BIT) { mp_set (p, prime_digit ()); return MP_OKAY; } if ((res = mp_init (&c)) != MP_OKAY) { return res; } if ((res = mp_init (&v)) != MP_OKAY) { goto LBL_C; } /* product of first 50 primes */ if ((res = mp_read_radix (&v, "19078266889580195013601891820992757757219839668357012055907516904309700014933909014729740190", 10)) != MP_OKAY) { goto LBL_V; } if ((res = mp_init (&a)) != MP_OKAY) { goto LBL_V; } /* set the prime */ mp_set (&a, prime_digit ()); if ((res = mp_init (&b)) != MP_OKAY) { goto LBL_A; } if ((res = mp_init (&n)) != MP_OKAY) { goto LBL_B; } if ((res = mp_init (&x)) != MP_OKAY) { goto LBL_N; } if ((res = mp_init (&y)) != MP_OKAY) { goto LBL_X; } if ((res = mp_init (&z)) != MP_OKAY) { goto LBL_Y; } /* now loop making the single digit */ while (mp_count_bits (&a) < k) { fprintf (stderr, "prime has %4d bits left\r", k - mp_count_bits (&a)); fflush (stderr); top: mp_set (&b, prime_digit ()); /* now compute z = a * b * 2 */ if ((res = mp_mul (&a, &b, &z)) != MP_OKAY) { /* z = a * b */ goto LBL_Z; } if ((res = mp_copy (&z, &c)) != MP_OKAY) { /* c = a * b */ goto LBL_Z; } if ((res = mp_mul_2 (&z, &z)) != MP_OKAY) { /* z = 2 * a * b */ goto LBL_Z; } /* n = z + 1 */ if ((res = mp_add_d (&z, 1, &n)) != MP_OKAY) { /* n = z + 1 */ goto LBL_Z; } /* check (n, v) == 1 */ if ((res = mp_gcd (&n, &v, &y)) != MP_OKAY) { /* y = (n, v) */ goto LBL_Z; } if (mp_cmp_d (&y, 1) != MP_EQ) goto top; /* now try base x=bases[ii] */ for (ii = 0; ii < li; ii++) { mp_set (&x, bases[ii]); /* compute x^a mod n */ if ((res = mp_exptmod (&x, &a, &n, &y)) != MP_OKAY) { /* y = x^a mod n */ goto LBL_Z; } /* if y == 1 loop */ if (mp_cmp_d (&y, 1) == MP_EQ) continue; /* now x^2a mod n */ if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2a mod n */ goto LBL_Z; } if (mp_cmp_d (&y, 1) == MP_EQ) continue; /* compute x^b mod n */ if ((res = mp_exptmod (&x, &b, &n, &y)) != MP_OKAY) { /* y = x^b mod n */ goto LBL_Z; } /* if y == 1 loop */ if (mp_cmp_d (&y, 1) == MP_EQ) continue; /* now x^2b mod n */ if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2b mod n */ goto LBL_Z; } if (mp_cmp_d (&y, 1) == MP_EQ) continue; /* compute x^c mod n == x^ab mod n */ if ((res = mp_exptmod (&x, &c, &n, &y)) != MP_OKAY) { /* y = x^ab mod n */ goto LBL_Z; } /* if y == 1 loop */ if (mp_cmp_d (&y, 1) == MP_EQ) continue; /* now compute (x^c mod n)^2 */ if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2ab mod n */ goto LBL_Z; } /* y should be 1 */ if (mp_cmp_d (&y, 1) != MP_EQ) continue; break; } /* no bases worked? */ if (ii == li) goto top; { char buf[4096]; mp_toradix(&n, buf, 10); printf("Certificate of primality for:\n%s\n\n", buf); mp_toradix(&a, buf, 10); printf("A == \n%s\n\n", buf); mp_toradix(&b, buf, 10); printf("B == \n%s\n\nG == %d\n", buf, bases[ii]); printf("----------------------------------------------------------------\n"); } /* a = n */ mp_copy (&n, &a); } /* get q to be the order of the large prime subgroup */ mp_sub_d (&n, 1, q); mp_div_2 (q, q); mp_div (q, &b, q, NULL); mp_exch (&n, p); res = MP_OKAY; LBL_Z:mp_clear (&z); LBL_Y:mp_clear (&y); LBL_X:mp_clear (&x); LBL_N:mp_clear (&n); LBL_B:mp_clear (&b); LBL_A:mp_clear (&a); LBL_V:mp_clear (&v); LBL_C:mp_clear (&c); return res; } int main (void) { mp_int p, q; char buf[4096]; int k, li; clock_t t1; srand (time (NULL)); load_tab(); printf ("Enter # of bits: \n"); fgets (buf, sizeof (buf), stdin); sscanf (buf, "%d", &k); printf ("Enter number of bases to try (1 to 8):\n"); fgets (buf, sizeof (buf), stdin); sscanf (buf, "%d", &li); mp_init (&p); mp_init (&q); t1 = clock (); pprime (k, li, &p, &q); t1 = clock () - t1; printf ("\n\nTook %ld ticks, %d bits\n", t1, mp_count_bits (&p)); mp_toradix (&p, buf, 10); printf ("P == %s\n", buf); mp_toradix (&q, buf, 10); printf ("Q == %s\n", buf); return 0; } /* $Source: /cvs/libtom/libtommath/etc/pprime.c,v $ */ /* $Revision: 1.3 $ */ /* $Date: 2006/03/31 14:18:47 $ */