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

📄 bigint.cpp

📁 RSA对称、非对称加密解密算法
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		carry=tmp%A;
	}
	mod=carry;
	for(myi=result.m_nLength-1;myi>=0;myi--)
	{
		if(result.m_ulvalue[myi]==0)
		{
			result.m_nLength--;
		}
		else
		{
			break;
		}
	}
	return result;
}
CBigInt CBigInt::Div(long A)
{
	unsigned long carry=0;
	int myi;
	My_int64 tmp;
	CBigInt result(this->base);
	result.m_nLength=this->m_nLength;
	for(myi=this->m_nLength-1;myi>=0;myi--)
	{
		tmp=carry*this->base+this->m_ulvalue[myi];
		result.m_ulvalue[myi]=tmp/A;
		carry=tmp%A;
	}
	for(myi=result.m_nLength-1;myi>=0;myi--)
	{
		if(result.m_ulvalue[myi]==0)
		{
			result.m_nLength--;
		}
		else
		{
			break;
		}
	}
	return result;
}
//file://大数求模
//file://调用形式:N.Mod(A),返回值:N%A
//file://求模与求商原理相同
CBigInt CBigInt::Mod(CBigInt& A)
{
	CBigInt X(base),Y(base);
	int len,i;
	My_int64 num,div;
	unsigned long carry=0;
	X.Mov(*this);
	while(X.Cmp(A)>0)
	{
		if(X.m_ulvalue[X.m_nLength-1]>A.m_ulvalue[A.m_nLength-1])
		{
			len=X.m_nLength-A.m_nLength;
			div=X.m_ulvalue[X.m_nLength-1]/(A.m_ulvalue[A.m_nLength-1]+1);
		}
		else
			if(X.m_nLength>A.m_nLength)
			{
				len=X.m_nLength-A.m_nLength-1;
				num=X.m_ulvalue[X.m_nLength-1];
				num=num*base+X.m_ulvalue[X.m_nLength-2];
				if(A.m_ulvalue[A.m_nLength-1]==(base-1))
					div=num/base;
				else
					div=num/(A.m_ulvalue[A.m_nLength-1]+1);
			}
			else
			{
				//X.Sub(A);
				X.Mov(X.Sub(A));
				break;
			}
			Y.Mov(div);
			Y.Mov(Y.Mul(A));
			//Y.Mul(A);
			Y.m_nLength+=len;
			for(i=Y.m_nLength-1;i>=len;i--)
				Y.m_ulvalue[i]=Y.m_ulvalue[i-len];
			for(i=0;i<len;i++)
				Y.m_ulvalue[i]=0;
			X.Mov(X.Sub(Y));
			//X.Sub(Y);
	}
	if(X.Cmp(A)==0)
		X.Mov(0);
	return X;
}
long CBigInt::Mod(long A)
{
	My_int64 tmp=0;
	for(unsigned int i=this->m_nLength-1;i>=0;i--)
	{
		tmp*=this->base;
		tmp+=this->m_ulvalue[i];
		tmp=tmp%A;
		if(i==0)
			break;
	}

	return (long)tmp;
}
//file://暂时只给出了十进制字符串的转化
int CBigInt::InPutFromStr(string& str, const unsigned int system=DEC)
{
	int len=str.length(),i,j;
	unsigned long tmp;
	Mov(0);
	if(system==10)
	{
		base=100000000;
		for(i=len-1,m_nLength=0;i>-1;m_nLength++)//m_nLength代表大数的那个位数
		{
			tmp=1;
			for(j=0;j<8&&i>-1;j++,i--)
			{
				m_ulvalue[m_nLength]+=(str[i]-'0')*tmp;
				tmp*=10;
			}
		}
	}
	else
	{
		base=0x100000000;//这个地方存在问题,处理不好兼容性会出问题
		//处理16进制的输入
	}
	
	return 0;
}

//file://暂时只给出了十进制字符串的转化
//mcqsmall://在这里的转化效率真的很低,有待改进
int CBigInt::OutPutToStr(string& str, const unsigned int system)
{
	str="";
	char ch[9];
	int len=0,i;
	for(i=0;i<m_nLength-1;i++)
	{
		_ultoa(m_ulvalue[i],ch,system);
		len=strlen(ch);
		str.insert(0,ch);
		for(len=8-len;len>0;len--)
			str.insert(0,"0");
	}
	_ultoa(m_ulvalue[i],ch,system);
	str.insert(0,ch);
	/*
	CBigInt X;
	X.Mov(*this);
	while(X.m_ulvalue[X.m_nLength-1]>0)
	{
		ch=X.Mod(system)+48;
		str.insert(0,ch);
		X.Mov(X.Div(system));//建议不要这样写,这样可能耗费的内存空间会比较大
	}
	*/
	return 0;
}

//file://欧几里德算法求:Y=X.Euc(A),使满足:YX mod A=1
//file://相当于对不定方程ax-by=1求最小整数解
//file://实际上就是初中学过的辗转相除法
/********************************************************************
例如:11x-49y=1,求x

            11 x  -  49 y  =   1      a)
49%11=5 ->  11 x  -   5 y  =   1      b)
11%5 =1 ->     x  -   5 y  =   1      c)

令y=1  代入c)式  得x=6
令x=6  代入b)式  得y=13
令y=13 代入a)式  得x=58  
********************************************************************/
CBigInt CBigInt::Euc(CBigInt& A)
{
	CBigInt X(base),Y(base),tmp(base);
	X.Mov(*this);
	Y.Mov(A);
	if((X.m_nLength==1)&&(X.m_ulvalue[0]==1))
		return X;
	if((Y.m_nLength==1)&&(Y.m_ulvalue[0]==1))
	{
		X.Mov(X.Sub(1));
		return X;
	}
	if(X.Cmp(Y)==1)
	{
		X.Mov(X.Mod(Y));
		if(X.Cmp(0)==0)
			return Y;
	}
	tmp.Mov(Y.Mod(X));
	while(tmp.Cmp(0)!=0)
	{
		Y.Mov(X);
		X.Mov(tmp);
		tmp.Mov(Y.Mod(X));
	}
	return X;
	/*
	X.Mov(X.Euc(Y));
	Y.Mov(*this);
	if(Y.Cmp(A)==1)
	{
		X.Mov(X.Mul(Y));
		X.Mov(X.Sub(1));
		X.Mov(X.Div(A));
	}
	else
	{
		X.Mov(X.Mul(A));
		X.Mov(X.Add(1));
		X.Mov(X.Div(Y));
	}
	return X;
	*/
}

CBigInt CBigInt::Euc(CBigInt &A, CBigInt &result)
{
	CBigInt q,s_1,s_2,r_j,r_j1,tmp;
	s_2.Mov(1);
	s_1.Mov(0);
	r_j.Mov(*this);
	r_j1.Mov(A);
	q.Mov(r_j.Div(r_j1));
	tmp.Mov(r_j.Mod(r_j1));
	r_j.Mov(r_j1);
	r_j1.Mov(tmp);
	result.Mov(0);
	while(r_j1.Cmp(0)!=0)
	{
		q.Mov(q.Mul(s_1));
		result.Mov(s_2.Sub(q));
		s_2.Mov(s_1);
		s_1.Mov(result);

		q.Mov(r_j.Div(r_j1));
		tmp.Mov(r_j.Mod(r_j1));
		r_j.Mov(r_j1);
		r_j1.Mov(tmp);
		
	}
	result.Mov(result.Add(A));
	return r_j;
}
//file://蒙哥马利算法求:Y=X.Mon(A,B),使满足:X^A mod B=Y
//file://俺估计就是高中学过的反复平方法
CBigInt CBigInt::Mon(CBigInt& A, CBigInt& B)
{
	CBigInt X(base),Y(base),Z(base);
	int i;
	unsigned long tmp,myk;
	long k;
	X.Mov(1);
	Y.Mov(*this);
	Z.Mov(A);
	while(Z.Cmp(0)!=0)
	{
		Z.Mov(Z.Div(2,k));
		if(k!=0)
		{
			X.Mov(X.Mul(Y));
			X.Mov(X.Mod(B));
		}
		Y.Mov(Y.Mul(Y));
		Y.Mov(Y.Mod(B));
	}
	return X;
	/*
	if(this->m_nLength==1)//小底数的模乘方
	{
	}
	else//
	{
	*/
		
		Y.Mov(this->Mod(B));
		X.Mov(Y);
		Z.Mov(A);
		if(base==100000000)
		{
			myk=0x4000000;
		}
		else
		{
			myk=0x80000000;
		}
		//处理最高位
		tmp=Z.m_ulvalue[Z.m_nLength-1];
		k=myk;
		while((k&tmp)==0)
		{
			k>>=1;
		}
		k>>=1;
		while(k!=0)
		{
			Y.Mov(Y.Mul(Y));
			Y.Mov(Y.Mod(B));
			if(k&tmp)
			{
				Y.Mov(Y.Mul(X));
				Y.Mov(Y.Mod(B));
				
			}
			k>>=1;
		}
		//处理剩下的各个位
		for(i=Z.m_nLength-2;i>=0;i--)
		{
			tmp=Z.m_ulvalue[i];
			k=myk;
			while(k!=0)
			{
				Y.Mov(Y.Mul(Y));
				Y.Mov(Y.Mod(B));
				if(k&tmp)
				{
					Y.Mov(Y.Mul(X));
					Y.Mov(Y.Mod(B));
				}
				k>>=1;
			}
		}
		return Y;
		/*
		while((Z.m_nLength!=1)||Z.m_ulvalue[0])
		{
			if(Z.m_ulvalue[0]&1)
			{
				Z.Mov(Z.Sub(1));
				X.Mov(X.Mul(Y));
				X.Mov(X.Mod(B));
			}
			else
			{
				Z.Mov(Z.Div(2));
				Y.Mov(Y.Mul(Y));
				Y.Mov(Y.Mod(B));
			}
		}
		*/
		return X;
	//}
}

