chiark / gitweb /
catacomb/pwsafe.py: Use `binascii' for Base64 conversion.
[catacomb-python] / pock
1 #! /usr/bin/python
2 ### -*- mode: python, coding: utf-8 -*-
3 ###
4 ### Tool for generating and verifying primality certificates
5 ###
6 ### (c) 2017 Straylight/Edgeware
7 ###
8
9 ###----- Licensing notice ---------------------------------------------------
10 ###
11 ### This file is part of the Python interface to Catacomb.
12 ###
13 ### Catacomb/Python is free software; you can redistribute it and/or modify
14 ### it under the terms of the GNU General Public License as published by
15 ### the Free Software Foundation; either version 2 of the License, or
16 ### (at your option) any later version.
17 ###
18 ### Catacomb/Python is distributed in the hope that it will be useful,
19 ### but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 ### GNU General Public License for more details.
22 ###
23 ### You should have received a copy of the GNU General Public License
24 ### along with Catacomb/Python; if not, write to the Free Software Foundation,
25 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27 ###--------------------------------------------------------------------------
28 ### Imported modules.
29
30 from sys import argv, stdin, stdout, stderr
31 import os as OS
32 import itertools as I
33 import math as M
34 import optparse as OP
35
36 import catacomb as C
37
38 ###--------------------------------------------------------------------------
39 ### Utilities.
40
41 def _excval():
42   """Return the most recent exception object."""
43   return SYS.exc_info()[1]
44
45 class ExpectedError (Exception):
46   """
47   I represent an expected error, which should be reported in a friendly way.
48   """
49   pass
50
51 def prod(ff, one = 1):
52   """
53   Return ONE times the product of the elements of FF.
54
55   This is not done very efficiently.
56   """
57   return reduce(lambda prod, f: prod*f, ff, one)
58
59 def parse_label(line):
60   """
61   Split LINE at an `=' character and return the left and right halves.
62
63   The returned pieces have leading and trailing whitespace trimmed.
64   """
65   eq = line.find('=')
66   if eq < 0: raise ExpectedError('expected `LABEL = ...\'')
67   return line[:eq].strip(), line[eq + 1:].strip()
68
69 def parse_list(s, n):
70   l = s.split(',', n - 1)
71   if n is not None and len(l) != n:
72     raise ExpectedError('expected `,\'-separated list of %d items' % n)
73   return l
74
75 def conv_int(s):
76   """Convert S to a integer."""
77   try: return C.MP(s, 0)
78   except TypeError: raise ExpectedError('invalid integer `%s\'' % s)
79
80 VERBOSITY = 1
81
82 class ProgressReporter (object):
83   """
84   I keep users amused while the program looks for large prime numbers.
85
86   My main strategy is the printing of incomprehensible runes.  I can be
87   muffled by lowering by verbosity level.
88
89   Prime searches are recursive in nature.  When a new recursive level is
90   started, call `push'; and call `pop' when the level is finished.  This must
91   be done around the top level too.
92   """
93   def __init__(me):
94     """Initialize the ProgressReporter."""
95     me._level = -1
96     me._update()
97   def _update(me):
98     """
99     Update our idea of whether we're active.
100
101     We don't write inscrutable runes when inactive.  The current policy is to
102     write nothing if verbosity is zero, to write runes for the top level only
103     if verbosity is 1, and to write runes always if verbosity is higher than
104     that.
105     """
106     me._active = VERBOSITY >= 2 or (VERBOSITY == 1 and me._level == 0)
107   def push(me):
108     """Push a new search level."""
109     me._level += 1
110     me._update()
111     if me._level > 0: me.p('[')
112     else: me.p(';; ')
113   def pop(me):
114     """Pop a search level."""
115     if me._level > 0: me.p(']')
116     else: me.p('\n')
117     me._level -= 1
118     me._update()
119   def p(me, ch):
120     """Print CH as a progress rune."""
121     if me._active: stderr.write(ch); stderr.flush()
122
123 def combinations(r, v):
124   """
125   Return an iterator which yields all combinations of R elements from V.
126
127   V must be an indexable sequence.  The each combination is returned as a
128   list, containing elements from V in their original order.
129   """
130
131   ## Set up the selection vector.  C will contain the indices of the items of
132   ## V we've selected for the current combination.  At all times, C contains
133   ## a strictly increasing sequence of integers in the interval [0, N).
134   n = len(v)
135   c = range(r)
136
137   while True:
138
139     ## Yield up the current combination.
140     vv = [v[i] for i in c]
141     yield vv
142
143     ## Now advance to the next one.  Find the last index in C which we can
144     ## increment subject to the rules.  As we iterate downwards, i will
145     ## contain the index into C, and j will be the maximum acceptable value
146     ## for the corresponding item.  We'll step the last index until it
147     ## reaches the limit, and then step the next one down, resetting the last
148     ## index, and so on.
149     i, j = r, n
150     while True:
151
152       ## If i is zero here, then we've advanced everything as far as it will
153       ## go.  We're done.
154       if i == 0: return
155
156       ## Move down to the next index.
157       i -= 1; j -= 1
158
159       ## If this index isn't at its maximum value, then we've found the place
160       ## to step.
161       if c[i] != j: break
162
163     ## Step this index on by one, and set the following indices to the
164     ## immediately following values.
165     j = c[i] + 1
166     while i < r: c[i] = j; i += 1; j += 1
167
168 class ArgFetcher (object):
169   """
170   I return arguments from a list, reporting problems when they occur.
171   """
172   def __init__(me, argv, errfn):
173     """
174     Initialize, returning successive arguments from ARGV.
175
176     Errors are reported to ERRFN.
177     """
178     me._argv = argv
179     me._argc = len(argv)
180     me._errfn = errfn
181     me._i = 0
182   def arg(me, default = None, must = True):
183     """
184     Return the next argument.
185
186     If MUST is true, then report an error (to the ERRFN) if there are no more
187     arguments; otherwise, return the DEFAULT.
188     """
189     if me._i >= me._argc:
190       if must: me._errfn('missing argument')
191       return default
192     arg = me._argv[me._i]; me._i += 1
193     return arg
194   def int(me, default = None, must = True, min = None, max = None):
195     """
196     Return the next argument converted to an integer.
197
198     If MUST is true, then report an error (to the ERRFN) if there are no more
199     arguments; otherwise return the DEFAULT.  Report an error if the next
200     argument is not a valid integer, or if the integer is beyond the MIN and
201     MAX bounds.
202     """
203     arg = me.arg(default = None, must = must)
204     if arg is None: return default
205     try: arg = int(arg)
206     except ValueError: me._errfn('bad integer')
207     if (min is not None and arg < min) or (max is not None and arg > max):
208       me._errfn('out of range')
209     return arg
210
211 ###--------------------------------------------------------------------------
212 ### Sieving for small primes.
213
214 class Sieve (object):
215   """
216   I represent a collection of small primes, up to some chosen limit.
217
218   The limit is available as the `limit' attribute.  Let L be this limit;
219   then, if N < L^2 is some composite, then N has at least one prime factor
220   less than L.
221   """
222
223   ## Figure out the number of bits in a (nonnegative) primitive `int'.  We'll
224   ## use a list of these as our sieve.
225   _NBIT = 15
226   while type(1 << (_NBIT + 1)) == int: _NBIT += 1
227
228   def __init__(me, limit):
229     """
230     Initialize a sieve holding all primes below LIMIT.
231     """
232
233     ## The sieve is maintained in the `_bits' attribute.  This is a list of
234     ## integers, used as a bitmask: let 2 < n < L be an odd integer; then bit
235     ## (n - 3)/2 will be clear iff n is prime.  Let W be the value of
236     ## `_NBIT', above; then bit W i + j in the sieve is stored in bit j of
237     ## `_bits[i]'.
238
239     ## Store the limit for later inspection.
240     me.limit = limit
241
242     ## Calculate the size of sieve we'll need and initialize the bit list.
243     n = (limit - 2)/2
244     sievesz = (n + me._NBIT - 1)/me._NBIT
245     me._sievemax = sievesz*me._NBIT
246     me._bits = sievesz*[0]
247
248     ## This is standard Sieve of Eratosthenes.  For each index i: if
249     ## bit i is clear, then p = 2 i + 3 is prime, so set the bits
250     ## corresponding to each multiple of p, i.e., bits (k p - 3)/2 =
251     ## (2 k i + 3 - 3)/2 = k i for k > 1.
252     for i in xrange(me._sievemax):
253       if me._bitp(i): i += 1; continue
254       p = 2*i + 3
255       if p >= limit: break
256       for j in xrange(i + p, me._sievemax, p): me._setbit(j)
257       i += 1
258
259   def _bitp(me, i): i, j = divmod(i, me._NBIT); return (me._bits[i] >> j)&1
260   def _setbit(me, i): i, j = divmod(i, me._NBIT); me._bits[i] |= 1 << j
261
262   def smallprimes(me):
263     """
264     Return an iterator over the known small primes.
265     """
266     yield 2
267     n = 3
268     for b in me._bits:
269       for j in xrange(me._NBIT):
270         if not (b&1): yield n
271         b >>= 1; n += 2
272
273 ## We generate the sieve on demand.
274 SIEVE = None
275
276 def initsieve(sievebits):
277   """
278   Generate the sieve.
279
280   Ensure that it can be used to check the primality of numbers up to (but not
281   including) 2^SIEVEBITS.
282   """
283   global SIEVE
284   if SIEVE is not None: raise ValueError('sieve already defined')
285   if sievebits < 6: sievebits = 6
286   SIEVE = Sieve(1 << (sievebits + 1)/2)
287
288 ###--------------------------------------------------------------------------
289 ### Primality checking.
290
291 def small_test(p):
292   """
293   Check that P is a small prime.
294
295   If not, raise an `ExpectedError'.  The `SIEVE' variable must have been
296   initialized.
297   """
298   if p < 2: raise ExpectedError('%d too small' % p)
299   if SIEVE.limit*SIEVE.limit < p:
300     raise ExpectedError('%d too large for small prime' % p)
301   for q in SIEVE.smallprimes():
302     if q*q > p: return
303     if p%q == 0: raise ExpectedError('%d divides %d' % (q, p))
304
305 def pock_test(p, a, qq):
306   """
307   Check that P is prime using Pocklington's criterion.
308
309   If not, raise an `ExpectedError'.
310
311   Let Q be the product of the elements of the sequence QQ.  The test works as
312   follows.  Suppose p is the smallest prime factor of P.  If A^{P-1} /== 1
313   (mod P) then P is certainly composite (Fermat's test); otherwise, we have
314   established that the order of A in (Z/pZ)^* divides P - 1.  Next, let t =
315   A^{(P-1)/q} for some prime factor q of Q, and let g = gcd(t - 1, P).  If g
316   = P then the proof is inconclusive; if 1 < g < P then g is a nontrivial
317   factor of P, so P is composite; otherwise, t has order q in (Z/pZ)^*, so
318   (Z/pZ)^* contains a subgroup of size q, and therefore q divides p - 1.  If
319   QQ is a sequence of distinct primes, and the preceding criterion holds for
320   all q in QQ, then Q divides p - 1.  If Q^2 < P then the proof is
321   inconclusive; otherwise, let p' be any prime dividing P/p.  Then p' >= p >
322   Q, so p p' > Q^2 > P; but p p' divides P, so this is a contradiction.
323   Therefore P/p has no prime factors, and P is prime.
324   """
325
326   ## We don't actually need the distinctness criterion.  Suppose that q^e
327   ## divides Q.  Then gcd(t - 1, P) = 1 implies that A^{(P-1)/q^{e-1}} has
328   ## order q^e in (Z/pZ)^*, which accounts for the multiplicity.
329
330   Q = prod(qq)
331   if p < 2: raise ExpectedError('%d too small' % p)
332   if Q*Q <= p:
333     raise ExpectedError('too few Pocklington factors for %d' % p)
334   if pow(a, p - 1, p) != 1:
335     raise ExpectedError('%d is Fermat witness for %d' % (a, p))
336   for q in qq:
337     if Q%(q*q) == 0:
338       raise ExpectedError('duplicate Pocklington factor %d for %d' % (q, p))
339     g = p.gcd(pow(a, (p - 1)/q, p) - 1)
340     if g == p:
341       raise ExpectedError('%d order not multiple of %d mod %d' % (a, q, p))
342     elif g != 1:
343       raise ExpectedError('%d divides %d' % (g, p))
344
345 def ecpp_test(p, a, b, x, y, qq):
346   """
347   Check that P is prime using Goldwasser and Kilian's ECPP method.
348
349   If not, raise an `ExpectedError'.
350
351   Let Q be the product of the elements of the sequence QQ.  Suppose p is the
352   smallest prime factor of P.  Let g = gcd(4 A^3 + 27 B^2, P).  If g = P then
353   the test is inconclusive; otherwise, if g /= 1 then g is a nontrivial
354   factor of P.  Define E(GF(p)) = { (x, y) | y^2 = x^3 + A x + B } U { inf }
355   to be the elliptic curve over p with short-Weierstraß coefficients A and B;
356   we have just checked that this curve is not singular.  If R = (X, Y) is not
357   a point on this curve, then the test is inconclusive.  If Q R is not the
358   point at infinity, then the test fails; otherwise we deduce that P has
359   Q-torsion in E.  Let S = (Q/q) R for some prime factor q of Q.  If S is the
360   point at infinity then the test is inconclusive; otherwise, q divides the
361   order of S in E.  If QQ is a sequence of distinct primes, and the preceding
362   criterion holds for all q in QQ, then Q divides the order of S.  Therefore
363   #E(p) >= Q.  If Q <= (qrrt(P) + 1)^2 then the test is inconclusive.
364   Otherwise, Hasse's theorem tells us that |p + 1 - #E(p)| <= 2 sqrt(p);
365   hence we must have p + 1 + 2 sqrt(p) = (sqrt(p) + 1)^2 >= #E(p) >= Q >
366   (qrrt(P) + 1)^2; so sqrt(p) + 1 > qrrt(P) + 1, i.e., p^2 > P.  As for
367   Pocklington above, if p' is any prime factor of P/p, then p p' >= p^2 > P,
368   which is a contradiction, and we conclude that P is prime.
369   """
370
371   ## This isn't going to work if gcd(P, 6) /= 1: we're going to use the
372   ## large-characteristic addition formulae.
373   g = p.gcd(6)
374   if g != 1: raise ExpectedError('%d divides %d' % (g, p))
375
376   ## We want to check that Q > (qrrt(P) + 1)^2 iff sqrt(Q) > qrrt(P) + 1; but
377   ## calculating square roots is not enjoyable (partly because we have to
378   ## deal with the imprecision).  Fortunately, some algebra will help: the
379   ## condition holds iff qrrt(P) < sqrt(Q) - 1 iff P < Q^2 - 4 Q sqrt(Q) +
380   ## 6 Q - 4 sqrt(Q) + 1 = Q (Q + 6) + 1 - 4 sqrt(Q) (Q + 1) iff Q (Q + 6) -
381   ## P + 1 > 4 sqrt(Q) (Q + 1) iff (Q (Q + 6) - P + 1)^2 > 16 Q (Q + 1)^2
382   Q = prod(qq)
383   t, u = Q*(Q + 6) - p + 1, 4*(Q + 1)
384   if t*t <= Q*u*u: raise ExpectedError('too few subgroups for ECPP')
385
386   ## Construct the curve.
387   E = C.PrimeField(p).ec(a, b) # careful: may not be a prime!
388
389   ## Find the base point.
390   R = E(x, y)
391   if not R.oncurvep():
392     raise ExpectedError('(%d, %d) is not on the curve' % (x, y))
393
394   ## Check that it has Q-torsion.
395   if Q*R: raise ExpectedError('(%d, %d) not a %d-torsion point' % (x, y, Q))
396
397   ## Now check the individual factors.
398   for q in qq:
399     if Q%(q*q) == 0:
400       raise ExpectedError('duplicate ECPP factor %d for %d' % (q, p))
401     S = (Q/q)*R
402     if not S:
403       raise ExpectedError('(%d, %d) order not a multiple of %d' % (x, y, q))
404     g = p.gcd(S._z)
405     if g != 1:
406       raise ExpectedError('%d divides %d' % (g, p))
407
408 ###--------------------------------------------------------------------------
409 ### Proof steps and proofs.
410
411 class BaseStep (object):
412   """
413   I'm a step in a primality proof.
414
415   I assert that a particular number is prime, and can check this.
416
417   This class provides basic protocol for proof steps, mostly to do with
418   handling labels.
419
420   The step's label is kept in its `label' attribute.  It can be set by the
421   constructor, and is `None' by default.  Users can modify this attribute if
422   they like.  Labels beginning `$' are assumed to be internal and
423   uninteresting; other labels cause `check' lines to be written to the output
424   listing the actual number of interest.
425
426   Protocol that proof steps should provide:
427
428   label         A string labelling the proof step and the associated prime
429                 number.
430
431   p             The prime number which this step proves to be prime.
432
433   check()       Check that the proof step is actually correct, assuming that
434                 any previous steps have already been verified.
435
436   out(FILE)     Write an appropriate encoding of the proof step to the output
437                 FILE.
438   """
439   def __init__(me, label = None, *arg, **kw):
440     """Initialize a proof step, setting a default label if necessary."""
441     super(BaseStep, me).__init__(*arg, **kw)
442     me.label = label
443   def out(me, file):
444     """
445     Write the proof step to an output FILE.
446
447     Subclasses must implement a method `_out' which actually does the work.
448     Here, we write a `check' line to verify that the proof actually applies
449     to the number we wanted, if the label says that this is an interesting
450     step.
451     """
452     me._out(file)
453     if me.label is not None and not me.label.startswith('$'):
454       file.write('check %s, %d, %d\n' % (me.label, me.p.nbits, me.p))
455
456 class SmallStep (BaseStep):
457   """
458   I represent a claim that a number is a small prime.
459
460   Such claims act as the base cases in a complicated primality proof.  When
461   verifying, the claim is checked by trial division using a collection of
462   known small primes.
463   """
464   def __init__(me, pp, p, *arg, **kw):
465     """
466     Initialize a small-prime step.
467
468     PP is the overall PrimeProof object of which this is a step; P is the
469     small number whose primality is asserted.
470     """
471     super(SmallStep, me).__init__(*arg, **kw)
472     me.p = p
473   def check(me):
474     """Check that the number is indeed a small prime."""
475     return small_test(me.p)
476   def _out(me, file):
477     """Write a small-prime step to the FILE."""
478     file.write('small %s = %d\n' % (me.label, me.p))
479   def __repr__(me): return 'SmallStep(%d)' % (me.p)
480   @classmethod
481   def parse(cls, pp, line):
482     """
483     Parse a small-prime step from a LINE in a proof file.
484
485     SMALL-STEP ::= `small' LABEL `=' P
486
487     PP is a PrimeProof object holding the results from the previous steps.
488     """
489     if SIEVE is None: raise ExpectedError('missing `sievebits\' line')
490     label, p = parse_label(line)
491     return cls(pp, conv_int(p), label = label)
492
493 class PockStep (BaseStep):
494   """
495   I represent a Pocklington certificate for a number.
496
497   The number is not explicitly represented in a proof file.  See `pock_test'
498   for the underlying mathematics.
499   """
500   def __init__(me, pp, a, R, qqi, *arg, **kw):
501     """
502     Inititialize a Pocklington step.
503
504     PP is the overall PrimeProof object of which this is a step; A is the
505     generator of a substantial subgroup of units; R is a cofactor; and QQI is
506     a sequence of labels for previous proof steps.  If Q is the product of
507     the primes listed in QQI, then the number whose primality is asserted is
508     2 Q R + 1.
509     """
510     super(PockStep, me).__init__(*arg, **kw)
511     me._a = a
512     me._R = R
513     me._qqi = qqi
514     me._qq = [pp.get_step(qi).p for qi in qqi]
515     me.p = prod(me._qq, 2*R) + 1
516   def check(me):
517     """Verify a proof step based on Pocklington's theorem."""
518     return pock_test(me.p, me._a, me._qq)
519   def _out(me, file):
520     """Write a Pocklington step to the FILE."""
521     file.write('pock %s = %d, %d, [%s]\n' % \
522                  (me.label, me._a,
523                   me._R, ', '.join('%s' % qi for qi in me._qqi)))
524   def __repr__(me): return 'PockStep(%d, %d, %s)' % (me._a, me._R, me._qqi)
525   @classmethod
526   def parse(cls, pp, line):
527     """
528     Parse a Pocklington step from a LINE in a proof file.
529
530     POCK-STEP ::= `pock' LABEL `=' A `,' R `,' `[' Q-LIST `]'
531     Q-LIST ::= Q [`,' Q-LIST]
532
533     PP is a PrimeProof object holding the results from the previous steps.
534     """
535     label, rest = parse_label(line)
536     a, R, qq = parse_list(rest, 3)
537     qq = qq.strip()
538     if not qq.startswith('[') or not qq.endswith(']'):
539       raise ExpectedError('missing `[...]\' around Pocklington factors')
540     return cls(pp, conv_int(a), conv_int(R),
541                [q.strip() for q in qq[1:-1].split(',')], label = label)
542
543 class ECPPStep (BaseStep):
544   """
545   I represent a Goldwasser--Kilian ECPP certificate for a number.
546   """
547   def __init__(me, pp, p, a, b, x, y, qqi, *arg, **kw):
548     """
549     Inititialize an ECPP step.
550
551     PP is the overall PrimeProof object of which this is a step; P is the
552     number whose primality is asserted; A and B are the short Weierstraß
553     curve coefficients; X and Y are the base point coordinates; and QQI is a
554     sequence of labels for previous proof steps.
555     """
556     super(ECPPStep, me).__init__(*arg, **kw)
557     me._a, me._b = a, b
558     me._x, me._y = x, y
559     me._qqi = qqi
560     me._qq = [pp.get_step(qi).p for qi in qqi]
561     me.p = p
562   def check(me):
563     """Verify a proof step based on Goldwasser and Kilian's theorem."""
564     return ecpp_test(me.p, me._a, me._b, me._x, me._y, me._qq)
565   def _out(me, file):
566     """Write an ECPP step to the FILE."""
567     file.write('ecpp %s = %d, %d, %d, %d, %d, [%s]\n' % \
568                  (me.label, me.p, me._a, me._b, me._x, me._y,
569                   ', '.join('%s' % qi for qi in me._qqi)))
570   def __repr__(me):
571     return 'ECPPstep(%d, %d, %d, %d, %d, %s)' % \
572         (me.p, me._a, me._b, me._x, me._y, me._qqi)
573   @classmethod
574   def parse(cls, pp, line):
575     """
576     Parse an ECPP step from a LINE in a proof file.
577
578     ECPP-STEP ::= `ecpp' LABEL `=' P `,' A `,' B `,' X `,' Y `,'
579         `[' Q-LIST `]'
580     Q-LIST ::= Q [`,' Q-LIST]
581
582     PP is a PrimeProof object holding the results from the previous steps.
583     """
584     label, rest = parse_label(line)
585     p, a, b, x, y, qq = parse_list(rest, 6)
586     qq = qq.strip()
587     if not qq.startswith('[') or not qq.endswith(']'):
588       raise ExpectedError('missing `[...]\' around ECPP factors')
589     return cls(pp, conv_int(p), conv_int(a), conv_int(b),
590                conv_int(x), conv_int(y),
591                [q.strip() for q in qq[1:-1].split(',')], label = label)
592
593 def check(pp, line):
594   """
595   Handle a `check' line in a proof file.
596
597   CHECK ::= `check' LABEL, B, N
598
599   Verify that the proof step with the given LABEL asserts the primality of
600   the integer N, and that 2^{B-1} <= N < 2^B.
601   """
602   label, nb, p = parse_list(line, 3)
603   label, nb, p = label.strip(), conv_int(nb), conv_int(p)
604   pi = pp.get_step(label).p
605   if pi != p:
606     raise ExpectedError('check failed: %s = %d /= %d' % (label, pi, p))
607   if p.nbits != nb:
608     raise ExpectedError('check failed: nbits(%s) = %d /= %d' % \
609                         (label, p.nbits, nb))
610   if VERBOSITY: print(';; %s = %d [%d]' % (label, p, nb))
611
612 def setsievebits(pp, line):
613   """
614   Handle a `sievebits' line in a proof file.
615
616   SIEVEBITS ::= `sievebits' N
617
618   Ensure that the verifier is willing to accept small primes up to 2^N.
619   """
620   initsieve(int(line))
621
622 class PrimeProof (object):
623   """
624   I represent a proof of primality for one or more numbers.
625
626   I can encode my proof as a line-oriented text file, in a simple format, and
627   read such a proof back to check it.
628   """
629
630   ## A table to dispatch on keywords read from a file.
631   STEPMAP = { 'small': SmallStep.parse,
632               'pock': PockStep.parse,
633               'ecpp': ECPPStep.parse,
634               'sievebits': setsievebits,
635               'check': check }
636
637   def __init__(me):
638     """
639     Initialize a proof object.
640     """
641     me._steps = {}                      # Maps labels to steps.
642     me._stepseq = []                    # Sequence of labels, in order.
643     me._pmap = {}                       # Maps primes to steps.
644     me._i = 0
645
646   def addstep(me, step):
647     """
648     Add a new STEP to the proof.
649
650     The STEP may have a label already.  If not, a new internal label is
651     chosen.  The proof step is checked before being added to the proof.  The
652     label is returned.
653     """
654
655     ## If there's already a step for this prime, and the new step doesn't
656     ## have a label, then return the old one instead.
657     if step.label is None:
658       try: return me._pmap[step.p]
659       except KeyError: pass
660
661     ## Make sure the step is actually correct.
662     step.check()
663
664     ## Generate a label if the step doesn't have one already.
665     if step.label is None: step.label = '$t%d' % me._i; me._i += 1
666
667     ## If the label is already taken then we have a problem.
668     if step.label in me._steps:
669       raise ExpectedError('duplicate label `%s\'' % step.label)
670
671     ## Store the proof step.
672     me._pmap[step.p] = step.label
673     me._steps[step.label] = step
674     me._stepseq.append(step.label)
675     return step.label
676
677   def get_step(me, label):
678     """
679     Check that LABEL labels a known step, and return that step.
680     """
681     try: return me._steps[label]
682     except KeyError: raise ExpectedError('unknown label `%s\'' % label)
683
684   def write(me, file):
685     """
686     Write the proof to the given FILE.
687     """
688
689     ## Prefix the main steps with a `sievebits' line.
690     file.write('sievebits %d\n' % (2*(SIEVE.limit.bit_length() - 1)))
691
692     ## Write the steps out one by one.
693     for label in me._stepseq: me._steps[label].out(file)
694
695   def read(me, file):
696     """
697     Read a proof from a given FILE.
698
699     FILE ::= {STEP | CHECK | SIEVEBITS} [FILE]
700     STEP ::= SMALL-STEP | POCK-STEP
701
702     Comments (beginning `;') and blank lines are ignored.  Other lines begin
703     with a keyword.
704     """
705     lastp = None
706     for lno, line in enumerate(file, 1):
707       line = line.strip()
708       if line.startswith(';'): continue
709       ww = line.split(None, 1)
710       if not ww: continue
711       w = ww[0]
712       if len(ww) > 1: tail = ww[1]
713       else: tail = ''
714       try:
715         try: op = me.STEPMAP[w]
716         except KeyError:
717           raise ExpectedError('unrecognized keyword `%s\'' % w)
718         step = op(me, tail)
719         if step is not None:
720           me.addstep(step)
721           lastp = step.p
722       except ExpectedError:
723         raise ExpectedError('%s:%d: %s' %
724                             (file.name, lno, _excval().message))
725     return lastp
726
727 ###--------------------------------------------------------------------------
728 ### Finding provable primes.
729
730 class BasePrime (object):
731   """
732   I represent a prime number which has been found and can be proven.
733
734   This object can eventually be turned into a sequence of proof steps and
735   added to a PrimeProof.  This isn't done immediately, because some
736   prime-search strategies want to build a pool of provable primes and will
737   then select some subset of them to actually construct the number of final
738   interest.  This way, we avoid cluttering the output proof with proofs of
739   uninteresting numbers.
740
741   Protocol required.
742
743   p             The prime number in question.
744
745   label(LABEL)  Associate LABEL with this prime, and the corresponding proof
746                 step.  A label can be set in the constructor, or later using
747                 this method.
748
749   register(PP)  Register the prime with a PrimeProof, adding any necessary
750                 proof steps.  Returns the label of the proof step for this
751                 number.
752
753   _mkstep(PP, **KW)
754                 Return a proof step for this prime.
755   """
756   def __init__(me, label = None, *args, **kw):
757     """Initialize a provable prime number object."""
758     super(BasePrime, me).__init__(*args, **kw)
759     me._index = me._pp = None
760     me._label = label
761   def label(me, label):
762     """Set this number's LABEL."""
763     me._label = label
764   def register(me, pp):
765     """
766     Register the prime's proof steps with PrimeProof PP.
767
768     Return the final step's label.
769     """
770     if me._pp is not None:
771       assert me._pp == pp
772     else:
773       me._pp = pp
774       me._index = pp.addstep(me._mkstep(pp, label = me._label))
775       ##try: me._index = pp.addstep(me._mkstep(pp, label = me._label))
776       ##except: raise RuntimeError('generated proof failed sanity check')
777     return me._index
778
779 class SmallPrime (BasePrime):
780   """I represent a prime small enough to be checked in isolation."""
781   def __init__(me, p, *args, **kw):
782     super(SmallPrime, me).__init__(*args, **kw)
783     me.p = p
784   def _mkstep(me, pp, **kw):
785     return SmallStep(pp, me.p, **kw)
786
787 class PockPrime (BasePrime):
788   """I represent a prime proven using Pocklington's theorem."""
789   def __init__(me, p, a, qq, *args, **kw):
790     super(PockPrime, me).__init__(*args, **kw)
791     me.p = p
792     me._a = a
793     me._qq = qq
794   def _mkstep(me, pp, **kw):
795     return PockStep(pp, me._a, (me.p - 1)/prod((q.p for q in me._qq), 2),
796                     [q.register(pp) for q in me._qq], **kw)
797
798 def gen_small(nbits, label = None, p = None):
799   """
800   Return a new small prime.
801
802   The prime will be exactly NBITS bits long.  The proof step will have the
803   given LABEL attached.  Report progress to the ProgressReporter P.
804   """
805   while True:
806
807     ## Pick a random NBITS-bit number.
808     n = C.rand.mp(nbits, 1)
809     assert n.nbits == nbits
810
811     ## If it's probably prime, then check it against the small primes we
812     ## know.  If it passes then we're done.  Otherwise, try again.
813     if n.primep():
814       for q in SIEVE.smallprimes():
815         if q*q > n: return SmallPrime(n, label = label)
816         if n%q == 0: break
817
818 def gen_pock(nbits, nsubbits = 0, label = None, p = ProgressReporter()):
819   """
820   Return a new prime provable using Pocklington's theorem.
821
822   The prime N will be exactly NBITS long, of the form N = 2 Q R + 1.  If
823   NSUBBITS is nonzero, then each prime factor of Q will be NSUBBITS bits
824   long; otherwise a suitable default will be chosen.  The proof step will
825   have the given LABEL attached.  Report progress to the ProgressReporter P.
826
827   The prime numbers this function returns are a long way from being uniformly
828   distributed.
829   """
830
831   ## Pick a suitable value for NSUBBITS if we don't have one.
832   if not nsubbits:
833
834     ## This is remarkably tricky.  Picking about 1/3 sqrt(NBITS) factors
835     ## seems about right for large numbers, but there's serious trouble
836     ## lurking for small sizes.
837     nsubbits = int(3*M.sqrt(nbits))
838     if nbits < nsubbits + 3: nsubbits = nbits//2 + 1
839     if nbits == 2*nsubbits: nsubbits += 1
840
841   ## Figure out how many subgroups we'll need.
842   npiece = ((nbits + 1)//2 + nsubbits - 1)//nsubbits
843   p.push()
844
845   ## Keep searching...
846   while True:
847
848     ## Come up with a collection of known prime factors.
849     p.p('!'); qq = [gen(nsubbits, p = p) for i in xrange(npiece)]
850     Q = prod(q.p for q in qq)
851
852     ## Come up with bounds on the cofactor.  If we're to have N = 2 Q R + 1,
853     ## and 2^{B-1} <= N < 2^B, then we must have 2^{B-2}/Q <= R < 2^{B-1}/Q.
854     Rbase = (C.MP(0).setbit(nbits - 2) + Q - 1)//Q
855     Rwd = C.MP(0).setbit(nbits - 2)//Q
856
857     ## Probe the available space of cofactors.  If the space is kind of
858     ## narrow, then we want to give up quickly if we're not finding anything
859     ## suitable.
860     step = 0
861     while step < Rwd:
862       step += 1
863
864       ## Pick a random cofactor and examine the number we ended up with.
865       ## Make sure it really does have the length we expect.
866       R = C.rand.range(Rwd) + Rbase
867       n = 2*Q*R + 1
868       assert n.nbits == nbits
869
870       ## As a complication, if NPIECE is 1, it's just about possible that Q^2
871       ## <= n, in which case this isn't going to work.
872       if Q*Q < n: continue
873
874       ## If n has small factors, then pick another cofactor.
875       if C.PrimeFilter.smallfactor(n) == C.PGEN_FAIL: continue
876
877       ## Work through the small primes to find a suitable generator.  The
878       ## value 2 is almost always acceptable, so don't try too hard here.
879       for a in I.islice(SIEVE.smallprimes(), 16):
880
881         ## First, try the Fermat test.  If that fails, then n is definitely
882         ## composite.
883         if pow(a, n - 1, n) != 1: p.p('.'); break
884         p.p('*')
885
886         ## Work through the subgroup orders, checking that suitable powers of
887         ## a generate the necessary subgroups.
888         for q in qq:
889           if n.gcd(pow(a, (n - 1)/q.p, n) - 1) != 1:
890             p.p('@'); ok = False; break
891         else:
892           ok = True
893
894         ## we're all good.
895         if ok: p.pop(); return PockPrime(n, a, qq, label = label)
896
897 def gen(nbits, label = None, p = ProgressReporter()):
898   """
899   Generate a prime number with NBITS bits.
900
901   Give it the LABEL, and report progress to P.
902   """
903   if SIEVE.limit >> (nbits + 1)/2: g = gen_small
904   else: g = gen_pock
905   return g(nbits, label = label, p = p)
906
907 def gen_limlee(nbits, nsubbits,
908                label = None, qlfmt = None, p = ProgressReporter()):
909   """
910   Generate a Lim--Lee prime with NBITS bits.
911
912   Let p be the prime.  Then we'll have p = 2 q_0 q_1 ... q_k, with all q_i at
913   least NSUBBITS bits long, and all but q_k exactly that long.
914
915   The prime will be given the LABEL; progress is reported to P.  The factors
916   q_i will be labelled by filling in the `printf'-style format string QLFMT
917   with the argument i.
918   """
919
920   ## Figure out how many factors (p - 1)/2 will have.
921   npiece = nbits//nsubbits
922   if npiece < 2: raise ExpectedError('too few pieces')
923
924   ## Decide how big to make the pool of factors.
925   poolsz = max(3*npiece + 5, 25) # Heuristic from GnuPG
926
927   ## Prepare for the main loop.
928   disp = nstep = 0
929   qbig = None
930   p.push()
931
932   ## Try to make a prime.
933   while True:
934     p.p('!')
935
936     ## Construct a pool of NSUBBITS-size primes.  There's a problem with very
937     ## small sizes: we might not be able to build a pool of distinct primes.
938     pool = []; qmap = {}
939     for i in xrange(poolsz):
940       for j in xrange(64):
941         q = gen(nsubbits, p = p)
942         if q.p not in qmap: break
943       else:
944         raise ExpectedError('insufficient diversity')
945       qmap[q.p] = q
946       pool.append(q)
947
948     ## Work through combinations of factors from the pool.
949     for qq in combinations(npiece - 1, pool):
950
951       ## Construct the product of the selected factors.
952       qsmall = prod(q.p for q in qq)
953
954       ## Maybe we'll need to replace the large factor.  Try not to do this
955       ## too often.  DISP measures the large factor's performance at
956       ## producing candidates with the right length.  If it looks bad then
957       ## we'll have to replace it.
958       if 3*disp*disp > nstep*nstep:
959         qbig = None
960         if disp < 0: p.p('<')
961         else: p.p('>')
962
963       ## If we don't have a large factor, then make one.
964       if qbig is None:
965         qbig = gen(nbits - qsmall.nbits, p = p)
966         disp = 0; nstep = 0
967
968       ## We have a candidate.  Calculate it and make sure it has the right
969       ## length.
970       n = 2*qsmall*qbig.p + 1
971       nstep += 1
972       if n.nbits < nbits: disp -= 1
973       elif n.nbits > nbits: disp += 1
974       elif C.PrimeFilter.smallfactor(n) == C.PGEN_FAIL: pass
975       else:
976
977         ## The candidate has passed the small-primes test.  Now check it
978         ## against Pocklington.
979         for a in I.islice(SIEVE.smallprimes(), 16):
980
981           ## Fermat test.
982           if pow(a, n - 1, n) != 1: p.p('.'); break
983           p.p('*')
984
985           ## Find a generator of a sufficiently large subgroup.
986           if n.gcd(pow(a, (n - 1)/qbig.p, n) - 1) != 1: p.p('@'); continue
987           ok = True
988           for q in qq:
989             if n.gcd(pow(a, (n - 1)/q.p, n) - 1) != 1:
990               p.p('@'); ok = False; break
991
992           ## We're done.
993           if ok:
994
995             ## Label the factors.
996             qq.append(qbig)
997             if qlfmt:
998               for i, q in enumerate(qq): q.label(qlfmt % i)
999
1000             ## Return the number we found.
1001             p.pop(); return PockPrime(n, a, qq, label = label)
1002
1003 ###--------------------------------------------------------------------------
1004 ### Main program.
1005
1006 def __main__():
1007   global VERBOSITY
1008
1009   ## Prepare an option parser.
1010   op = OP.OptionParser(
1011     usage = '''\
1012 pock [-qv] [-s SIEVEBITS] CMD ARGS...
1013         gen NBITS
1014         ll NBITS NSUBBITS
1015         check [FILE]''',
1016     description = 'Generate or verify certified prime numbers.')
1017   op.add_option('-v', '--verbose', dest = 'verbosity',
1018                 action = 'count', default = 1,
1019                 help = 'print mysterious runes while looking for prime numbers')
1020   op.add_option('-q', '--quiet', dest = 'quietude',
1021                 action = 'count', default = 0,
1022                 help = 'be quiet while looking for prime numbers')
1023   op.add_option('-s', '--sievebits', dest = 'sievebits',
1024                 type = 'int', default = 32,
1025                 help = 'size (in bits) of largest small prime')
1026   opts, argv = op.parse_args()
1027   VERBOSITY = opts.verbosity - opts.quietude
1028   p = ProgressReporter()
1029   a = ArgFetcher(argv, op.error)
1030
1031   ## Process arguments and do what the user asked.
1032   w = a.arg()
1033
1034   if w == 'gen':
1035     ## Generate a prime with no special structure.
1036     initsieve(opts.sievebits)
1037     nbits = a.int(min = 4)
1038     pp = PrimeProof()
1039     p = gen(nbits, 'p', p = p)
1040     p.register(pp)
1041     pp.write(stdout)
1042
1043   elif w == 'll':
1044     ## Generate a Lim--Lee prime.
1045     initsieve(opts.sievebits)
1046     nbits = a.int(min = 4)
1047     nsubbits = a.int(min = 4, max = nbits)
1048     pp = PrimeProof()
1049     p = gen_limlee(nbits, nsubbits, 'p', 'q_%d', p = p)
1050     p.register(pp)
1051     pp.write(stdout)
1052
1053   elif w == 'check':
1054     ## Check an existing certificate.
1055     fn = a.arg(default = '-', must = False)
1056     if fn == '-': f = stdin
1057     else: f = open(fn, 'r')
1058     pp = PrimeProof()
1059     p = pp.read(f)
1060
1061   else:
1062     raise ExpectedError("unknown command `%s'" % w)
1063
1064 if __name__ == '__main__':
1065   prog = OS.path.basename(argv[0])
1066   try: __main__()
1067   except ExpectedError: exit('%s: %s' % (prog, _excval().message))
1068   except IOError: exit('%s: %s' % (prog, _excval()))
1069
1070 ###----- That's all, folks --------------------------------------------------