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
15 /* fast square root */
24 x2
= x1
- ((x1
* x1
) - x
) / (2 * x1
);
35 /* generates a prime digit */
36 static void gen_prime (void)
38 mp_digit r
, x
, y
, next
;
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 */
57 next
= (y
+ 1) * (y
+ 1);
61 r
+= 2; /* next candidate */
68 next
= (y
+ 1) * (y
+ 1);
71 /* loop if divisible by 3,5,7,11,13,17,19,23,29 */
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) {
115 if ((r
% (x
+ 7)) == 0) {
119 if ((r
% (x
+ 11)) == 0) {
123 if ((r
% (x
+ 13)) == 0) {
127 if ((r
% (x
+ 17)) == 0) {
131 if ((r
% (x
+ 19)) == 0) {
135 if ((r
% (x
+ 23)) == 0) {
139 if ((r
% (x
+ 29)) == 0) {
145 if (r
> 31) { fwrite(&r
, 1, sizeof(mp_digit
), out
); printf("%9d\r", r
); fflush(stdout
); }
154 primes
= fopen("pprime.dat", "rb");
155 if (primes
== NULL
) {
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)
168 n
= abs(rand()) % n_prime
;
169 fseek(primes
, n
* sizeof(mp_digit
), SEEK_SET
);
170 fread(&d
, 1, sizeof(mp_digit
), primes
);
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
;
181 static const mp_digit bases
[] = { 2, 3, 5, 7, 11, 13, 17, 19 };
184 if (k
<= (int) DIGIT_BIT
) {
185 mp_set (p
, prime_digit ());
189 if ((res
= mp_init (&c
)) != MP_OKAY
) {
193 if ((res
= mp_init (&v
)) != MP_OKAY
) {
197 /* product of first 50 primes */
200 "19078266889580195013601891820992757757219839668357012055907516904309700014933909014729740190",
205 if ((res
= mp_init (&a
)) != MP_OKAY
) {
210 mp_set (&a
, prime_digit ());
212 if ((res
= mp_init (&b
)) != MP_OKAY
) {
216 if ((res
= mp_init (&n
)) != MP_OKAY
) {
220 if ((res
= mp_init (&x
)) != MP_OKAY
) {
224 if ((res
= mp_init (&y
)) != MP_OKAY
) {
228 if ((res
= mp_init (&z
)) != MP_OKAY
) {
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
));
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 */
244 if ((res
= mp_copy (&z
, &c
)) != MP_OKAY
) { /* c = a * b */
248 if ((res
= mp_mul_2 (&z
, &z
)) != MP_OKAY
) { /* z = 2 * a * b */
253 if ((res
= mp_add_d (&z
, 1, &n
)) != MP_OKAY
) { /* n = z + 1 */
257 /* check (n, v) == 1 */
258 if ((res
= mp_gcd (&n
, &v
, &y
)) != MP_OKAY
) { /* y = (n, v) */
262 if (mp_cmp_d (&y
, 1) != MP_EQ
)
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 */
275 if (mp_cmp_d (&y
, 1) == MP_EQ
)
279 if ((res
= mp_sqrmod (&y
, &n
, &y
)) != MP_OKAY
) { /* y = x^2a mod n */
283 if (mp_cmp_d (&y
, 1) == MP_EQ
)
286 /* compute x^b mod n */
287 if ((res
= mp_exptmod (&x
, &b
, &n
, &y
)) != MP_OKAY
) { /* y = x^b mod n */
292 if (mp_cmp_d (&y
, 1) == MP_EQ
)
296 if ((res
= mp_sqrmod (&y
, &n
, &y
)) != MP_OKAY
) { /* y = x^2b mod n */
300 if (mp_cmp_d (&y
, 1) == MP_EQ
)
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 */
309 if (mp_cmp_d (&y
, 1) == MP_EQ
)
312 /* now compute (x^c mod n)^2 */
313 if ((res
= mp_sqrmod (&y
, &n
, &y
)) != MP_OKAY
) { /* y = x^2ab mod n */
318 if (mp_cmp_d (&y
, 1) != MP_EQ
)
323 /* no bases worked? */
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");
343 /* get q to be the order of the large prime subgroup */
346 mp_div (q
, &b
, q
, NULL
);
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
);
387 pprime (k
, li
, &p
, &q
);
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
);
400 /* Source: /cvs/libtom/libtommath/etc/pprime.c,v */
402 /* Date: 2006/03/31 14:18:47 */