From d24ab714b958b9fece4631076e240739ad0dd23f Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Mon, 3 Oct 2016 22:15:25 +0200 Subject: Progress --- bigint.cpp | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- bigint.h | 17 ++++++++-- main.cpp | 34 ++++++++++++------- numalgo.cpp | 61 +++++++++++++++++++++++++++++++++- numalgo.h | 5 +++ primes.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++++ primes.h | 19 +++++++++++ 7 files changed, 292 insertions(+), 32 deletions(-) create mode 100644 primes.cpp create mode 100644 primes.h diff --git a/bigint.cpp b/bigint.cpp index 5182d07..644ffb3 100644 --- a/bigint.cpp +++ b/bigint.cpp @@ -7,6 +7,10 @@ using namespace std; +Bigint Bigint::zero(0); +Bigint Bigint::one(1); +Bigint Bigint::mone(-1); + Bigint::Bigint() :sign(1){} @@ -163,6 +167,11 @@ Bigint& Bigint::operator*=(const Bigint &o){ return *this; } +//TODO: optimise these functions +Bigint& Bigint::operator+=(slongdigit_t n){return *this+=Bigint(n);} +Bigint& Bigint::operator-=(slongdigit_t n){return *this-=Bigint(n);} +Bigint& Bigint::operator*=(slongdigit_t n){return *this*=Bigint(n);} + Bigint& Bigint::operator<<=(int sh){ if(sh==0)return *this; if(digits.size()==0)return *this; @@ -233,12 +242,26 @@ Bigint Bigint::operator*(const Bigint &o) const { return product(*this,o); } +//TODO: optimise these functions +Bigint Bigint::operator+(slongdigit_t n) const {return *this+Bigint(n);} +Bigint Bigint::operator-(slongdigit_t n) const {return *this-Bigint(n);} +Bigint Bigint::operator*(slongdigit_t n) const {return *this*Bigint(n);} + +Bigint Bigint::operator<<(int sh) const { + return Bigint(*this)<<=sh; +} + +Bigint Bigint::operator>>(int sh) const { + return Bigint(*this)>>=sh; +} + int depthrecord; pair Bigint::divmod(const Bigint &div) const { pair res=divmod(div,1); //cerr< "< Bigint::divmod(const Bigint &div,int depth) const { - //cerr<<"divmod("<100)assert(false); + //cerr<<"divmod("< Bigint::divmod(const Bigint &div,int depth) const { //cerr<<"guess="< Bigint::divmod(const Bigint &div,int depth) const { longdigit_t factor=((longdigit_t)1<=1); + for(int i=0;i<1000;i++){ + Bigint n(rand64()); + for(int j=1;jn); + } +} + void performrsa(){ PrivateKey privkey; Bigint p(1000000007),q(3000000019); @@ -115,8 +133,7 @@ void performrsa(){ privkey.pub.exp=65537; { Bigint x; - Bigint one(1); - egcd((p-one)*(q-one),privkey.pub.exp,x,privkey.pexp); + egcd((p-Bigint::one)*(q-Bigint::one),privkey.pub.exp,x,privkey.pexp); } cout<<"d = "<=0); assert(m>=1); - if(m==1)return Bigint(0); + if(m==1)return Bigint::zero; Bigint res(1); vector bits(e.bits()); for(int i=bits.size()-1;i>=0;i--){ @@ -42,9 +43,67 @@ Bigint expmod(const Bigint &b,const Bigint &e,const Bigint &m){ return res; } +Bigint isqrt(const Bigint &n){ + assert(n>=0); + if(n<=1)return n; + const int maxiter=20; //empirically, this should happen around 3.5 million bits in n. (niter ~= -1.87+1.45ln(bits)) + // __asm("int3\n\t"); + // cout<<"bitcount="< smallprimes; +bool smallprimes_inited=false; + +void fillsmallprimes(){ + smallprimes_inited=true; + //TODO: reserve expected amount of space in smallprimes + smallprimes.push_back(2); + const int highbound=65000; + bool composite[highbound/2]; //entries for 3, 5, 7, 9, etc. + memset(composite,0,highbound/2*sizeof(bool)); + int roothighbound=sqrt(highbound); + for(int i=3;i<=highbound;i+=2){ + if(composite[i/2-1])continue; + smallprimes.push_back(i); + if(i>roothighbound)continue; + for(int j=i*i;j<=highbound;j+=2*i){ + composite[j/2-1]=true; + } + } + //for(int p : smallprimes)cerr< genprimepair(int nbits){ + // for x = nbits/2: + // (2^x)^2 = 2^(2x) + // (2^x + 2^(x-2))^2 = 2^(2x) + 2^(2x-1) + 2^(2x-4) + // ergo: (2^x + lambda*2^(x-2))^2 \in [2^(2x), 2^(2x+1)), for lambda \in [0,1] + // To make sure the primes "differ in length by a few digits" [RSA78], we use x1=x-2 in the first + // prime and x2-x+2 in the second + int x1=nbits/2-2,x2=(nbits+1)/2+2; + assert(x1+x2==nbits); + return make_pair( + randprime(Bigint::one<biglow); + static const int maxrangesize=100001; + Bigint diff(bighigh-biglow); + Bigint low,high; //inclusive + if(diff<=maxrangesize){ + low=biglow; + high=bighigh; + } else { + high=low=cryptrandom_big(diff-maxrangesize); + high+=maxrangesize; + } + if(low.even())low+=1; + if(high.even())high-=1; + Bigint sizeb(high-low+1); + assert(sizeb>=0&&sizeb<=maxrangesize); + int nnums=(sizeb.lowdigits()+1)/2; + + bool composite[nnums]; //low, low+2, low+4, ..., high (all odd numbers) + memset(composite,0,nnums*sizeof(bool)); + int nsmallprimes=smallprimes.size(); + for(int i=1;i +#include +#include "bigint.h" + +extern std::vector smallprimes; + +void fillsmallprimes(); + +//for use in RSA (pass target number of bits of N) +std::pair genprimepair(int nbits); + +//finds random in range [low,high]; throws domain_error if no prime found +//Will call fillsmallprimes() if not yet done +Bigint randprime(const Bigint &low,const Bigint &high); + +//checks primality +bool bailliePSW(const Bigint&); -- cgit v1.2.3-54-g00ecf