//小指数的模乘方
CBigInt CBigInt::Mon(unsigned int A,CBigInt& B)
{
	CBigInt result(this->base),tmp_base(this->base),tmp_this(this->base);
	unsigned long k=0x8000;
	if(B.Cmp(0)==0)//除数为0
	{
		result.Clear0();
		return result;
	}
	if(B.Cmp(1)==0)//模==1  剩余为0
	{
		result.Clear0();
		return result;
	}
	if(A==0)//指数为0
	{
		result.Mov(1);
		return result;
	}
	if(this->Cmp(0)==0)
	{
		result.Clear0();
		return result;
	}
	tmp_base.Mov(this->Mod(B));
	tmp_this.Mov(tmp_base);
	while((A&k)==0)
	{
		k>>=1;
	}
	k>>=1;
	while(k!=0)
	{
		tmp_base.Mov(tmp_base.Mul(tmp_base));
		tmp_base.Mov(tmp_base.Mod(B));
		if(A&k)
		{
			tmp_base.Mov(tmp_base.Mul(tmp_this));
			tmp_base.Mov(tmp_base.Mod(B));
		}
		k>>=1;
	}
	return tmp_base;
}

//file://错误处理
void PrintErr(int Errnum)
//void PrintErr(string& str)
{
	//1:表示溢出,超出了最大能承受的范围
	if(Errnum==1)
	{
		cout<<"Digits execd the largest number ,please redefine the BI_MAXLEN"<<endl;
	}
   //cout<<str<<endl;
}

int CBigInt::Is_Even()
{
	if(this->m_ulvalue[0]%2==0)
		return 1;
	else
		return 0;
}
CBigInt CBigInt::Gcd(CBigInt A)
{
	CBigInt temp,tmp_this,tmp_A;
	tmp_this.Mov(*this);
	if(tmp_this.Cmp(tmp_A)<0)
	{
		temp.Mov(tmp_this);
		tmp_this.Mov(tmp_A);
		tmp_A.Mov(temp);
	}
	while(tmp_A.Cmp(0)!=0)
	{
		temp.Mov(tmp_this.Mod(tmp_A));
		tmp_this.Mov(tmp_A);
		tmp_A.Mov(temp);
	}
	return tmp_this;
}

	//生成随机数
void CBigInt::Rand(unsigned long bigint_len)
{
	unsigned long temp,chengshu;
	this->Clear0();
	srand((unsigned )time(NULL));
	temp=rand()%9973;
	temp*=10000;
	temp+=rand()%9973;

	this->Mov(temp);
	while(this->m_nLength<bigint_len)
	{
		chengshu=rand()%9973;
		chengshu*=10000;
		chengshu+=rand()%9973;
		this->Mul(chengshu);
	}
	if(this->m_ulvalue[0]%2==0)
		this->m_ulvalue[0]++;
}

//64位随机数初始化
CBigInt CBigInt::Seed(CBigInt seed_l)
   {
	   int len=seed_l.m_nLength>4?4:seed_l.m_nLength;
		A64.InPutFromStr(a,10);
		M.InPutFromStr(b,10);
		Buff64.Mov(Seed64);
		for(int i=0;i<=len;i++)
		{
			Seed64.m_ulvalue[i]=seed_l.m_ulvalue[i];
		}
		return Buff64;
   }

   //64位随机数生成
CBigInt CBigInt::Rand64(void)
   {
	   Seed64.Mov(Seed64.Mov(A64));
		Seed64.Mov(Seed64.Add(1));
		Seed64.Mov(Seed64.Mod(M));
		return Seed64;
   };

/*

最后需要说明的是因为在VC里面存在一个__int64类型可以
用来计算进位与借位值,所以将大数当作0x100000000进制
进行运算是可能的,而在其他编译系统中如果不存在64位
整形,则可以采用0x40000000进制,由于在0x40000000
进制中,对任何两个“数字”进行四则运算,结果都在
0x3fffffff*03fffffff之间,小于0xffffffff,都可以用
一个32位无符号整数来表示。事实上《楚汉棋缘》采用的
freelip大数库正是运用了0x40000000进制来表示大数的,
所以其反汇编后大数的值在内存中表现出来有些“奇怪”。
 */

⌨️ 快捷键说明

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