⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nbtheory.cpp

📁 lots Elliptic curve cryptography codes. Use Visual c++ to compile
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// nbtheory.cpp - written and placed in the public domain by Wei Dai#include "pch.h"#ifndef CRYPTOPP_IMPORTS#include "nbtheory.h"#include "modarith.h"#include "algparam.h"#include <math.h>#include <vector>#ifdef _OPENMP// needed in MSVC 2005 to generate correct manifest#include <omp.h>#endifNAMESPACE_BEGIN(CryptoPP)const word s_lastSmallPrime = 32719;struct NewPrimeTable{	std::vector<word16> * operator()() const	{		const unsigned int maxPrimeTableSize = 3511;		std::auto_ptr<std::vector<word16> > pPrimeTable(new std::vector<word16>);		std::vector<word16> &primeTable = *pPrimeTable;		primeTable.reserve(maxPrimeTableSize);		primeTable.push_back(2);		unsigned int testEntriesEnd = 1;				for (unsigned int p=3; p<=s_lastSmallPrime; p+=2)		{			unsigned int j;			for (j=1; j<testEntriesEnd; j++)				if (p%primeTable[j] == 0)					break;			if (j == testEntriesEnd)			{				primeTable.push_back(p);				testEntriesEnd = UnsignedMin(54U, primeTable.size());			}		}		return pPrimeTable.release();	}};const word16 * GetPrimeTable(unsigned int &size){	const std::vector<word16> &primeTable = Singleton<std::vector<word16>, NewPrimeTable>().Ref();	size = (unsigned int)primeTable.size();	return &primeTable[0];}bool IsSmallPrime(const Integer &p){	unsigned int primeTableSize;	const word16 * primeTable = GetPrimeTable(primeTableSize);	if (p.IsPositive() && p <= primeTable[primeTableSize-1])		return std::binary_search(primeTable, primeTable+primeTableSize, (word16)p.ConvertToLong());	else		return false;}bool TrialDivision(const Integer &p, unsigned bound){	unsigned int primeTableSize;	const word16 * primeTable = GetPrimeTable(primeTableSize);	assert(primeTable[primeTableSize-1] >= bound);	unsigned int i;	for (i = 0; primeTable[i]<bound; i++)		if ((p % primeTable[i]) == 0)			return true;	if (bound == primeTable[i])		return (p % bound == 0);	else		return false;}bool SmallDivisorsTest(const Integer &p){	unsigned int primeTableSize;	const word16 * primeTable = GetPrimeTable(primeTableSize);	return !TrialDivision(p, primeTable[primeTableSize-1]);}bool IsFermatProbablePrime(const Integer &n, const Integer &b){	if (n <= 3)		return n==2 || n==3;	assert(n>3 && b>1 && b<n-1);	return a_exp_b_mod_c(b, n-1, n)==1;}bool IsStrongProbablePrime(const Integer &n, const Integer &b){	if (n <= 3)		return n==2 || n==3;	assert(n>3 && b>1 && b<n-1);	if ((n.IsEven() && n!=2) || GCD(b, n) != 1)		return false;	Integer nminus1 = (n-1);	unsigned int a;	// calculate a = largest power of 2 that divides (n-1)	for (a=0; ; a++)		if (nminus1.GetBit(a))			break;	Integer m = nminus1>>a;	Integer z = a_exp_b_mod_c(b, m, n);	if (z==1 || z==nminus1)		return true;	for (unsigned j=1; j<a; j++)	{		z = z.Squared()%n;		if (z==nminus1)			return true;		if (z==1)			return false;	}	return false;}bool RabinMillerTest(RandomNumberGenerator &rng, const Integer &n, unsigned int rounds){	if (n <= 3)		return n==2 || n==3;	assert(n>3);	Integer b;	for (unsigned int i=0; i<rounds; i++)	{		b.Randomize(rng, 2, n-2);		if (!IsStrongProbablePrime(n, b))			return false;	}	return true;}bool IsLucasProbablePrime(const Integer &n){	if (n <= 1)		return false;	if (n.IsEven())		return n==2;	assert(n>2);	Integer b=3;	unsigned int i=0;	int j;	while ((j=Jacobi(b.Squared()-4, n)) == 1)	{		if (++i==64 && n.IsSquare())	// avoid infinite loop if n is a square			return false;		++b; ++b;	}	if (j==0) 		return false;	else		return Lucas(n+1, b, n)==2;}bool IsStrongLucasProbablePrime(const Integer &n){	if (n <= 1)		return false;	if (n.IsEven())		return n==2;	assert(n>2);	Integer b=3;	unsigned int i=0;	int j;	while ((j=Jacobi(b.Squared()-4, n)) == 1)	{		if (++i==64 && n.IsSquare())	// avoid infinite loop if n is a square			return false;		++b; ++b;	}	if (j==0) 		return false;	Integer n1 = n+1;	unsigned int a;	// calculate a = largest power of 2 that divides n1	for (a=0; ; a++)		if (n1.GetBit(a))			break;	Integer m = n1>>a;	Integer z = Lucas(m, b, n);	if (z==2 || z==n-2)		return true;	for (i=1; i<a; i++)	{		z = (z.Squared()-2)%n;		if (z==n-2)			return true;		if (z==2)			return false;	}	return false;}struct NewLastSmallPrimeSquared{	Integer * operator()() const	{		return new Integer(Integer(s_lastSmallPrime).Squared());	}};bool IsPrime(const Integer &p){	if (p <= s_lastSmallPrime)		return IsSmallPrime(p);	else if (p <= Singleton<Integer, NewLastSmallPrimeSquared>().Ref())		return SmallDivisorsTest(p);	else		return SmallDivisorsTest(p) && IsStrongProbablePrime(p, 3) && IsStrongLucasProbablePrime(p);}bool VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level){	bool pass = IsPrime(p) && RabinMillerTest(rng, p, 1);	if (level >= 1)		pass = pass && RabinMillerTest(rng, p, 10);	return pass;}unsigned int PrimeSearchInterval(const Integer &max){	return max.BitCount();}static inline bool FastProbablePrimeTest(const Integer &n){	return IsStrongProbablePrime(n,2);}AlgorithmParameters MakeParametersForTwoPrimesOfEqualSize(unsigned int productBitLength){	if (productBitLength < 16)		throw InvalidArgument("invalid bit length");	Integer minP, maxP;	if (productBitLength%2==0)	{		minP = Integer(182) << (productBitLength/2-8);		maxP = Integer::Power2(productBitLength/2)-1;	}	else	{		minP = Integer::Power2((productBitLength-1)/2);		maxP = Integer(181) << ((productBitLength+1)/2-8);	}	return MakeParameters("RandomNumberType", Integer::PRIME)("Min", minP)("Max", maxP);}class PrimeSieve{public:	// delta == 1 or -1 means double sieve with p = 2*q + delta	PrimeSieve(const Integer &first, const Integer &last, const Integer &step, signed int delta=0);	bool NextCandidate(Integer &c);	void DoSieve();	static void SieveSingle(std::vector<bool> &sieve, word16 p, const Integer &first, const Integer &step, word16 stepInv);	Integer m_first, m_last, m_step;	signed int m_delta;	word m_next;	std::vector<bool> m_sieve;};PrimeSieve::PrimeSieve(const Integer &first, const Integer &last, const Integer &step, signed int delta)	: m_first(first), m_last(last), m_step(step), m_delta(delta), m_next(0){	DoSieve();}bool PrimeSieve::NextCandidate(Integer &c){	bool safe = SafeConvert(std::find(m_sieve.begin()+m_next, m_sieve.end(), false) - m_sieve.begin(), m_next);	assert(safe);	if (m_next == m_sieve.size())	{		m_first += long(m_sieve.size())*m_step;		if (m_first > m_last)			return false;		else		{			m_next = 0;			DoSieve();			return NextCandidate(c);		}	}	else	{		c = m_first + long(m_next)*m_step;		++m_next;		return true;	}}void PrimeSieve::SieveSingle(std::vector<bool> &sieve, word16 p, const Integer &first, const Integer &step, word16 stepInv){	if (stepInv)	{		size_t sieveSize = sieve.size();		size_t j = (word32(p-(first%p))*stepInv) % p;		// if the first multiple of p is p, skip it		if (first.WordCount() <= 1 && first + step*long(j) == p)			j += p;		for (; j < sieveSize; j += p)			sieve[j] = true;	}}void PrimeSieve::DoSieve(){	unsigned int primeTableSize;	const word16 * primeTable = GetPrimeTable(primeTableSize);	const unsigned int maxSieveSize = 32768;	unsigned int sieveSize = STDMIN(Integer(maxSieveSize), (m_last-m_first)/m_step+1).ConvertToLong();	m_sieve.clear();	m_sieve.resize(sieveSize, false);	if (m_delta == 0)	{		for (unsigned int i = 0; i < primeTableSize; ++i)			SieveSingle(m_sieve, primeTable[i], m_first, m_step, (word16)m_step.InverseMod(primeTable[i]));	}	else	{		assert(m_step%2==0);		Integer qFirst = (m_first-m_delta) >> 1;		Integer halfStep = m_step >> 1;		for (unsigned int i = 0; i < primeTableSize; ++i)		{			word16 p = primeTable[i];			word16 stepInv = (word16)m_step.InverseMod(p);			SieveSingle(m_sieve, p, m_first, m_step, stepInv);			word16 halfStepInv = 2*stepInv < p ? 2*stepInv : 2*stepInv-p;			SieveSingle(m_sieve, p, qFirst, halfStep, halfStepInv);		}	}}bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector){	assert(!equiv.IsNegative() && equiv < mod);	Integer gcd = GCD(equiv, mod);	if (gcd != Integer::One())	{		// the only possible prime p such that p%mod==equiv where GCD(mod,equiv)!=1 is GCD(mod,equiv)		if (p <= gcd && gcd <= max && IsPrime(gcd) && (!pSelector || pSelector->IsAcceptable(gcd)))		{			p = gcd;			return true;		}		else			return false;	}	unsigned int primeTableSize;	const word16 * primeTable = GetPrimeTable(primeTableSize);	if (p <= primeTable[primeTableSize-1])	{		const word16 *pItr;		--p;		if (p.IsPositive())			pItr = std::upper_bound(primeTable, primeTable+primeTableSize, (word)p.ConvertToLong());		else			pItr = primeTable;		while (pItr < primeTable+primeTableSize && !(*pItr%mod == equiv && (!pSelector || pSelector->IsAcceptable(*pItr))))			++pItr;		if (pItr < primeTable+primeTableSize)		{			p = *pItr;			return p <= max;		}		p = primeTable[primeTableSize-1]+1;	}	assert(p > primeTable[primeTableSize-1]);	if (mod.IsOdd())		return FirstPrime(p, max, CRT(equiv, mod, 1, 2, 1), mod<<1, pSelector);	p += (equiv-p)%mod;	if (p>max)		return false;	PrimeSieve sieve(p, max, mod);	while (sieve.NextCandidate(p))	{		if ((!pSelector || pSelector->IsAcceptable(p)) && FastProbablePrimeTest(p) && IsPrime(p))			return true;	}	return false;}// the following two functions are based on code and comments provided by Preda Mihailescustatic bool ProvePrime(const Integer &p, const Integer &q){	assert(p < q*q*q);	assert(p % q == 1);// this is the Quisquater test. Numbers p having passed the Lucas - Lehmer test// for q and verifying p < q^3 can only be built up of two factors, both = 1 mod q,// or be prime. The next two lines build the discriminant of a quadratic equation// which holds iff p is built up of two factors (excercise ... )	Integer r = (p-1)/q;	if (((r%q).Squared()-4*(r/q)).IsSquare())		return false;	unsigned int primeTableSize;	const word16 * primeTable = GetPrimeTable(primeTableSize);	assert(primeTableSize >= 50);	for (int i=0; i<50; i++) 	{		Integer b = a_exp_b_mod_c(primeTable[i], r, p);		if (b != 1) 			return a_exp_b_mod_c(b, q, p) == 1;	}	return false;}Integer MihailescuProvablePrime(RandomNumberGenerator &rng, unsigned int pbits){	Integer p;	Integer minP = Integer::Power2(pbits-1);	Integer maxP = Integer::Power2(pbits) - 1;	if (maxP <= Integer(s_lastSmallPrime).Squared())	{		// Randomize() will generate a prime provable by trial division		p.Randomize(rng, minP, maxP, Integer::PRIME);		return p;	}	unsigned int qbits = (pbits+2)/3 + 1 + rng.GenerateWord32(0, pbits/36);	Integer q = MihailescuProvablePrime(rng, qbits);	Integer q2 = q<<1;	while (true)	{		// this initializes the sieve to search in the arithmetic		// progression p = p_0 + \lambda * q2 = p_0 + 2 * \lambda * q,		// with q the recursively generated prime above. We will be able		// to use Lucas tets for proving primality. A trick of Quisquater		// allows taking q > cubic_root(p) rather then square_root: this		// decreases the recursion.		p.Randomize(rng, minP, maxP, Integer::ANY, 1, q2);		PrimeSieve sieve(p, STDMIN(p+PrimeSearchInterval(maxP)*q2, maxP), q2);		while (sieve.NextCandidate(p))		{			if (FastProbablePrimeTest(p) && ProvePrime(p, q))				return p;		}	}	// not reached	return p;}Integer MaurerProvablePrime(RandomNumberGenerator &rng, unsigned int bits){	const unsigned smallPrimeBound = 29, c_opt=10;	Integer p;	unsigned int primeTableSize;	const word16 * primeTable = GetPrimeTable(primeTableSize);	if (bits < smallPrimeBound)	{		do			p.Randomize(rng, Integer::Power2(bits-1), Integer::Power2(bits)-1, Integer::ANY, 1, 2);		while (TrialDivision(p, 1 << ((bits+1)/2)));	}	else	{		const unsigned margin = bits > 50 ? 20 : (bits-10)/2;		double relativeSize;		do			relativeSize = pow(2.0, double(rng.GenerateWord32())/0xffffffff - 1);		while (bits * relativeSize >= bits - margin);		Integer a,b;		Integer q = MaurerProvablePrime(rng, unsigned(bits*relativeSize));		Integer I = Integer::Power2(bits-2)/q;		Integer I2 = I << 1;		unsigned int trialDivisorBound = (unsigned int)STDMIN((unsigned long)primeTable[primeTableSize-1], (unsigned long)bits*bits/c_opt);		bool success = false;		while (!success)		{			p.Randomize(rng, I, I2, Integer::ANY);			p *= q; p <<= 1; ++p;			if (!TrialDivision(p, trialDivisorBound))			{				a.Randomize(rng, 2, p-1, Integer::ANY);				b = a_exp_b_mod_c(a, (p-1)/q, p);				success = (GCD(b-1, p) == 1) && (a_exp_b_mod_c(b, q, p) == 1);			}		}	}	return p;}Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u){	// isn't operator overloading great?	return p * (u * (xq-xp) % q) + xp;/*	Integer t1 = xq-xp;	cout << hex << t1 << endl;	Integer t2 = u * t1;	cout << hex << t2 << endl;	Integer t3 = t2 % q;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -