125 lines
2.7 KiB
C++
125 lines
2.7 KiB
C++
/*
|
|
* Test program to find discrete logarithms using Pollard's rho method.
|
|
* Suitable primes are generated by "genprime" program
|
|
*
|
|
* See "Monte Carlo Methods for Index Computation"
|
|
* by J.M. Pollard in Math. Comp. Vol. 32 1978 pp 918-924
|
|
*
|
|
* Requires: big.cpp crt.cpp
|
|
*/
|
|
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include "big.h" /* include MIRACL system */
|
|
#include "crt.h" /* chinese remainder thereom */
|
|
#define NPRIMES 10
|
|
#define PROOT 2
|
|
|
|
using namespace std;
|
|
|
|
Miracl precision=100;
|
|
|
|
static Big p,p1,order,lim1,lim2;
|
|
static BOOL flag=FALSE;
|
|
|
|
void iterate(Big &x,Big &q,Big &r,Big &a,Big &b)
|
|
{ /* apply Pollards random mapping */
|
|
if (x<lim1)
|
|
{
|
|
x=(x*q)%p;
|
|
a+=1;
|
|
if (a==order) a=0;
|
|
return;
|
|
}
|
|
if (x<lim2)
|
|
{
|
|
x=(x*x)%p;
|
|
a*=2;
|
|
if (a>=order) a-=order;
|
|
b*=2;
|
|
if (b>=order) b-=order;
|
|
return;
|
|
}
|
|
x=(x*r)%p;
|
|
b+=1;
|
|
if (b==order) b=0;
|
|
}
|
|
|
|
long rho(Big &q,Big &r,Big &m,Big &n)
|
|
{ /* find q^m = r^n */
|
|
long iter,rr,i;
|
|
Big ax,bx,ay,by,x,y;
|
|
x=1;
|
|
y=1;
|
|
iter=0L;
|
|
rr=1L;
|
|
do
|
|
{ /* Brent's Cycle finder */
|
|
x=y;
|
|
ax=ay;
|
|
bx=by;
|
|
rr*=2;
|
|
for (i=1;i<=rr;i++)
|
|
{
|
|
iter++;
|
|
iterate(y,q,r,ay,by);
|
|
if (x==y) break;
|
|
}
|
|
} while (x!=y);
|
|
m=ax-ay;
|
|
if (m<0) m+=order;
|
|
n=by-bx;
|
|
if (n<0) n+=order;
|
|
return iter;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
int i,np;
|
|
long iter;
|
|
Big pp[NPRIMES],rem[NPRIMES];
|
|
Big m,n,Q,R,q,w,x;
|
|
ifstream prime_data("prime.dat");
|
|
p1=1;
|
|
prime_data >> np;
|
|
for (i=0;i<np;i++) prime_data >> pp[i];
|
|
for (i=0;i<np;i++) p1*=pp[i];
|
|
p=p1+1;
|
|
if (!prime(p))
|
|
{
|
|
cout << "Huh - modulus is not prime!";
|
|
return 0;
|
|
}
|
|
lim1=p/3;
|
|
lim2=2*lim1;
|
|
cout << "solve discrete logarithm problem - using Pollard rho method\n";
|
|
cout << "finds x in y=" << PROOT << "^x mod p, given y, for fixed p\n";
|
|
cout << "p=";
|
|
cout << p << endl;
|
|
cout << "given factorisation of p-1 = \n2";
|
|
for (i=1;i<np;i++)
|
|
cout << "*" << pp[i];
|
|
cout << "\n\nEnter y= ";
|
|
cin >> q;
|
|
Crt chinese(np,pp);
|
|
for (i=0;i<np;i++)
|
|
{ /* accumulate solutions for each pp */
|
|
w=p1;
|
|
w/=pp[i];
|
|
Q=pow(q,w,p);
|
|
R=pow(PROOT,w,p);
|
|
order=pp[i];
|
|
iter=rho(Q,R,m,n);
|
|
w=inverse(m,order);
|
|
rem[i]=(w*n)%order;
|
|
cout << iter << " iterations needed" << endl;
|
|
}
|
|
x=chinese.eval(rem); /* apply Chinese remainder thereom */
|
|
cout << "Discrete log of y= ";
|
|
cout << x << endl;
|
|
w=pow(PROOT,x,p);
|
|
cout << "check = ";
|
|
cout << w << endl;
|
|
return 0;
|
|
}
|