source: git/Singular/LIB/crypto.lib @ 8e48d49

spielwiese
Last change on this file since 8e48d49 was 8e48d49, checked in by Hans Schoenemann <hannes@…>, 11 years ago
fix: typo in doc.
  • Property mode set to 100644
File size: 53.1 KB
Line 
1///////////////////////////////////////////////////////////////////////////////
2version="$Id$";
3category="Teaching";
4info="
5LIBRARY:  crypto.lib     Procedures for teaching cryptography
6AUTHOR:                  Gerhard Pfister, pfister@mathematik.uni-kl.de
7
8OVERVIEW:
9     The library contains procedures to compute the discrete logarithm,
10      primality-tests, factorization included elliptic curves.
11      The library is intended to be used for teaching purposes but not
12      for serious computations. Sufficiently high printlevel allows to
13      control each step, thus illustrating the algorithms at work.
14
15
16PROCEDURES:
17 decimal(s);                number corresponding to the hexadecimal number s
18 exgcdN(a,n)                compute s,t,d such that d=gcd(a,n)=s*a+t*n
19 eexgcdN(L)                 T with sum_i L[i]*T[i]=T[n+1]=gcd(L[1],...,L[n])
20 gcdN(a,b)                  compute gcd(a,b)
21 lcmN(a,b)                  compute lcm(a,b)
22 powerN(m,d,n)              compute m^d mod n
23 chineseRem(T,L)            compute x such that x = T[i] mod L[i]
24 Jacobi(a,n)                the generalized Legendre symbol of a and n
25 primList(n)                the list of all primes <=n
26 primL(q)                   first primes p_1,...,p_r such that q<p_1*...*p_r
27 intPart(x)                 the integral part of a rational number
28 intRoot(m)                 the integral part of the square root of m
29 squareRoot(a,p)            the square root of a in Z/p, p prime
30 solutionsMod2(M)           basis solutions of Mx=0 over Z/2
31 powerX(q,i,I)              q-th power of the i-th variable modulo I
32 babyGiant(b,y,p)           discrete logarithm x: b^x=y mod p
33 rho(b,y,p)                 discrete logarithm x: b^x=y mod p
34 MillerRabin(n,k)           probabilistic primaly-test of Miller-Rabin
35 SolowayStrassen(n,k)       probabilistic primaly-test of Soloway-Strassen
36 PocklingtonLehmer(N,[])    primaly-test of Pocklington-Lehmer
37 PollardRho(n,k,a,[])       Pollard's rho factorization
38 pFactor(n,B,P)             Pollard's p-factorization
39 quadraticSieve(n,c,B,k)    quadratic sieve factorization
40 isOnCurve(N,a,b,P)         P is on the curve y^2z=x^3+a*xz^2+b*z^3  over Z/N
41 ellipticAdd(N,a,b,P,Q)     P+Q, addition on elliptic curves
42 ellipticMult(N,a,b,P,k)    k*P on elliptic curves
43 ellipticRandomCurve(N)     generates y^2z=x^3+a*xz^2+b*z^3  over Z/N randomly
44 ellipticRandomPoint(N,a,b) random point on y^2z=x^3+a*xz^2+b*z^3  over Z/N
45 countPoints(N,a,b)         number of points of y^2=x^3+a*x+b  over Z/N
46 ellipticAllPoints(N,a,b)   points of y^2=x^3+a*x+b  over Z/N
47 ShanksMestre(q,a,b,[])     number of points of y^2=x^3+a*x+b  over Z/N
48 Schoof(N,a,b)              number of points of y^2=x^3+a*x+b  over Z/N
49 generateG(a,b,m)           m-th division polynomial of y^2=x^3+a*x+b  over Z/N
50 factorLenstraECM(N,S,B,[]) Lenstra's factorization
51 ECPP(N)                    primaly-test of Goldwasser-Kilian
52
53              [parameters in square brackets are optional]
54";
55
56LIB "poly.lib";
57
58///////////////////////////////////////////////////////////////////////////////
59
60
61//=============================================================================
62//=========================== basic prozedures ================================
63//=============================================================================
64
65proc decimal(string s)
66"USAGE:  decimal(s); s = string
67RETURN: the (decimal) number corresponding to the hexadecimal number s
68EXAMPLE:example decimal; shows an example
69"
70{
71   int n=size(s);
72   int i;
73   bigint k;
74   bigint t=16;
75   bigint m=0;
76   for(i=1;i<=n;i++)
77   {
78      if(s[i]=="1"){k=1;}
79      if(s[i]=="2"){k=2;}
80      if(s[i]=="3"){k=3;}
81      if(s[i]=="4"){k=4;}
82      if(s[i]=="5"){k=5;}
83      if(s[i]=="6"){k=6;}
84      if(s[i]=="7"){k=7;}
85      if(s[i]=="8"){k=8;}
86      if(s[i]=="9"){k=9;}
87      if(s[i]=="a"){k=10;}
88      if(s[i]=="b"){k=11;}
89      if(s[i]=="c"){k=12;}
90      if(s[i]=="d"){k=13;}
91      if(s[i]=="e"){k=14;}
92      if(s[i]=="f"){k=15;}
93      m=m*t+k;
94   }
95   return(m);
96}
97example
98{ "EXAMPLE:"; echo = 2;
99   string s  ="8edfe37dae96cfd2466d77d3884d4196";
100   decimal(s);
101}
102
103proc exgcdN(number a, number n)
104"USAGE:  exgcdN(a,n);
105RETURN: a list s,t,d of numbers satisfying d=gcd(a,n)=s*a+t*n
106EXAMPLE:example exgcdN; shows an example
107"
108{
109  number x=a mod n;
110  if(x==0){return(list(0,1,n))}
111  if (x<0) { x=x+n;}
112  list l=exgcdN(n,x);
113  return(list(l[2],l[1]-(a-x)*l[2]/n,l[3]))
114}
115example
116{ "EXAMPLE:"; echo = 2;
117   ring R = 0,x,dp;
118   exgcdN(24,15);
119}
120
121proc eexgcdN(list L)
122"USAGE:  eexgcdN(L);
123RETURN: list T such that sum_i L[i]*T[i]=T[n+1]=gcd(L[1],...,L[n])
124EXAMPLE:example eexgcdN; shows an example
125"
126{
127   if(size(L)==2){return(exgcdN(L[1],L[2]));}
128   number p=L[size(L)];
129   L=delete(L,size(L));
130   list T=eexgcdN(L);
131   list S=exgcdN(T[size(T)],p);
132   int i;
133   for(i=1;i<=size(T)-1;i++)
134   {
135      T[i]=T[i]*S[1];
136   }
137   p=T[size(T)];
138   T[size(T)]=S[2];
139   T[size(T)+1]=S[3];
140   return(T);
141}
142example
143{ "EXAMPLE:"; echo = 2;
144   ring R = 0,x,dp;
145   eexgcdN(list(24,15,21));
146}
147
148proc gcdN(number a, number b)
149"USAGE:  gcdN(a,b);
150RETURN: gcd(a,b)
151EXAMPLE:example gcdN; shows an example
152"
153{
154   //if((a mod b)==0){return(b)}
155   //return(gcdN(b,a mod b));
156   return(gcd(a,b));
157}
158example
159{ "EXAMPLE:"; echo = 2;
160   ring R = 0,x,dp;
161   gcdN(24,15);
162}
163
164proc lcmN(number a, number b)
165"USAGE:  lcmN(a,b);
166RETURN: lcm(a,b);
167EXAMPLE:example lcmN; shows an example
168"
169{
170   //number d=gcdN(a,b);
171   //return(a*b/d);
172   return (a*b/gcd(a,b));
173}
174example
175{ "EXAMPLE:"; echo = 2;
176   ring R = 0,x,dp;
177   lcmN(24,15);
178}
179
180proc powerN(number m, number d, number n)
181"USAGE:  powerN(m,d,n);
182RETURN: m^d mod n
183EXAMPLE:example powerN; shows an example
184"
185{
186   if(d==0){return(1);}
187   int i;
188   if(n==0)
189   {
190      for(i=12;i>=2;i--)
191      {
192         if((d mod i)==0){return(powerN(m,d/i,n)^i);}
193      }
194      return(m*powerN(m,d-1,n));
195   }
196   for(i=12;i>=2;i--)
197   {
198      if((d mod i)==0)
199      {
200        number rr=powerN(m,d/i,n)^i mod n;
201        if (rr<0) { rr=rr+n;}
202        return(rr);
203      }
204   }
205   return(m*powerN(m,d-1,n) mod n);
206}
207example
208{ "EXAMPLE:"; echo = 2;
209   ring R = 0,x,dp;
210   powerN(24,15,7);
211}
212
213proc chineseRem(list T,list L)
214"USAGE:  chineseRem(T,L);
215RETURN: x such that x = T[i] mod L[i]
216NOTE:   chinese remainder theorem
217EXAMPLE:example chineseRem; shows an example
218"
219{
220   int i;
221   int n=size(L);
222   number N=1;
223   for(i=1;i<=n;i++)
224   {
225      N=N*L[i];
226   }
227   list M;
228   for(i=1;i<=n;i++)
229   {
230      M[i]=N/L[i];
231   }
232   list S=eexgcdN(M);
233   number x;
234   for(i=1;i<=n;i++)
235   {
236      x=x+S[i]*M[i]*T[i];
237   }
238   x=x mod N;
239   return(x);
240}
241example
242{ "EXAMPLE:"; echo = 2;
243   ring R = 0,x,dp;
244   chineseRem(list(24,15,7),list(2,3,5));
245}
246
247proc Jacobi(number a, number n)
248"USAGE:  Jacobi(a,n);
249RETURN: the generalized Legendre symbol
250NOTE: if n is an odd prime then Jacobi(a,n)=0,1,-1 if n|a, a=x^2 mod n,else
251EXAMPLE:example Jacobi; shows an example
252"
253{
254   int i;
255   int z=1;
256   number t=1;
257   number k;
258
259   if((((n-1)/2) mod 2)!=0){z=-1;}
260   if(a<0){return(z*Jacobi(-a,n));}
261   a=a mod n;
262   if(n==1){return(1);}
263   if(a==0){return(0);}
264
265   while(a!=0)
266   {
267      while((a mod 2)==0)
268      {
269         a=a/2;
270         if(((n mod 8)==3)||((n mod 8)==5)){t=-t;}
271      }
272      k=a;a=n;n=k;
273      if(((a mod 4)==3)&&((n mod 4)==3)){t=-t;}
274      a=a mod n;
275   }
276   if (n==1){return(t);}
277   return(0);
278}
279example
280{ "EXAMPLE:"; echo = 2;
281   ring R = 0,x,dp;
282   Jacobi(13580555397810650806,5792543);
283}
284
285proc primList(int n)
286"USAGE:  primList(n);
287RETURN: the list of all primes <=n
288EXAMPLE:example primList; shows an example
289"
290{
291   int i,j;
292   list re;
293   re[1]=2;
294   re[2]=3;
295   for(i=5;i<=n;i=i+2)
296   {
297     j=1;
298     while(j<=size(re))
299     {
300        if((i mod re[j])==0){break;}
301        j++;
302     }
303     if(j==size(re)+1){re[size(re)+1]=i;}
304   }
305   return(re);
306}
307example
308{ "EXAMPLE:"; echo = 2;
309   list L=primList(100);
310   size(L);
311   L[size(L)];
312}
313
314proc primL(number q)
315"USAGE:  primL(q);
316RETURN: list of the first primes p_1,...,p_r such that q>p_1*...*p_(r-1)
317        and q<p_1*...*p_r
318EXAMPLE:example primL; shows an example
319"
320{
321   int i,j;
322   list re;
323   re[1]=2;
324   re[2]=3;
325   number s=6;
326   i=3;
327   while(s<=q)
328   {
329     i=i+2;
330     j=1;
331     while(j<=size(re))
332     {
333        if((i mod re[j])==0){break;}
334        j++;
335     }
336     if(j==size(re)+1)
337     {
338        re[size(re)+1]=i;
339        s=s*i;
340     }
341   }
342   return(re);
343}
344example
345{ "EXAMPLE:"; echo = 2;
346   ring R = 0,x,dp;
347   primL(20);
348}
349
350proc intPart(number x)
351"USAGE:  intPart(x);
352RETURN: the integral part of a rational number
353EXAMPLE:example intPart; shows an example
354"
355{
356  if (x>=0)
357  {
358    return((numerator(x)-(numerator(x) mod denominator(x)))/denominator(x));
359  }
360  else
361  {
362    return((numerator(x)-(numerator(x) mod denominator(x)+denominator(x)))/denominator(x));
363  }
364}
365example
366{ "EXAMPLE:"; echo = 2;
367   ring R = 0,x,dp;
368   intPart(7/3);
369}
370
371proc intRoot(number m)
372"USAGE:  intRoot(m);
373RETURN: the integral part of the square root of m
374EXAMPLE:example intRoot; shows an example
375"
376{
377   number x=1;
378   number t=x^2;
379   number s=(x+1)^2;
380   while(((m>t)&&(m>s))||((m<t)&&(m<s)))
381   {
382      if (x==0) { t=0; }
383      else
384      {
385        x=intPart(x/2+m/(2*x));  //Newton step
386        t=x^2;
387      }
388      if(t>m)
389      {
390         s=(x-1)^2;
391      }
392      else
393      {
394         s=(x+1)^2;
395      }
396   }
397   if(t>m){return(x-1);}
398   if(s==m){return(x+1);}
399   return(x);
400}
401example
402{ "EXAMPLE:"; echo = 2;
403   ring R = 0,x,dp;
404   intRoot(20);
405}
406
407proc squareRoot(number a, number p)
408"USAGE:  squareRoot(a,p);
409RETURN: the square root of a in Z/p, p prime
410NOTE:   assumes the Jacobi symbol is 1 or p=2.
411EXAMPLE:example squareRoot; shows an example
412"
413{
414   if(p==2){return(a);}
415   if((a mod p)==0){return(0);}
416   if (a<0) { a=a+p; }
417   if(powerN(a,p-1,p)!=1)
418   {
419      "p is not prime";
420      return(number(-5));
421   }
422   number n=random(1,2147483647) mod p;
423   if(n==0){n=n+1;}
424   number j=Jacobi(n,p);
425   if(j==0)
426   {
427      "p is not prime";
428      return(number(-5));
429   }
430   if(j==1)
431   {
432      return(squareRoot(a,p));
433   }
434   number q=p-1;
435   number e=0;
436   number two=2;
437   number z,m,t;
438   while((q mod 2)==0)
439   {
440      e=e+1;
441      q=q/2;
442   }
443   number y=powerN(n,q,p);
444   number r=e;
445   number x=powerN(a,(q-1)/2,p);
446   number b=a*x^2 mod p;
447   x=a*x mod p;
448
449   while(((b-1) mod p)!=0)
450   {
451      m=0;z=b;
452      while(((z-1) mod p)!=0)
453      {
454         z=z^2 mod p;
455         m=m+1;
456      }
457      t=powerN(y,powerN(two,r-m-1,p),p);
458      y=t^2 mod p;
459      r=m;
460      x=x*t mod p;
461      b=b*y mod p;
462   }
463   return(x);
464}
465example
466{ "EXAMPLE:"; echo = 2;
467   ring R = 0,x,dp;
468   squareRoot(8315890421938608,32003);
469}
470
471
472proc solutionsMod2(matrix M)
473"USAGE:  solutionsMod2(M);
474RETURN: an intmat containing a basis of the vector space of solutions of the
475        linear system of equations defined by M over the prime field of
476        characteristic 2
477EXAMPLE:example solutionsMod2; shows an example
478"
479{
480   def R=basering;
481   ring Rhelp=2,z,(c,dp);
482   matrix M=imap(R,M);
483   matrix S=syz(M);
484   setring(R);
485   matrix S=imap(Rhelp,S);
486   int i,j;
487   intmat v[nrows(S)][ncols(S)];
488   for(i=1;i<=nrows(S);i++)
489   {
490      for(j=1;j<=ncols(S);j++)
491      {
492         if(S[i,j]==1){v[i,j]=1;}
493      }
494   }
495   return(v);
496}
497example
498{ "EXAMPLE:"; echo = 2;
499   ring R = 0,x,dp;
500   matrix M[3][3]=1,2,3,4,5,6,7,6,5;
501   solutionsMod2(M);
502}
503
504proc powerX(int q, int i, ideal I)
505"USAGE:  powerX(q,i,I);
506RETURN: the q-th power of the i-th variable modulo I
507ASSUME: I is a standard basis
508EXAMPLE:example powerX; shows an example
509"
510{
511   if(q<=181){return(reduce(var(i)^int(q),I));}
512   if((q mod 5)==0){return(reduce(powerX(q div 5,i,I)^5,I));}
513   if((q mod 4)==0){return(reduce(powerX(q div 4,i,I)^4,I));}
514   if((q mod 3)==0){return(reduce(powerX(q div 3,i,I)^3,I));}
515   if((q mod 2)==0){return(reduce(powerX(q div 2,i,I)^2,I));}
516   return(reduce(var(i)*powerX(q-1,i,I),I));
517}
518example
519{ "EXAMPLE:"; echo = 2;
520   ring R = 0,(x,y),dp;
521   powerX(100,2,std(ideal(x3-1,y2-x)));
522}
523
524//======================================================================
525//=========================== Discrete Logarithm =======================
526//======================================================================
527
528//============== Shank's baby step - giant step ========================
529
530proc babyGiant(number b, number y, number p)
531"USAGE:  babyGiant(b,y,p);
532RETURN: the discrete logarithm x: b^x=y mod p
533NOTE:   This procedure works based on Shank's baby step - giant step method.
534EXAMPLE:example babyGiant; shows an example
535"
536{
537   int i,j,m;
538   list l;
539   number h=1;
540   number x;
541
542//choose m minimal such that m^2>p
543   for(i=1;i<=p;i++){if(i^2>p) break;}
544   m=i;
545
546//baby-step:  compute the table y*b^i for 1<=i<=m
547   for(i=1;i<=m;i++){l[i]=y*b^i mod p;}
548
549//giant-step: compute b^(m+j), 1<=j<=m and search in the baby-step table
550//for an i with y*b^i=b^(m*j). If found then x=m*j-i
551   number g=b^m mod p;
552   while(j<m)
553   {
554      j++;
555      h=h*g mod p;
556      for(i=1;i<=m;i++)
557      {
558         if(h==l[i])
559         {
560            x=m*j-i;
561            j=m;
562            break;
563         }
564     }
565   }
566   return(x);
567}
568example
569{ "EXAMPLE:"; echo = 2;
570   ring R = 0,z,dp;
571   number b=2;
572   number y=10;
573   number p=101;
574   babyGiant(b,y,p);
575}
576
577//==============  Pollards rho  =================================
578
579proc rho(number b, number y, number p)
580"USAGE:  rho(b,y,p);
581RETURN: the discrete logarithm x=log_b(y): b^x=y mod p
582NOTE: Pollard's rho:
583       choose random f_0 in 0,...,p-2 ,e_0=0, define x_0=b^f_0, define
584       x_i=y^e_i*b^f_i as below. For i large enough there is i with
585       x_(i/2)=x_i. Let s:=e_(i/2)-e_i mod p-1 and t:=f_i-f_(i/2) mod p-1,
586       d=gcd(s,p-1)=u*s+v*(p-1) then x=tu/d +j*(p-1)/d for some j (to be
587       found by trying)
588EXAMPLE:example rho; shows an example
589"
590{
591   int i=1;
592   int j;
593   number s,t;
594   list e,f,x;
595
596   e[1]=0;
597   f[1]=random(0,2147483629) mod (p-1);
598   x[1]=powerN(b,f[1],p);
599   while(i)
600   {
601      if((x[i] mod 3)==1)
602      {
603         x[i+1]=y*x[i] mod p;
604         e[i+1]=e[i]+1 mod (p-1);
605         f[i+1]=f[i];
606      }
607      if((x[i] mod 3)==2)
608      {
609         x[i+1]=x[i]^2 mod p;
610         e[i+1]=e[i]*2 mod (p-1);
611         f[i+1]=f[i]*2 mod (p-1);
612      }
613      if((x[i] mod 3)==0)
614      {
615         x[i+1]=x[i]*b mod p;
616         e[i+1]=e[i];
617         f[i+1]=f[i]+1 mod (p-1);
618      }
619      i++;
620      for(j=i-1;j>=1;j--)
621      {
622         if(x[i]==x[j])
623         {
624            s=(e[j]-e[i]) mod (p-1);
625            t=(f[i]-f[j]) mod (p-1);
626            if(s!=0)
627            {
628               i=0;
629            }
630            else
631            {
632               e[1]=0;
633               f[1]=random(0,2147483629) mod (p-1);
634               x[1]=powerN(b,f[1],p);
635               i=1;
636            }
637            break;
638         }
639      }
640   }
641
642   list w=exgcdN(s,p-1);
643   number u=w[1];
644   number d=w[3];
645
646   number a=(t*u/d) mod (p-1);
647
648   number pn=powerN(b,a,p);
649   if (pn<0) { pn=pn+p;}
650   while(powerN(b,a,p)!=y)
651   {
652      a=(a+(p-1)/d) mod (p-1);
653      if (a<0) { a=a+p-1; }
654   }
655   return(a);
656}
657example
658{ "EXAMPLE:"; echo = 2;
659   ring R = 0,x,dp;
660   number b=2;
661   number y=10;
662   number p=101;
663   rho(b,y,p);
664}
665//====================================================================
666//====================== Primality Tests =============================
667//====================================================================
668
669//================================= Miller-Rabin =====================
670
671proc MillerRabin(number n, int k)
672"USAGE:  MillerRabin(n,k);
673RETURN: 1 if n is prime, 0 else
674NOTE: probabilistic test of Miller-Rabin with k loops to test if n is prime.
675       Using the theorem: If n is prime, n-1=2^s*r, r odd, then
676       powerN(a,r,n)=1 or powerN(a,r*2^i,n)=-1 for some i
677EXAMPLE:example MillerRabin; shows an example
678"
679{
680   if(n<0){n=-n;}
681   if((n==2)||(n==3)){return(1);}
682   if((n mod 2)==0){return(0);}
683
684   int i;
685   number a,b,j,r,s;
686   r=n-1;
687   s=0;
688   while((r mod 2)==0)
689   {
690      s=s+1;
691      r=r/2;
692   }
693   while(i<k)
694   {
695      i++;
696      a=random(2,2147483629) mod n; if(a==0){a=3;}
697      if(exgcdN(a,n)[3]!=1){return(0);}
698      b=powerN(a,r,n);
699      if(b!=1)
700      {
701         j=0;
702         while(j<s)
703         {
704           if(((b+1) mod n)==0) break;
705           b=powerN(b,2,n);
706           j=j+1;
707         }
708         if(j==s){return(0);}
709      }
710   }
711   return(1);
712}
713example
714{ "EXAMPLE:"; echo = 2;
715   ring R = 0,z,dp;
716   number x=2;
717   x=x^787-1;
718   MillerRabin(x,3);
719}
720
721//======================= Soloway-Strassen  ==========================
722
723proc SolowayStrassen(number n, int k)
724"USAGE:  SolowayStrassen(n,k);
725RETURN: 1 if n is prime, 0 else
726NOTE: probabilistic test of Soloway-Strassen with k loops to test if n is
727       prime using the theorem: If n is prime then
728       powerN(a,(n-1)/2,n)=Jacobi(a,n) mod n
729EXAMPLE:example SolowayStrassen; shows an example
730"
731{
732   if(n<0){n=-n;}
733   if((n==2)||(n==3)){return(1);}
734   if((n mod 2)==0){return(0);}
735
736   number a,pn,jn;
737   int i;
738   while(i<k)
739   {
740      i++;
741      a=random(2,2147483629) mod n; if(a==0){a=3;}
742      if(gcd(a,n)!=1){return(0);}
743      pn=powerN(a,(n-1)/2,n);
744      if (pn<0) { pn=pn+n;}
745      jn=Jacobi(a,n) mod n;
746      if (jn<0) { jn=jn+n;}
747      if(pn!=jn){return(0);}
748   }
749   return(1);
750}
751example
752{ "EXAMPLE:"; echo = 2;
753   ring R = 0,z,dp;
754   number h=10;
755   number p=h^100+267;
756   //p=h^100+43723;
757   //p=h^200+632347;
758   SolowayStrassen(h,3);
759}
760
761
762/*
763ring R=0,z,dp;
764number p=398075086424064937397125500550386491199064362342526708406385189575946388957261768583317;
765number q=472772146107435302536223071973048224632914695302097116459852171130520711256363590397527;
766number n=p*q;
767SolowayStrassen(n,3);
768*/
769
770//===================== Pocklington-Lehmer ==============================
771
772proc PocklingtonLehmer(number N, list #)
773"USAGE: PocklingtonLehmer(N); optional: PocklingtonLehmer(N,L);
774        L a list of the first k primes
775RETURN:message N is not prime or {A,{p},{a_p}} as certificate for N being prime
776NOTE:assumes that it is possible to factorize N-1=A*B such that gcd(A,B)=1,
777      the factorization of A is completely known and A^2>N .
778      N is prime if and only if for each prime factor p of A we can find
779      a_p such that a_p^(N-1)=1 mod N and gcd(a_p^((N-1)/p)-1,N)=1
780EXAMPLE:example PocklingtonLehmer; shows an example
781"
782{
783   number m=intRoot(N);
784   if(size(#)>0)
785   {
786      list S=PollardRho(N-1,10000,1,#);
787   }
788   else
789   {
790      list S=PollardRho(N-1,10000,1);
791   }
792   int i,j;
793   number A=1;
794   number p,a,g;
795   list PA;
796   list re;
797
798   while(i<size(S))
799   {
800      p=S[i+1];
801      A=A*p;
802      PA[i+1]=p;
803      if(A>m){break;}
804
805      while(1)
806      {
807        p=p*S[i+1];
808        if(((N-1) mod p)==0)
809        {
810           A=A*p;
811        }
812        else
813        {
814           break;
815        }
816      }
817      i++;
818   }
819   if(A<=m)
820   {
821     A=N/A;
822     PA=list(S[size(S)]);
823   }
824   for(i=1;i<=size(PA);i++)
825   {
826      a=1;
827      while(a<N-1)
828      {
829         a=a+1;
830         if(powerN(a,N-1,N)!=1){return("not prime");}
831         g=gcd(powerN(a,(N-1)/PA[i],N),N);
832         if(g==1)
833         {
834           re[size(re)+1]=list(PA[i],a);
835           break;
836         }
837         if(g<N){"not prime";return(g);}
838      }
839   }
840   return(list(A,re));
841}
842example
843{ "EXAMPLE:"; echo = 2;
844   ring R = 0,z,dp;
845   number N=105554676553297;
846   PocklingtonLehmer(N);
847   list L=primList(1000);
848   PocklingtonLehmer(N,L);
849}
850
851//=======================================================================
852//======================= Factorization =================================
853//=======================================================================
854
855//======================= Pollards rho  =================================
856
857proc PollardRho(number n, int k, int allFactors, list #)
858"USAGE:  PollardRho(n,k,allFactors); optional: PollardRho(n,k,allFactors,L);
859         L a list of the first k primes
860RETURN: a list of factors of n (which could be just n),if allFactors=0@*
861        a list of all factors of n ,if allFactors=1
862NOTE: probabilistic rho-algorithm of Pollard to find a factor of n in k loops.
863      Creates a sequence x_i such that (x_i)^2=(x_2i)^2 mod n for some i,
864      computes gcd(x_i-x_2i,n) to find a divisor. To define the sequence
865      choose x,a and define x_n+1=x_n^2+a mod n, x_1=x.
866      If allFactors is 1, it tries to find recursively all prime factors
867      using the Soloway-Strassen test.
868SEE ALSO: primefactors
869EXAMPLE:example PollardRho; shows an example
870"
871{
872    int i,j;
873    list L=primList(100);
874    list re,se;
875    if(n<0){n=-n;}
876    if(n==1){return(re);}
877
878//this is optional: test whether a prime of the list # devides n
879    if(size(#)>0)
880    {
881       L=#;
882    }
883    for(i=1;i<=size(L);i++)
884    {
885       if((n mod L[i])==0)
886       {
887          re[size(re)+1]=L[i];
888          while((n mod L[i])==0)
889          {
890             n=n/L[i];
891          }
892       }
893       if(n==1){return(re);}
894    }
895    int e=size(re);
896//here the rho-algorithm starts
897    number a,d,x,y;
898    while(n>1)
899    {
900       a=random(2,2147483629);
901       x=random(2,2147483629);
902       y=x;
903       d=1;
904       i=0;
905       while(i<k)
906       {
907          i++;
908          x=powerN(x,2,n); x=(x+a) mod n;
909          y=powerN(y,2,n); y=(y+a) mod n;
910          y=powerN(y,2,n); y=(y+a) mod n;
911          d=gcd(x-y,n);
912          if(d>1)
913          {
914             re[size(re)+1]=d;
915             while((n mod d)==0)
916             {
917               n=n/d;
918             }
919             break;
920          }
921          if(i==k)
922          {
923             re[size(re)+1]=n;
924             n=1;
925          }
926       }
927    }
928    if(allFactors)      //want to obtain all prime factors
929    {
930       i=e;
931       while(i<size(re))
932       {
933          i++;
934
935          if(!SolowayStrassen(re[i],5))
936          {
937             se=PollardRho(re[i],2*k,1);
938             re[i]=se[size(se)];
939             for(j=1;j<=size(se)-1;j++)
940             {
941                re[size(re)+1]=se[j];
942             }
943             i--;
944          }
945       }
946    }
947    return(re);
948}
949example
950{ "EXAMPLE:"; echo = 2;
951   ring R = 0,z,dp;
952   number h=10;
953   number p=h^30+4;
954   PollardRho(p,5000,0);
955}
956
957//======================== Pollards p-factorization ================
958proc pFactor(number n,int B, list P)
959"USAGE:  pFactor(n,B,P); n to be factorized, B a bound , P a list of primes
960RETURN: a list of factors of n or n if no factor found
961NOTE: Pollard's p-factorization
962       creates the product k of powers of primes (bounded by B)  from
963       the list P with the idea that for a prime divisor p of n we have
964       p-1|k, and then p divides gcd(a^k-1,n) for some random a
965EXAMPLE:example pFactor; shows an example
966"
967{
968   int i;
969   number k=1;
970   number w;
971   while(i<size(P))
972   {
973      i++;
974      w=P[i];
975      if(w>B) break;
976      while(w*P[i]<=B)
977      {
978         w=w*P[i];
979      }
980      k=k*w;
981   }
982   number a=random(2,2147483629);
983   number d=gcd(powerN(a,k,n)-1,n);
984   if((d>1)&&(d<n)){return(d);}
985   return(n);
986}
987example
988{ "EXAMPLE:"; echo = 2;
989   ring R = 0,z,dp;
990   list L=primList(1000);
991   pFactor(1241143,13,L);
992   number h=10;
993   h=h^30+25;
994   pFactor(h,20,L);
995}
996
997//==================== quadratic sieve ==============================
998
999proc quadraticSieve(number n, int c, list B, int k)
1000"USAGE:  quadraticSieve(n,c,B,k); n to be factorized, [-c,c] the
1001         sieve-intervall, B a list of primes,
1002         k for using the first k elements in B
1003RETURN: a list of factors of n or the message: no divisor found
1004NOTE: The idea being used is to find x,y such that x^2=y^2 mod n then
1005      gcd(x-y,n) can be a proper divisor of n
1006EXAMPLE:example quadraticSieve; shows an example
1007"
1008{
1009   number f,d;
1010   int i,j,l,s,p;
1011   list S,tmp;
1012   intvec v;
1013   v[k]=0;
1014
1015//compute the integral part of the square root of n
1016   number m=intRoot(n);
1017
1018//consider the function f(X)=(X+m)^2-n and compute for s in [-c,c] the values
1019   while(i<=2*c)
1020   {
1021      f=(i-c+m)^2-n;
1022      tmp[1]=i-c+m;
1023      tmp[2]=f;
1024      tmp[3]=v;
1025      S[i+1]=tmp;
1026      i++;
1027   }
1028
1029//the sieve with p in B
1030//find all s in [-c,c] such that f(s) has all prime divisors in the first
1031//k elements of B and the decomposition of f(s). They are characterized
1032//by 1 or -1 at the second place of S[j]:
1033//S[j]=j-c+m,f(j-c)/p_1^v_1*...*p_k^v_k, v_1,...,v_k maximal
1034   for(i=1;i<=k;i++)
1035   {
1036      p=B[i];
1037      if((p>2)&&(Jacobi(n,p)==-1)){i++;continue;}//n is no quadratic rest mod p
1038      j=1;
1039      while(j<=p)
1040      {
1041         if(j>2*c+1) break;
1042         f=S[j][2];
1043         v=S[j][3];
1044         s=0;
1045         while((f mod p)==0)
1046         {
1047            s++;
1048            f=f/p;
1049         }
1050         if(s)
1051         {
1052           S[j][2]=f;
1053           v[i]=s;
1054           S[j][3]=v;
1055           l=j;
1056           while(l+p<=2*c+1)
1057           {
1058              l=l+p;
1059              f=S[l][2];
1060              v=S[l][3];
1061              s=0;
1062              while((f mod p)==0)
1063              {
1064                s++;
1065                f=f/p;
1066              }
1067              S[l][2]=f;
1068              v[i]=s;
1069              S[l][3]=v;
1070           }
1071         }
1072         j++;
1073      }
1074   }
1075   list T;
1076   for(j=1;j<=2*c+1;j++)
1077   {
1078      if((S[j][2]==1)||(S[j][2]==-1))
1079      {
1080         T[size(T)+1]=S[j];
1081      }
1082   }
1083
1084//the system of equations for the exponents {l_s} for the f(s) such
1085//product f(s)^l_s is a square (l_s are 1 or 0)
1086   matrix M[k+1][size(T)];
1087   for(j=1;j<=size(T);j++)
1088   {
1089      if(T[j][2]==-1){M[1,j]=1;}
1090      for(i=1;i<=k;i++)
1091      {
1092         M[i+1,j]=T[j][3][i];
1093      }
1094   }
1095   intmat G=solutionsMod2(M);
1096
1097//construction of x and y such that x^2=y^2 mod n and d=gcd(x-y,n)
1098//y=square root of product f(s)^l_s
1099//x=product s+m
1100   number x=1;
1101   number y=1;
1102
1103   for(i=1;i<=ncols(G);i++)
1104   {
1105      kill v;
1106      intvec v;
1107      v[k]=0;
1108      for(j=1;j<=size(T);j++)
1109      {
1110         x=x*T[j][1]^G[j,i] mod n;
1111         if((T[j][2]==-1)&&(G[j,i]==1)){y=-y;}
1112         v=v+G[j,i]*T[j][3];
1113
1114      }
1115      for(l=1;l<=k;l++)
1116      {
1117         y=y*B[l]^(v[l] div 2) mod n;
1118      }
1119      d=gcd(x-y,n);
1120      if((d>1)&&(d<n)){return(d);}
1121   }
1122   return("no divisor found");
1123}
1124example
1125{ "EXAMPLE:"; echo = 2;
1126   ring R = 0,z,dp;
1127   list L=primList(5000);
1128   quadraticSieve(7429,3,L,4);
1129   quadraticSieve(1241143,100,L,50);
1130}
1131
1132//======================================================================
1133//==================== elliptic curves  ================================
1134//======================================================================
1135
1136//================= elementary operations ==============================
1137
1138proc isOnCurve(number N, number a, number b, list P)
1139"USAGE:  isOnCurve(N,a,b,P);
1140RETURN: 1 or 0 (depending on whether P is on the curve or not)
1141NOTE: checks whether P=(P[1]:P[2]:P[3]) is a point on the elliptic
1142      curve defined by y^2z=x^3+a*xz^2+b*z^3  over Z/N
1143EXAMPLE:example isOnCurve; shows an example
1144"
1145{
1146   if(((P[2]^2*P[3]-P[1]^3-a*P[1]*P[3]^2-b*P[3]^3) mod N)!=0){return(0);}
1147   return(1);
1148}
1149example
1150{ "EXAMPLE:"; echo = 2;
1151   ring R = 0,z,dp;
1152   isOnCurve(32003,5,7,list(10,16,1));
1153}
1154
1155proc ellipticAdd(number N, number a, number b, list P, list Q)
1156"USAGE:  ellipticAdd(N,a,b,P,Q);
1157RETURN: list L, representing the point P+Q
1158NOTE: P=(P[1]:P[2]:P[3]), Q=(Q[1]:Q[2]:Q[3]) points on the elliptic curve
1159      defined by y^2z=x^3+a*xz^2+b*z^3  over Z/N
1160EXAMPLE:example ellipticAdd; shows an example
1161"
1162{
1163   if(N==2){ERROR("not implemented for 2");}
1164   int i;
1165   for(i=1;i<=3;i++)
1166   {
1167      P[i]=P[i] mod N; if (P[i]<0) { P[i]=P[i]+N:}
1168      Q[i]=Q[i] mod N; if (Q[i]<0) { Q[i]=Q[i]+N;}
1169   }
1170   list Resu;
1171   Resu[1]=number(0);
1172   Resu[2]=number(1);
1173   Resu[3]=number(0);
1174   list Error;
1175   Error[1]=0;
1176   //test for ellictic curve
1177   number D=4*a^3+27*b^2;
1178   number g=gcd(D,N);
1179   if(g==N){return(Error);}
1180   if(g!=1)
1181   {
1182      P[4]=g;
1183      return(P);
1184   }
1185   if(((P[1]==0)&&(P[2]==0)&&(P[3]==0))||((Q[1]==0)&&(Q[2]==0)&&(Q[3]==0)))
1186   {
1187      Error[1]=-2;
1188      return(Error);
1189   }
1190   if(!isOnCurve(N,a,b,P)||!isOnCurve(N,a,b,Q))
1191   {
1192      Error[1]=-1;
1193      return(Error);
1194   }
1195   if(P[3]==0){return(Q);}
1196   if(Q[3]==0){return(P);}
1197   list I=exgcdN(P[3],N);
1198   if(I[3]!=1)
1199   {
1200      P[4]=I[3];
1201      return(P);
1202   }
1203   P[1]=P[1]*I[1] mod N;
1204   P[2]=P[2]*I[1] mod N;
1205   I=exgcdN(Q[3],N);
1206   if(I[3]!=1)
1207   {
1208      P[4]=I[3];
1209      return(P);
1210   }
1211   Q[1]=Q[1]*I[1] mod N;
1212   Q[2]=Q[2]*I[1] mod N;
1213   if((P[1]==Q[1])&&(((P[2]+Q[2]) mod N)==0)){return(Resu);}
1214   number L;
1215   if((P[1]==Q[1])&&(P[2]==Q[2]))
1216   {
1217      I=exgcdN(2*Q[2],N);
1218      if(I[3]!=1)
1219      {
1220         P[4]=I[3];
1221         return(P);
1222      }
1223      L=I[1]*(3*Q[1]^2+a) mod N;
1224   }
1225   else
1226   {
1227      I=exgcdN(Q[1]-P[1],N);
1228      if(I[3]!=1)
1229      {
1230         P[4]=I[3];
1231         return(P);
1232      }
1233      L=(Q[2]-P[2])*I[1] mod N;
1234   }
1235   Resu[1]=(L^2-P[1]-Q[1]) mod N;
1236   if (Resu[1]<0) { Resu[1]=Resu[1]+N; }
1237   Resu[2]=(L*(P[1]-Resu[1])-P[2]) mod N;
1238   if (Resu[2]<0) { Resu[2]=Resu[2]+N; }
1239   Resu[3]=number(1);
1240   return(Resu);
1241}
1242example
1243{ "EXAMPLE:"; echo = 2;
1244   ring R = 0,z,dp;
1245   number N=11;
1246   number a=1;
1247   number b=6;
1248   list P,Q;
1249   P[1]=2;
1250   P[2]=4;
1251   P[3]=1;
1252   Q[1]=3;
1253   Q[2]=5;
1254   Q[3]=1;
1255   ellipticAdd(N,a,b,P,Q);
1256}
1257
1258proc ellipticMult(number N, number a, number b, list P, number k)
1259"USAGE:  ellipticMult(N,a,b,P,k);
1260RETURN: a list L representing the point k*P
1261NOTE:  P=(P[1]:P[2]:P[3]) a point on the elliptic curve defined by
1262       y^2z=x^3+a*xz^2+b*z^3  over Z/N
1263EXAMPLE:example ellipticMult; shows an example
1264"
1265{
1266   if(P[3]==0){return(P);}
1267   list resu;
1268   resu[1]=number(0);
1269   resu[2]=number(1);
1270   resu[3]=number(0);
1271
1272   if(k==0){return(resu);}
1273   if(k==1){return(P);}
1274   if(k==2){return(ellipticAdd(N,a,b,P,P));}
1275   if(k==-1)
1276   {
1277      resu=P;
1278      resu[2]=N-P[2];
1279      return(resu);
1280   }
1281   if(k<0)
1282   {
1283      resu=ellipticMult(N,a,b,P,-k);
1284      return(ellipticMult(N,a,b,resu,-1));
1285   }
1286   if((k mod 2)==0)
1287   {
1288      resu=ellipticMult(N,a,b,P,k/2);
1289      return(ellipticAdd(N,a,b,resu,resu));
1290   }
1291   resu=ellipticMult(N,a,b,P,k-1);
1292   return(ellipticAdd(N,a,b,resu,P));
1293}
1294example
1295{ "EXAMPLE:"; echo = 2;
1296   ring R = 0,z,dp;
1297   number N=11;
1298   number a=1;
1299   number b=6;
1300   list P;
1301   P[1]=2;
1302   P[2]=4;
1303   P[3]=1;
1304   ellipticMult(N,a,b,P,3);
1305}
1306
1307//================== Random for elliptic curves =====================
1308
1309proc ellipticRandomCurve(number N)
1310"USAGE:  ellipticRandomCurve(N);
1311RETURN: a list of two random numbers a,b and 4a^3+27b^2 mod N
1312NOTE:   y^2z=x^3+a*xz^2+b^2*z^3 defines an elliptic curve over Z/N
1313EXAMPLE:example ellipticRandomCurve; shows an example
1314"
1315{
1316   int k;
1317   while(k<=10)
1318   {
1319     k++;
1320     number a=random(1,2147483647) mod N;
1321     number b=random(1,2147483647) mod N;
1322     //test for ellictic curve
1323     number D=4*a^3+27*b^4; //the constant term is b^2
1324     number g=gcd(D,N);
1325     if(g<N){return(list(a,b,g));}
1326   }
1327   ERROR("no random curve found");
1328}
1329example
1330{ "EXAMPLE:"; echo = 2;
1331   ring R = 0,z,dp;
1332   ellipticRandomCurve(32003);
1333}
1334
1335proc ellipticRandomPoint(number N, number a, number b)
1336"USAGE:  ellipticRandomPoint(N,a,b);
1337RETURN: a list representing  a random point (x:y:z) of the elliptic curve
1338        defined by y^2z=x^3+a*xz^2+b*z^3  over Z/N
1339EXAMPLE:example ellipticRandomPoint; shows an example
1340"
1341{
1342   number x=random(1,2147483647) mod N;
1343   number h=x^3+a*x+b;
1344   h=h mod N;
1345   list resu;
1346   resu[1]=x;
1347   resu[2]=0;
1348   resu[3]=1;
1349   if(h==0){return(resu);}
1350
1351   number n=Jacobi(h,N);
1352   if(n==0)
1353   {
1354      resu=-5;
1355      "N is not prime";
1356      return(resu);
1357   }
1358   if(n==1)
1359   {
1360      resu[2]=squareRoot(h,N);
1361      return(resu);
1362   }
1363   return(ellipticRandomPoint(N,a,b));
1364}
1365example
1366{ "EXAMPLE:"; echo = 2;
1367   ring R = 0,z,dp;
1368   ellipticRandomPoint(32003,3,181);
1369}
1370
1371
1372
1373//====================================================================
1374//======== counting the points of an elliptic curve  =================
1375//====================================================================
1376
1377//==================   the trivial approaches  =======================
1378proc countPoints(number N, number a, number b)
1379"USAGE:  countPoints(N,a,b);
1380RETURN: the number of points of the elliptic curve defined by
1381        y^2=x^3+a*x+b  over Z/N
1382NOTE: trivial approach
1383EXAMPLE:example countPoints; shows an example
1384"
1385{
1386  number x;
1387  number r=N+1;
1388  while(x<N)
1389  {
1390     r=r+Jacobi((x^3+a*x+b) mod N,N);
1391     x=x+1;
1392  }
1393  return(r);
1394}
1395example
1396{ "EXAMPLE:"; echo = 2;
1397   ring R = 0,z,dp;
1398   countPoints(181,71,150);
1399}
1400
1401proc ellipticAllPoints(number N, number a, number b)
1402"USAGE:  ellipticAllPoints(N,a,b);
1403RETURN: list of points (x:y:z) of the elliptic curve defined by
1404        y^2z=x^3+a*xz^2+b*z^3  over Z/N
1405EXAMPLE:example ellipticAllPoints; shows an example
1406"
1407{
1408   list resu,point;
1409   point[1]=0;
1410   point[2]=1;
1411   point[3]=0;
1412   resu[1]=point;
1413   point[3]=1;
1414   number x,h,n;
1415   while(x<N)
1416   {
1417      h=(x^3+a*x+b) mod N;
1418      if(h==0)
1419      {
1420         point[1]=x;
1421         point[2]=0;
1422         resu[size(resu)+1]=point;
1423      }
1424      else
1425      {
1426         n=Jacobi(h,N);
1427         if(n==1)
1428         {
1429            n=squareRoot(h,N);
1430            point[1]=x;
1431            point[2]=n;
1432            resu[size(resu)+1]=point;
1433            point[2]=N-n;
1434            resu[size(resu)+1]=point;
1435         }
1436      }
1437      x=x+1;
1438   }
1439   return(resu);
1440}
1441example
1442{ "EXAMPLE:"; echo = 2;
1443   ring R = 0,z,dp;
1444   list L=ellipticAllPoints(181,71,150);
1445   size(L);
1446   L[size(L)];
1447}
1448
1449//================ the algorithm of Shanks and Mestre =================
1450
1451proc ShanksMestre(number q, number a, number b, list #)
1452"USAGE:  ShanksMestre(q,a,b); optional: ShanksMestre(q,a,b,s); s the number
1453         of loops in the algorithm (default s=1)
1454RETURN: the number of points of the elliptic curve defined by
1455         y^2=x^3+a*x+b  over Z/N
1456NOTE: algorithm of Shanks and Mestre (baby-step-giant-step)
1457EXAMPLE:example ShanksMestre; shows an example
1458"
1459{
1460   number n=intRoot(4*q);
1461   number m=intRoot(intRoot(16*q))+1;
1462   number d;
1463   int i,j,k,s;
1464   list B,K,T,P,Q,R,mP;
1465   B[1]=list(0,1,0);
1466   if(size(#)>0)
1467   {
1468      s=#[1];
1469   }
1470   else
1471   {
1472      s=1;
1473   }
1474   while(k<s)
1475   {
1476      P =ellipticRandomPoint(q,a,b);
1477      Q =ellipticMult(q,a,b,P,n+q+1);
1478
1479      while(j<m)
1480      {
1481         j++;
1482         B[j+1]=ellipticAdd(q,a,b,P,B[j]);  //baby-step list
1483      }
1484      mP=ellipticAdd(q,a,b,P,B[j]);
1485      mP[2]=q-mP[2];
1486      while(i<m)                            //giant-step
1487      {
1488         j=0;
1489         while(j<m)
1490         {
1491            j++;
1492            if((Q[1]==B[j][1])&&(Q[2]==B[j][2])&&(Q[3]==B[j][3]))
1493            {
1494
1495               T[1]=P;
1496               T[2]=q+1+n-(i*m+j-1);
1497               K[size(K)+1]=T;
1498               if(size(K)>1)
1499               {
1500                  if(K[size(K)][2]!=K[size(K)-1][2])
1501                  {
1502                     d=gcd(K[size(K)][2],K[size(K)-1][2]);
1503                     if(ellipticMult(q,a,b,K[size(K)],d)[3]==0)
1504                     {
1505                       K[size(K)][2]=K[size(K)-1][2];
1506                     }
1507                  }
1508               }
1509               i=int(m);
1510               break;
1511            }
1512         }
1513         i=i+1;
1514         Q=ellipticAdd(q,a,b,mP,Q);
1515      }
1516      k++;
1517   }
1518   if(size(K)>0)
1519   {
1520      int te=1;
1521      for(i=1;i<=size(K)-1;i++)
1522      {
1523         if(K[size(K)][2]!=K[i][2])
1524         {
1525           if(ellipticMult(q,a,b,K[i],K[size(K)][2])[3]!=0)
1526           {
1527             te=0;
1528             break;
1529           }
1530         }
1531      }
1532      if(te)
1533      {
1534         return(K[size(K)][2]);
1535      }
1536   }
1537   return(ShanksMestre(q,a,b,s));
1538}
1539example
1540{ "EXAMPLE:"; echo = 2;
1541   ring R = 0,z,dp;
1542   ShanksMestre(32003,71,602);
1543}
1544
1545//==================== Schoof's algorithm =============================
1546
1547proc Schoof(number N,number a, number b)
1548"USAGE:  Schoof(N,a,b);
1549RETURN: the number of points of the elliptic curve defined by
1550        y^2=x^3+a*x+b  over Z/N
1551NOTE:  algorithm of Schoof
1552EXAMPLE:example Schoof; shows an example
1553"
1554{
1555   int pr=printlevel;
1556//test for ellictic curve
1557   number D=4*a^3+27*b^2;
1558   number G=gcd(D,N);
1559   if(G==N){ERROR("not an elliptic curve");}
1560   if(G!=1){ERROR("not a prime");}
1561
1562//=== small N
1563  // if((N<=500)&&(pr<5)){return(countPoints(int(N),a,b));}
1564
1565//=== the general case
1566   number q=intRoot(4*N);
1567   list L=primL(2*q);
1568   int r=size(L);
1569   list T;
1570   int i,j;
1571   for(j=1;j<=r;j++)
1572   {
1573      T[j]=(testElliptic(int(N),a,b,L[j])+int(q)) mod L[j];
1574   }
1575   if(pr>=5)
1576   {
1577      "===================================================================";
1578      "Chinese remainder :";
1579      for(i=1;i<=size(T);i++)
1580      {
1581         " x =",T[i]," mod ",L[i];
1582      }
1583      "gives t+ integral part of the square root of q (to be positive)";
1584      chineseRem(T,L);
1585      "we obtain t = ",chineseRem(T,L)-q;
1586      "===================================================================";
1587   }
1588   number t=chineseRem(T,L)-q;
1589   return(N+1-t);
1590}
1591example
1592{ "EXAMPLE:"; echo = 2;
1593   ring R = 0,z,dp;
1594   Schoof(32003,71,602);
1595}
1596
1597/*
1598needs 518 sec
1599Schoof(2147483629,17,3567);
16002147168895
1601*/
1602
1603
1604proc generateG(number a,number b, int m)
1605"USAGE:  generateG(a,b,m);
1606RETURN: m-th division polynomial
1607NOTE: generate the so-called division polynomials, i.e., the recursively defined
1608polynomials p_m=generateG(a,b,m) in Z[x, y] such that, for a point (x:y:1) on the
1609elliptic curve defined by y^2=x^3+a*x+b  over Z/N the point@*
1610m*P=(x-(p_(m-1)*p_(m+1))/p_m^2 :(p_(m+2)*p_(m-1)^2-p_(m-2)*p_(m+1)^2)/4y*p_m^3 :1)
1611and m*P=0 if and only if p_m(P)=0
1612EXAMPLE:example generateG; shows an example
1613"
1614{
1615   if(m==0){return(poly(0));}
1616   if(m==1){return(poly(1));}
1617   if(m==2){return(2*var(1));}
1618   if(m==3){return(3*var(2)^4+6*a*var(2)^2+12*b*var(2)-a^2);}
1619   if(m==4)
1620   {
1621      return(4*var(1)*(var(2)^6+5*a*var(2)^4+20*b*var(2)^3-5*a^2*var(2)^2
1622        -4*a*b*var(2)-8*b^2-a^3));
1623   }
1624   if((m mod 2)==0)
1625   {
1626      return((generateG(a,b,m div 2+2)*generateG(a,b,m div 2-1)^2
1627        -generateG(a,b,m div 2-2)*generateG(a,b,m div 2+1)^2)
1628        *generateG(a,b,m div 2)/(2*var(1)));
1629   }
1630   return(generateG(a,b,(m-1) div 2+2)*generateG(a,b,(m-1) div 2)^3
1631     -generateG(a,b,(m-1) div 2-1)*generateG(a,b,(m-1) div 2+1)^3);
1632}
1633example
1634{ "EXAMPLE:"; echo = 2;
1635   ring R = 0,(x,y),dp;
1636   generateG(7,15,4);
1637}
1638
1639
1640proc testElliptic(int q,number a,number b,int l)
1641"USAGE:  testElliptic(q,a,b,l);
1642RETURN: an integer t, the trace of the Frobenius
1643NOTE: the kernel for the Schoof algorithm: looks for the t such that for all
1644      points (x:y:1) in C[l]={P in C | l*P=0},C the elliptic curve defined by
1645      y^2=x^3+a*x+b  over Z/q with group structure induced by 0=(0:1:0),
1646      (x:y:1)^(q^2)-t*(x:y:1)^q -ql*(x:y:1)=(0:1:0), ql= q mod l, trace of
1647      Frobenius.
1648EXAMPLE:example testElliptic; shows an example
1649"
1650{
1651   int pr=printlevel;
1652   def R=basering;
1653   ring S=q,(y,x),(L(100000),lp);
1654   number a=imap(R,a);
1655   number b=imap(R,b);
1656   poly F=y2-x3-a*x-b;       // the curve C
1657   poly G=generateG(a,b,l);
1658   ideal I=std(ideal(F,G));  // the points C[l]
1659   poly xq=powerX(q,2,I);
1660   poly yq=powerX(q,1,I);
1661   poly xq2=reduce(subst(xq,x,xq,y,yq),I);
1662   poly yq2=reduce(subst(yq,x,xq,y,yq),I);
1663   ideal J;
1664   int ql=q mod l;
1665   if(ql==0){ERROR("q is not prime");}
1666   int t;
1667   poly F1,F2,G1,G2,P1,P2,Q1,Q2,H1,H2,L1,L2;
1668
1669   if(pr>=5)
1670   {
1671      "===================================================================";
1672      "q=",q;
1673      "l=",l;
1674      "q mod l=",ql;
1675      "the Groebner basis for C[l]:";I;
1676      "x^q mod I = ",xq;
1677      "x^(q^2) mod I = ",xq2;
1678      "y^q mod I = ",yq;
1679      "y^(q^2) mod I = ",yq2;
1680      pause();
1681   }
1682   //==== l=2 =============================================================
1683   if(l==2)
1684   {
1685      xq=powerX(q,2,std(x3+a*x+b));
1686      J=std(ideal(xq-x,x3+a*x+b));
1687      if(deg(J[1])==0){t=1;}
1688      if(pr>=5)
1689      {
1690         "===================================================================";
1691         "the case l=2";
1692         "the gcd(x^q-x,x^3+ax+b)=",J[1];
1693         pause();
1694      }
1695      setring R;
1696      return(t);
1697   }
1698   //=== (F1/G1,F2/G2)=[ql](x,y) ==========================================
1699   if(ql==1)
1700   {
1701      F1=x;G1=1;F2=y;G2=1;
1702   }
1703   else
1704   {
1705      G1=reduce(generateG(a,b,ql)^2,I);
1706      F1=reduce(x*G1-generateG(a,b,ql-1)*generateG(a,b,ql+1),I);
1707      G2=reduce(4*y*generateG(a,b,ql)^3,I);
1708      F2=reduce(generateG(a,b,ql+2)*generateG(a,b,ql-1)^2
1709               -generateG(a,b,ql-2)*generateG(a,b,ql+1)^2,I);
1710
1711   }
1712   if(pr>=5)
1713   {
1714      "===================================================================";
1715      "the point ql*(x,y)=(F1/G1,F2/G2)";
1716      "F1=",F1;
1717      "G1=",G1;
1718      "F2=",F2;
1719      "G2=",G2;
1720      pause();
1721   }
1722   //==== the case t=0 :  the equations for (x,y)^(q^2)=-[ql](x,y) ===
1723   J[1]=xq2*G1-F1;
1724   J[2]=yq2*G2+F2;
1725   if(pr>=5)
1726   {
1727      "===================================================================";
1728      "the case t=0 mod l";
1729      "the equations for (x,y)^(q^2)=-[ql](x,y) :";
1730      J;
1731      "the test, if they vanish for all points in C[l]:";
1732      reduce(J,I);
1733      pause();
1734   }
1735   //=== test if all points of C[l] satisfy  (x,y)^(q^2)=-[ql](x,y)
1736   //=== if so: t mod l =0 is returned
1737   if(size(reduce(J,I))==0){setring R;return(0);}
1738
1739   //==== test for (x,y)^(q^2)=[ql](x,y) for some point
1740
1741   J=xq2*G1-F1,yq2*G2-F2;
1742   J=std(J+I);
1743   if(pr>=5)
1744   {
1745      "===================================================================";
1746      "test if (x,y)^(q^2)=[ql](x,y) for one point";
1747      "if so, the Frobenius has an eigenvalue 2ql/t: (x,y)^q=(2ql/t)*(x,y)";
1748      "it follows that t^2=4q mod l";
1749      "if w is one square root of q mod l";
1750      "t =2w mod l or -2w mod l ";
1751      "-------------------------------------------------------------------";
1752      "the equations for (x,y)^(q^2)=[ql](x,y) :";
1753      xq2*G1-F1,yq2*G2-F2;
1754      "the test if one point satisfies them";
1755      J;
1756      pause();
1757   }
1758   if(deg(J[1])>0)
1759   {
1760      setring R;
1761      int w=int(squareRoot(q,l));
1762      setring S;
1763      //=== +/-2w mod l zurueckgeben, wenn (x,y)^q=+/-[w](x,y)
1764      //==== the case t>0 :  (Q1/P1,Q2/P2)=[w](x,y) ==============
1765      if(w==1)
1766      {
1767         Q1=x;P1=1;Q2=y;P2=1;
1768      }
1769      else
1770      {
1771         P1=reduce(generateG(a,b,w)^2,I);
1772         Q1=reduce(x*G1-generateG(a,b,w-1)*generateG(a,b,w+1),I);
1773         P2=reduce(4*y*generateG(a,b,w)^3,I);
1774         Q2=reduce(generateG(a,b,w+2)*generateG(a,b,w-1)^2
1775               -generateG(a,b,w-2)*generateG(a,b,w+1)^2,I);
1776      }
1777      J=xq*P1-Q1,yq*P2-Q2;
1778      J=std(I+J);
1779      if(pr>=5)
1780      {
1781      "===================================================================";
1782      "the Frobenius has an eigenvalue, one of the roots of  w^2=q mod l:";
1783      "one root is:";w;
1784      "test, if it is the eigenvalue (if not it must be -w):";
1785      "the equations for (x,y)^q=w*(x,y)";I;xq*P1-Q1,yq*P2-Q2;
1786      "the Groebner basis";
1787       J;
1788         pause();
1789      }
1790      if(deg(J[1])>0){return(2*w mod l);}
1791      return(-2*w mod l);
1792   }
1793
1794   //==== the case t>0 :  (Q1/P1,Q2/P2)=(x,y)^(q^2)+[ql](x,y) =====
1795   P1=reduce(G1*G2^2*(F1-xq2*G1)^2,I);
1796   Q1=reduce((F2-yq2*G2)^2*G1^3-F1*G2^2*(F1-xq2*G1)^2-xq2*P1,I);
1797   P2=reduce(P1*G2*(F1-xq2*G1),I);
1798   Q2=reduce((xq2*P1-Q1)*(F2-yq2*G2)*G1-yq2*P2,I);
1799
1800   if(pr>=5)
1801   {
1802      "we are in the general case:";
1803      "(x,y)^(q^2)!=ql*(x,y) and (x,y)^(q^2)!=-ql*(x,y) ";
1804      "the point (Q1/P1,Q2/P2)=(x,y)^(q^2)+[ql](x,y)";
1805      "Q1=",Q1;
1806      "P1=",P1;
1807      "Q2=",Q2;
1808      "P2=",P2;
1809      pause();
1810   }
1811   while(t<(l-1) div 2)
1812   {
1813      t++;
1814      //====  (H1/L1,H2/L2)=[t](x,y)^q ===============================
1815      if(t==1)
1816      {
1817         H1=xq;L1=1;
1818         H2=yq;L2=1;
1819      }
1820      else
1821      {
1822         H1=x*generateG(a,b,t)^2-generateG(a,b,t-1)*generateG(a,b,t+1);
1823         H1=subst(H1,x,xq,y,yq);
1824         H1=reduce(H1,I);
1825         L1=generateG(a,b,t)^2;
1826         L1=subst(L1,x,xq,y,yq);
1827         L1=reduce(L1,I);
1828         H2=generateG(a,b,t+2)*generateG(a,b,t-1)^2
1829           -generateG(a,b,t-2)*generateG(a,b,t+1)^2;
1830         H2=subst(H2,x,xq,y,yq);
1831         H2=reduce(H2,I);
1832         L2=4*y*generateG(a,b,t)^3;
1833         L2=subst(L2,x,xq,y,yq);
1834         L2=reduce(L2,I);
1835      }
1836      J=Q1*L1-P1*H1,Q2*L2-P2*H2;
1837      if(pr>=5)
1838      {
1839      "we test now the different t, 0<t<=(l-1)/2:";
1840      "the point (H1/L1,H2/L2)=[t](x,y)^q :";
1841      "H1=",H1;
1842      "L1=",L1;
1843      "H2=",H2;
1844      "L2=",L2;
1845      "the equations for (x,y)^(q^2)+[ql](x,y)=[t](x,y)^q :";J;
1846      "the test";reduce(J,I);
1847      "the test for l-t (the x-cordinate is the same):";
1848       Q1*L1-P1*H1,Q2*L2+P2*H2;
1849       reduce(ideal(Q1*L1-P1*H1,Q2*L2+P2*H2),I);
1850         pause();
1851      }
1852      if(size(reduce(J,I))==0){setring R;return(t);}
1853      J=Q1*L1-P1*H1,Q2*L2+P2*H2;
1854      if(size(reduce(J,I))==0){setring R;return(l-t);}
1855   }
1856   ERROR("something is wrong in testElliptic");
1857}
1858example
1859{ "EXAMPLE:"; echo = 2;
1860   ring R = 0,z,dp;
1861   testElliptic(1267985441,338474977,64740730,3);
1862}
1863
1864//============================================================================
1865//================== Factorization and Primality Test ========================
1866//============================================================================
1867
1868//============= Lenstra's ECM Factorization ==================================
1869
1870proc factorLenstraECM(number N, list S, int B, list #)
1871"USAGE:  factorLenstraECM(N,S,B); optional: factorLenstraECM(N,S,B,d);
1872         d+1 the number of loops in the algorithm (default d=0)
1873RETURN: a factor of N or the message no factor found
1874NOTE: - computes a factor of N using Lenstra's ECM factorization@*
1875      - the idea is that the fact that N is not prime is dedected using
1876        the operations on the elliptic curve
1877      - is similarly to Pollard's p-1-factorization
1878EXAMPLE:example factorLenstraECM; shows an example
1879"
1880{
1881   list L,P;
1882   number g,M,w;
1883   int i,j,k,d;
1884   int l=size(S);
1885   if(size(#)>0)
1886   {
1887      d=#[1];
1888   }
1889
1890   while(i<=d)
1891   {
1892      L=ellipticRandomCurve(N);
1893      if(L[3]>1){return(L[3]);} //the discriminant was not invertible
1894      P=list(0,L[2],1);
1895      j=0;
1896      M=1;
1897      while(j<l)
1898      {
1899         j++;
1900         w=S[j];
1901         if(w>B) break;
1902         while(w*S[j]<B)
1903         {
1904           w=w*S[j];
1905         }
1906         M=M*w;
1907         P=ellipticMult(N,L[1],L[2]^2,P,w);
1908         if(size(P)==4){return(P[4]);}  //some inverse did not exsist
1909         if(P[3]==0){break;}            //the case M*P=0
1910      }
1911      i++;
1912   }
1913   return("no factor found");
1914}
1915example
1916{ "EXAMPLE:"; echo = 2;
1917   ring R = 0,z,dp;
1918   list L=primList(1000);
1919   factorLenstraECM(181*32003,L,10,5);
1920   number h=10;
1921   h=h^30+25;
1922   factorLenstraECM(h,L,4,3);
1923}
1924
1925//================= ECPP (Goldwasser-Kilian) a primaly-test =============
1926
1927proc ECPP(number N)
1928"USAGE:  ECPP(N);
1929RETURN: message:N is not prime or {L,P,m,q} as certificate for N being prime@*
1930         L a list (y^2=x^3+L[1]*x+L[2] defines an elliptic curve C)@*
1931         P a list ((P[1]:P[2]:P[3]) is a point of C)@*
1932         m,q integers
1933ASSUME: gcd(N,6)=1
1934NOTE:   The basis of the algorithm is the following theorem:
1935         Given C, an elliptic curve over Z/N, P a point of C(Z/N),
1936         m an integer, q a prime with the following properties:
1937         - q|m
1938         - q>(4-th root(N) +1)^2
1939         - m*P=0=(0:1:0)
1940         - (m/q)*P=(x:y:z) and z a unit in Z/N
1941         Then N is prime.
1942EXAMPLE:example ECPP; shows an example
1943"
1944{
1945   list L,S,P;
1946   number m,q;
1947   int i;
1948
1949   number n=intRoot(intRoot(N));
1950   n=(n+1)^2;                         //lower bound for q
1951   while(1)
1952   {
1953      L=ellipticRandomCurve(N);       //a random elliptic curve C
1954      m=ShanksMestre(N,L[1],L[2],3);  //number of points of the curve C
1955      S=PollardRho(m,10000,1);        //factorization of m
1956      for(i=1;i<=size(S);i++)         //search for q between the primes
1957      {
1958         q=S[i];
1959         if(n<q){break;}
1960      }
1961      if(n<q){break;}
1962   }
1963   number u=m/q;
1964   while(1)
1965   {
1966      P=ellipticRandomPoint(N,L[1],L[2]);  //a random point on C
1967      "P=",P;
1968      if(ellipticMult(N,L[1],L[2],P,m)[3]!=0){"N is not prime";return(-5);}
1969      if(ellipticMult(N,L[1],L[2],P,u)[3]!=0)
1970      {
1971         L=delete(L,3);
1972         return(list(L,P,m,q));
1973      }
1974   }
1975}
1976example
1977{ "EXAMPLE:"; echo = 2;
1978   ring R = 0,z,dp;
1979   number N=1267985441;
1980   ECPP(N);
1981}
1982
1983static proc wordToNumber(string s)
1984{
1985   int i;
1986   intvec v;
1987   number n;
1988   number t=27;
1989   for(i=size(s);i>0;i--)
1990   {
1991      if(s[i]=="a"){v[i]=0;}
1992      if(s[i]=="b"){v[i]=1;}
1993      if(s[i]=="c"){v[i]=2;}
1994      if(s[i]=="d"){v[i]=3;}
1995      if(s[i]=="e"){v[i]=4;}
1996      if(s[i]=="f"){v[i]=5;}
1997      if(s[i]=="g"){v[i]=6;}
1998      if(s[i]=="h"){v[i]=7;}
1999      if(s[i]=="i"){v[i]=8;}
2000      if(s[i]=="j"){v[i]=9;}
2001      if(s[i]=="k"){v[i]=10;}
2002      if(s[i]=="l"){v[i]=11;}
2003      if(s[i]=="m"){v[i]=12;}
2004      if(s[i]=="n"){v[i]=13;}
2005      if(s[i]=="o"){v[i]=14;}
2006      if(s[i]=="p"){v[i]=15;}
2007      if(s[i]=="q"){v[i]=16;}
2008      if(s[i]=="r"){v[i]=17;}
2009      if(s[i]=="s"){v[i]=18;}
2010      if(s[i]=="t"){v[i]=19;}
2011      if(s[i]=="u"){v[i]=20;}
2012      if(s[i]=="v"){v[i]=21;}
2013      if(s[i]=="w"){v[i]=22;}
2014      if(s[i]=="x"){v[i]=23;}
2015      if(s[i]=="y"){v[i]=24;}
2016      if(s[i]=="z"){v[i]=25;}
2017      if(s[i]==" "){v[i]=26;}
2018   }
2019   for(i=1;i<=size(s);i++)
2020   {
2021      n=n+v[i]*t^(i-1);
2022   }
2023   return(n);
2024}
2025
2026static proc numberToWord(number n)
2027{
2028   int i,j;
2029   string v;
2030   list s;
2031   number t=27;
2032   number mm;
2033   number nn=n;
2034   while(nn>t)
2035   {
2036      j++;
2037      mm=nn mod t;
2038      s[j]=mm;
2039      nn=(nn-mm)/t;
2040   }
2041   j++;
2042   s[j]=nn;
2043   for(i=1;i<=j;i++)
2044   {
2045      if(s[i]==0){v=v+"a";}
2046      if(s[i]==1){v=v+"b";}
2047      if(s[i]==2){v=v+"c";}
2048      if(s[i]==3){v=v+"d";}
2049      if(s[i]==4){v=v+"e";}
2050      if(s[i]==5){v=v+"f";}
2051      if(s[i]==6){v=v+"g";}
2052      if(s[i]==7){v=v+"h";}
2053      if(s[i]==8){v=v+"i";}
2054      if(s[i]==9){v=v+"j";}
2055      if(s[i]==10){v=v+"k";}
2056      if(s[i]==11){v=v+"l";}
2057      if(s[i]==12){v=v+"m";}
2058      if(s[i]==13){v=v+"n";}
2059      if(s[i]==14){v=v+"o";}
2060      if(s[i]==15){v=v+"p";}
2061      if(s[i]==16){v=v+"q";}
2062      if(s[i]==17){v=v+"r";}
2063      if(s[i]==18){v=v+"s";}
2064      if(s[i]==19){v=v+"t";}
2065      if(s[i]==20){v=v+"u";}
2066      if(s[i]==21){v=v+"v";}
2067      if(s[i]==22){v=v+"w";}
2068      if(s[i]==23){v=v+"x";}
2069      if(s[i]==24){v=v+"y";}
2070      if(s[i]==25){v=v+"z";}
2071      if(s[i]==26){v=v+" ";}
2072   }
2073   return(v);
2074}
2075
2076proc code(string s)
2077"USAGE:  code(s); s a string
2078ASSUME:  s contains only small letters and space
2079COMPUTE: a number, RSA-coding of the string s
2080RETURN:  return RSA-coding of the string s as string
2081EXAMPLE: code;  shows an example
2082"
2083{
2084   ring r=0,x,dp;
2085   number
2086p=398075086424064937397125500550386491199064362342526708406385189575946388957261768583317;
2087   number
2088q=472772146107435302536223071973048224632914695302097116459852171130520711256363590397527;
2089   number n=p*q;
2090   number phi=(p-1)*(q-1);
2091   number e=1234567891;
2092   list L=exgcdN(e,phi);
2093   number d=L[1];
2094   number m=wordToNumber(s);
2095   number c=powerN(m,e,n);
2096   string cc=string(c);
2097   return(cc);
2098}
2099example
2100{"EXAMPLE:";  echo = 2;
2101  string s="i go to school";
2102  code(s);
2103}
2104
2105proc decodeString(string g)
2106"USAGE:  decodeString(s); s a string
2107ASSUME:  s is a string of a number, the output of code
2108COMPUTE: a string, RSA-decoding of the string s
2109RETURN:  return RSA-decoding of the string s as string
2110EXAMPLE: decodeString;  shows an example
2111"
2112{
2113   ring r=0,x,dp;
2114   number
2115p=398075086424064937397125500550386491199064362342526708406385189575946388957261768583317;
2116   number
2117q=472772146107435302536223071973048224632914695302097116459852171130520711256363590397527;
2118   number n=p*q;
2119   number phi=(p-1)*(q-1);
2120   number e=1234567891;
2121   list L=exgcdN(e,phi);
2122   number d=L[1];
2123   execute("number c="+g+";");
2124   number f=powerN(c,d,n);
2125   string s=numberToWord(f);
2126   return(s);
2127}
2128example
2129{"EXAMPLE:";  echo = 2;
2130  string
2131s="78638618599886548153321853785991541374544958648147340831959482696082179852616053583234149080198937632782579537867262780982185252913122030800897193851413140758915381848932565";
2132  string t=decodeString(s);
2133  t;
2134}
2135
2136/*
2137//===============================================================
2138//=======  Example for DSA  =====================================
2139//===============================================================
2140Suppose a file test is given.It contains "Oscar".
2141
2142//Hash-function MD5 under Linux
2143
2144md5sum test           8edfe37dae96cfd2466d77d3884d4196
2145
2146//================================================================
2147
2148ring R=0,x,dp;
2149
2150number q=2^19+21;          //524309
2151number o=2*3*23*number(7883)*number(16170811);
2152
2153number p=o*q+1;            //9223372036869000547
2154number b=2;
2155number g=power(2,o,p);     //8308467587808723131
2156
2157number a=111111;
2158number A=power(g,a,p);     //8566038811843553785
2159
2160number h =decimal("8edfe37dae96cfd2466d77d3884d4196");
2161
2162                           //189912871665444375716340628395668619670
2163h= h mod q;                //259847
2164
2165number k=123456;
2166
2167number ki=exgcd(k,q)[1];    //50804
2168                            //inverse von k mod q
2169
2170number r= power(g,k,p) mod q;    //76646
2171
2172number s=ki*(h+a*r) mod q;       //2065
2173
2174//========== signatur is (r,s)=(76646,2065) =====================
2175//==================== verification  ============================
2176
2177number si=exgcd(s,q)[1];  //inverse von s mod q
2178number e1=si*h mod q;
2179number e2=si*r mod q;
2180number rr=((power(g,e1,p)*power(A,e2,p)) mod p) mod q;    //76646
2181
2182//===============================================================
2183//=======  Example for knapsack  ================================
2184//===============================================================
2185ring R=(5^5,t),x,dp;
2186R;
2187//   # ground field : 3125
2188//   primitive element : t
2189//   minpoly        : 1*t^5+4*t^1+2*t^0
2190//   number of vars : 1
2191//        block   1 : ordering dp
2192//                  : names    x
2193//        block   2 : ordering C
2194
2195proc findEx(number n, number g)
2196{
2197   int i;
2198   for(i=0;i<=size(basering)-1;i++)
2199   {
2200      if(g^i==n){return(i);}
2201   }
2202}
2203
2204number g=t^3;                       //choice of the primitive root
2205
2206findEx(t+1,g);
2207//2091
2208findEx(t+2,g);
2209//2291
2210findEx(t+3,g);
2211//1043
2212
2213intvec b=1,2091,2291,1043;          // k=4
2214int z=199;
2215intvec v=1043+z,1+z,2091+z,2291+z;  //permutation   pi=(0123)
2216v;
22171242,200,2290,2490
2218
2219//(1101)=(e_3,e_2,e_1,e_0)
2220//encoding 2490+2290+1242=6022 und 1+1+0+1=3
2221
2222//(6022,3) decoding: c-z*c'=6022-199*3=5425
2223
2224ring S=5,x,dp;
2225poly F=x5+4x+2;
2226poly G=reduce((x^3)^5425,std(F));
2227G;
2228//x3+x2+x+1
2229
2230factorize(G);
2231//[1]:
2232//   _[1]=1
2233//   _[2]=x+1
2234//   _[3]=x-2
2235//   _[4]=x+2
2236//[2]:
2237//   1,1,1,1
2238
2239//factors x+1,x+2,x+3, i.e.  (1110)=(e_pi(3),e_pi(2),e_pi(1),e_pi(0))
2240
2241//pi(0)=1,pi(1)=2,pi(2)=3,pi(3)=0 gives:  (1101)
2242
2243*/
2244
Note: See TracBrowser for help on using the repository browser.