Remove building with NOCRYPTO option
[minix.git] / crypto / external / bsd / heimdal / dist / lib / hcrypto / libtommath / etc / pprime.c
blob0e03ab1ba43e3041bec876db05307395a2fcd614
1 /* $NetBSD: pprime.c,v 1.1.1.2 2014/04/24 12:45:39 pettai Exp $ */
3 /* Generates provable primes
5 * See http://gmail.com:8080/papers/pp.pdf for more info.
7 * Tom St Denis, tomstdenis@gmail.com, http://tom.gmail.com
8 */
9 #include <time.h>
10 #include "tommath.h"
12 int n_prime;
13 FILE *primes;
15 /* fast square root */
16 static mp_digit
17 i_sqrt (mp_word x)
19 mp_word x1, x2;
21 x2 = x;
22 do {
23 x1 = x2;
24 x2 = x1 - ((x1 * x1) - x) / (2 * x1);
25 } while (x1 != x2);
27 if (x1 * x1 > x) {
28 --x1;
31 return x1;
35 /* generates a prime digit */
36 static void gen_prime (void)
38 mp_digit r, x, y, next;
39 FILE *out;
41 out = fopen("pprime.dat", "wb");
43 /* write first set of primes */
44 r = 3; fwrite(&r, 1, sizeof(mp_digit), out);
45 r = 5; fwrite(&r, 1, sizeof(mp_digit), out);
46 r = 7; fwrite(&r, 1, sizeof(mp_digit), out);
47 r = 11; fwrite(&r, 1, sizeof(mp_digit), out);
48 r = 13; fwrite(&r, 1, sizeof(mp_digit), out);
49 r = 17; fwrite(&r, 1, sizeof(mp_digit), out);
50 r = 19; fwrite(&r, 1, sizeof(mp_digit), out);
51 r = 23; fwrite(&r, 1, sizeof(mp_digit), out);
52 r = 29; fwrite(&r, 1, sizeof(mp_digit), out);
53 r = 31; fwrite(&r, 1, sizeof(mp_digit), out);
55 /* get square root, since if 'r' is composite its factors must be < than this */
56 y = i_sqrt (r);
57 next = (y + 1) * (y + 1);
59 for (;;) {
60 do {
61 r += 2; /* next candidate */
62 r &= MP_MASK;
63 if (r < 31) break;
65 /* update sqrt ? */
66 if (next <= r) {
67 ++y;
68 next = (y + 1) * (y + 1);
71 /* loop if divisible by 3,5,7,11,13,17,19,23,29 */
72 if ((r % 3) == 0) {
73 x = 0;
74 continue;
76 if ((r % 5) == 0) {
77 x = 0;
78 continue;
80 if ((r % 7) == 0) {
81 x = 0;
82 continue;
84 if ((r % 11) == 0) {
85 x = 0;
86 continue;
88 if ((r % 13) == 0) {
89 x = 0;
90 continue;
92 if ((r % 17) == 0) {
93 x = 0;
94 continue;
96 if ((r % 19) == 0) {
97 x = 0;
98 continue;
100 if ((r % 23) == 0) {
101 x = 0;
102 continue;
104 if ((r % 29) == 0) {
105 x = 0;
106 continue;
109 /* now check if r is divisible by x + k={1,7,11,13,17,19,23,29} */
110 for (x = 30; x <= y; x += 30) {
111 if ((r % (x + 1)) == 0) {
112 x = 0;
113 break;
115 if ((r % (x + 7)) == 0) {
116 x = 0;
117 break;
119 if ((r % (x + 11)) == 0) {
120 x = 0;
121 break;
123 if ((r % (x + 13)) == 0) {
124 x = 0;
125 break;
127 if ((r % (x + 17)) == 0) {
128 x = 0;
129 break;
131 if ((r % (x + 19)) == 0) {
132 x = 0;
133 break;
135 if ((r % (x + 23)) == 0) {
136 x = 0;
137 break;
139 if ((r % (x + 29)) == 0) {
140 x = 0;
141 break;
144 } while (x == 0);
145 if (r > 31) { fwrite(&r, 1, sizeof(mp_digit), out); printf("%9d\r", r); fflush(stdout); }
146 if (r < 31) break;
149 fclose(out);
152 void load_tab(void)
154 primes = fopen("pprime.dat", "rb");
155 if (primes == NULL) {
156 gen_prime();
157 primes = fopen("pprime.dat", "rb");
159 fseek(primes, 0, SEEK_END);
160 n_prime = ftell(primes) / sizeof(mp_digit);
163 mp_digit prime_digit(void)
165 int n;
166 mp_digit d;
168 n = abs(rand()) % n_prime;
169 fseek(primes, n * sizeof(mp_digit), SEEK_SET);
170 fread(&d, 1, sizeof(mp_digit), primes);
171 return d;
175 /* makes a prime of at least k bits */
177 pprime (int k, int li, mp_int * p, mp_int * q)
179 mp_int a, b, c, n, x, y, z, v;
180 int res, ii;
181 static const mp_digit bases[] = { 2, 3, 5, 7, 11, 13, 17, 19 };
183 /* single digit ? */
184 if (k <= (int) DIGIT_BIT) {
185 mp_set (p, prime_digit ());
186 return MP_OKAY;
189 if ((res = mp_init (&c)) != MP_OKAY) {
190 return res;
193 if ((res = mp_init (&v)) != MP_OKAY) {
194 goto LBL_C;
197 /* product of first 50 primes */
198 if ((res =
199 mp_read_radix (&v,
200 "19078266889580195013601891820992757757219839668357012055907516904309700014933909014729740190",
201 10)) != MP_OKAY) {
202 goto LBL_V;
205 if ((res = mp_init (&a)) != MP_OKAY) {
206 goto LBL_V;
209 /* set the prime */
210 mp_set (&a, prime_digit ());
212 if ((res = mp_init (&b)) != MP_OKAY) {
213 goto LBL_A;
216 if ((res = mp_init (&n)) != MP_OKAY) {
217 goto LBL_B;
220 if ((res = mp_init (&x)) != MP_OKAY) {
221 goto LBL_N;
224 if ((res = mp_init (&y)) != MP_OKAY) {
225 goto LBL_X;
228 if ((res = mp_init (&z)) != MP_OKAY) {
229 goto LBL_Y;
232 /* now loop making the single digit */
233 while (mp_count_bits (&a) < k) {
234 fprintf (stderr, "prime has %4d bits left\r", k - mp_count_bits (&a));
235 fflush (stderr);
236 top:
237 mp_set (&b, prime_digit ());
239 /* now compute z = a * b * 2 */
240 if ((res = mp_mul (&a, &b, &z)) != MP_OKAY) { /* z = a * b */
241 goto LBL_Z;
244 if ((res = mp_copy (&z, &c)) != MP_OKAY) { /* c = a * b */
245 goto LBL_Z;
248 if ((res = mp_mul_2 (&z, &z)) != MP_OKAY) { /* z = 2 * a * b */
249 goto LBL_Z;
252 /* n = z + 1 */
253 if ((res = mp_add_d (&z, 1, &n)) != MP_OKAY) { /* n = z + 1 */
254 goto LBL_Z;
257 /* check (n, v) == 1 */
258 if ((res = mp_gcd (&n, &v, &y)) != MP_OKAY) { /* y = (n, v) */
259 goto LBL_Z;
262 if (mp_cmp_d (&y, 1) != MP_EQ)
263 goto top;
265 /* now try base x=bases[ii] */
266 for (ii = 0; ii < li; ii++) {
267 mp_set (&x, bases[ii]);
269 /* compute x^a mod n */
270 if ((res = mp_exptmod (&x, &a, &n, &y)) != MP_OKAY) { /* y = x^a mod n */
271 goto LBL_Z;
274 /* if y == 1 loop */
275 if (mp_cmp_d (&y, 1) == MP_EQ)
276 continue;
278 /* now x^2a mod n */
279 if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2a mod n */
280 goto LBL_Z;
283 if (mp_cmp_d (&y, 1) == MP_EQ)
284 continue;
286 /* compute x^b mod n */
287 if ((res = mp_exptmod (&x, &b, &n, &y)) != MP_OKAY) { /* y = x^b mod n */
288 goto LBL_Z;
291 /* if y == 1 loop */
292 if (mp_cmp_d (&y, 1) == MP_EQ)
293 continue;
295 /* now x^2b mod n */
296 if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2b mod n */
297 goto LBL_Z;
300 if (mp_cmp_d (&y, 1) == MP_EQ)
301 continue;
303 /* compute x^c mod n == x^ab mod n */
304 if ((res = mp_exptmod (&x, &c, &n, &y)) != MP_OKAY) { /* y = x^ab mod n */
305 goto LBL_Z;
308 /* if y == 1 loop */
309 if (mp_cmp_d (&y, 1) == MP_EQ)
310 continue;
312 /* now compute (x^c mod n)^2 */
313 if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2ab mod n */
314 goto LBL_Z;
317 /* y should be 1 */
318 if (mp_cmp_d (&y, 1) != MP_EQ)
319 continue;
320 break;
323 /* no bases worked? */
324 if (ii == li)
325 goto top;
328 char buf[4096];
330 mp_toradix(&n, buf, 10);
331 printf("Certificate of primality for:\n%s\n\n", buf);
332 mp_toradix(&a, buf, 10);
333 printf("A == \n%s\n\n", buf);
334 mp_toradix(&b, buf, 10);
335 printf("B == \n%s\n\nG == %d\n", buf, bases[ii]);
336 printf("----------------------------------------------------------------\n");
339 /* a = n */
340 mp_copy (&n, &a);
343 /* get q to be the order of the large prime subgroup */
344 mp_sub_d (&n, 1, q);
345 mp_div_2 (q, q);
346 mp_div (q, &b, q, NULL);
348 mp_exch (&n, p);
350 res = MP_OKAY;
351 LBL_Z:mp_clear (&z);
352 LBL_Y:mp_clear (&y);
353 LBL_X:mp_clear (&x);
354 LBL_N:mp_clear (&n);
355 LBL_B:mp_clear (&b);
356 LBL_A:mp_clear (&a);
357 LBL_V:mp_clear (&v);
358 LBL_C:mp_clear (&c);
359 return res;
364 main (void)
366 mp_int p, q;
367 char buf[4096];
368 int k, li;
369 clock_t t1;
371 srand (time (NULL));
372 load_tab();
374 printf ("Enter # of bits: \n");
375 fgets (buf, sizeof (buf), stdin);
376 sscanf (buf, "%d", &k);
378 printf ("Enter number of bases to try (1 to 8):\n");
379 fgets (buf, sizeof (buf), stdin);
380 sscanf (buf, "%d", &li);
383 mp_init (&p);
384 mp_init (&q);
386 t1 = clock ();
387 pprime (k, li, &p, &q);
388 t1 = clock () - t1;
390 printf ("\n\nTook %ld ticks, %d bits\n", t1, mp_count_bits (&p));
392 mp_toradix (&p, buf, 10);
393 printf ("P == %s\n", buf);
394 mp_toradix (&q, buf, 10);
395 printf ("Q == %s\n", buf);
397 return 0;
400 /* Source: /cvs/libtom/libtommath/etc/pprime.c,v */
401 /* Revision: 1.3 */
402 /* Date: 2006/03/31 14:18:47 */