2008-04-28 13:59
这里给出的代码不是最终的,不可避免的存在一些问题。如果要用这些代码的话,
请参考源码文件。
A. 加密解密
//gjsRSA.h的内容如下===========================================
#ifndef _gjs_RSA_H
#define _gjs_RSA_H
#define g_ENC_KEY 65537//3//7
gChar gGenerateKey(gBigInt *n,gBigInt *e,gBigInt *d);
char* gEncRSA(unsigned char* data, gBigInt* e, gBigInt* n,\
unsigned long inlen,unsigned long* outlen);//加密
char* gDecRSA(unsigned char* data,gBigInt* e, gBigInt* n,\
unsigned long inlen,unsigned long* outlen);//解密
#endif
//gjsRSA.cpp的内容如下===========================================
#include "gjsBigInt.h"
#include "gjsPrime.h"
#include "gjsRSA.h"
#include "stdlib.h"
#include "mem.h"
gChar gGenerateKey(gBigInt *n,gBigInt *e,gBigInt *d)
{//生成密钥
gBigInt p,q,t;
if(n==NULL || e==NULL || d==NULL)
return 0;
gMovInt(n,0);
gMovInt(e,0);
gMovInt(d,0);
gGeneratePrime(&p);//生成p
do{//生成q
gGeneratePrime(&q);
}while(gCmp(&p,&q)==0);
gMov(n,&p);
gMul(n,&q);//n=pq
gSubInt(&p,1);//p-1
gSubInt(&q,1);//q-1
gMul(&p,&q);//(p-1)(q-1)
/*do{//生成和(p-1)(q-1)互素的e
gGeneratePrime(e);
gMov(&t,e);
gGcd(&t,&p);
}while(gCmpInt(&t,1)!=0);*/
if(g_ENC_KEY<g_UINT_MAX)
gMovInt(e,g_ENC_KEY);//
else
{//溢出
gMovInt(e,g_UINT_MAX);
gAddInt(e,g_ENC_KEY-g_UINT_MAX);
}
gMov(d,e);
gEuc(d,&p);//ed % (p-1)(1-1)=1
return 1;
}
char* gEncRSA(unsigned char *data, gBigInt *e, gBigInt *n,\
unsigned long inlen,unsigned long *outlen)
{//加密
char *ret,*p;
int tn=0,tn1=0,rlen=0,i,j;
gBigInt tbi;
if(data==NULL || e==NULL || n==NULL || inlen==0)
return NULL;
if(gCmpInt(e,0)==0 || gCmpInt(n,0)==0)
return NULL;
gMov(&tbi,n);
while(gCmpInt(&tbi,0)!=0)
{//计算n的位数(字节数)
gDivInt(&tbi,0x100);
tn++;
}
tn1=tn-1;
rlen=inlen/tn1;
if(inlen%tn1!=0)
rlen=rlen+1;
rlen=rlen*tn+4;
*outlen=rlen;//密文长度
if((ret=(char*)malloc(rlen+1))==NULL)
return NULL;//开辟内存失败
memset(ret,0,rlen+1);
p=ret;//把明文长度保存起来
*p=inlen>>24;p++;
*p=inlen>>16;p++;
*p=inlen>>8;p++;
*p=inlen;p++;
for(i=0;i<inlen;i=i+tn1)
{//将明文分组
j=0;gMovInt(&tbi,0);
while(j<tn1 && (i+j)<inlen)
{//提取一组明文
gMulInt(&tbi,0x100);
gAddInt(&tbi,*(data+i+j));
j++;
}
gMon(&tbi,e,n);//加密运算
for(j=0;j<tn;j++)
{//将密文保存起来
*(p+tn-j-1)=(char)tbi.value[0];
gDivInt(&tbi,0x100);
}
p=p+tn;
}
return ret;
}
char* gDecRSA(unsigned char *data,gBigInt *d, gBigInt *n,\
unsigned long inlen,unsigned long *outlen)
{//解密
char *ret,*p;
int tn=0,tn1=0,rlen=0,tlen=0,i,j;
gBigInt tbi;
if(data==NULL || d==NULL || n==NULL)
return NULL;
if(gCmpInt(d,0)==0 || gCmpInt(n,0)==0)
return NULL;
gMov(&tbi,n);
while(gCmpInt(&tbi,0)!=0)
{//计算n的位数(字节数)
gDivInt(&tbi,0x100);
tn++;
}
tn1=tn-1;
rlen=(*data<<24)+(*(data+1)<<16)+(*(data+2)<<8)+*(data+3);
*outlen=rlen;//密文长度
tlen=rlen/tn1;
if(rlen%tn1!=0)
tlen=tlen+1;
tlen=tlen*tn+4;
if(inlen<tlen)
return NULL;//校验失败
else inlen=tlen;
if((ret=(char*)malloc(rlen+1))==NULL)
return NULL;//开辟内存失败
memset(ret,0,rlen+1);
p=ret;
for(i=4;i<inlen;i=i+tn)
{//将密文分组
j=0;gMovInt(&tbi,0);
while(j<tn && (i+j)<inlen)
{//提取一组密文
gMulInt(&tbi,0x100);
gAddInt(&tbi,*(data+i+j));
j++;
}
gMon(&tbi,d,n);//解密运算
for(j=0;j<tn1 && rlen>0;j++,rlen--)
{//将明文保存起来
tlen=rlen<(tn1-j)?rlen:(tn1-j);
*(p+tlen-1)=(char)tbi.value[0];
gDivInt(&tbi,0x100);
}
p=p+tn1;
}
return ret;
}
B. 素数的生成
//gjsPrime.h的内容如下===========================================
#ifndef _gjs_PRIME_H_
#define _gjs_PRIME_H_
#include "gjsBigInt.h"
#define g_INCREASE 1
#define g_DECREASE 0
#define g_PRIME_BIT_NUM 4 //大素数的位数
#define g_SMALL_PRIME_BIT_NUM 1 //小随机数的位数
#define g_RM_TEST_NUM 5 //Rabin-Miller检测次数
gChar gIsNotPrime(gBigInt *p);//判断p是否可能是素数
gChar gRabinMillerTest(gBigInt *p,int tNum);//Rabin-Miller检测
gChar gGeneratePrime(gBigInt *p);//随机产生一个大素数
gChar gGeneratePrimeEx(gBigInt *p, int flg);//顺序搜大素数
#endif
//gjsPrime.cpp的内容如下===========================================
#include "gjsPrime.h"
#include "gjsBigInt.h"
#include "stdlib.h"
gChar gIsNotPrime(gBigInt *p)
{//判断p是否是素数
#define g_SMALL_PRIME_NUM 100
int i=0;
const gUInt sPrime[g_SMALL_PRIME_NUM]={ 2, 3, 5, 7, 11, 13,17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89,97,101,103,107,109,113,
127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,
223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,
313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,
421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541};
gBigInt tbi;
if(p==NULL || p->len<=0)
return 1;
if(gCmpInt(p,1)==0)//p==1
return 1;
gMovInt(&tbi,0);
for(i=0;i<g_SMALL_PRIME_NUM;i++)
{
gMov(&tbi,p);
if(gCmpInt(&tbi,sPrime[i])==0)
return 0;//本身是小素数
gModInt(&tbi,sPrime[i]);//取余
if(gCmpInt(&tbi,0)==0)
return sPrime[i];
}
return 0;
}
gChar gRabinMillerTest(gBigInt *p,int tNum)
{//Miller-Rabin随机性素数测试算法
int i=0,j=0,k=0,n=0,b=0;
gBigInt tbi,tbi1,a,m,z,p1;
if(p==NULL || gCmpInt(p,1)==0)
return 0;
gMov(&p1,p);
p1.sign=1;//置正
gMovInt(&tbi,0);
gMovInt(&tbi1,0);//暂存用
gMovInt(&a,0);//a=0
gMovInt(&m,0);//m=0
gMovInt(&z,0);
n=0;b=0;
gMov(&tbi,&p1);
while(gCmpInt(&tbi,0)!=0)
{//计算大数的位数n
gDivInt(&tbi,2);
n++;
}
gMov(&tbi,&p1);//p
gMov(&tbi1,&tbi);//p
gSubInt(&tbi1,1);//p=p-1
gModInt(&tbi1,2);//t=(p-1)%2
while(gCmpInt(&tbi1,0)==0)
{//求2整除p-1的次数b
b=b+1;
gDivInt(&tbi,2);//p=(p-1)/2
gMov(&tbi1,&tbi);
gModInt(&tbi1,2);//t=(p-1)%2
}
//求满足n=1+(2^b)*m的m
gMovInt(&m,n-1);//m=n-1
gMovInt(&tbi1,1);
for(i=0;i<b;i++)//(2^b)
gMulInt(&tbi1,2);
gDiv(&m,&tbi1);//m=(n-1)/(2^b)
gMov(&tbi1,&p1);
gSubInt(&tbi1,1);//p-1
for(i=0;i<tNum;i++)
{//循环检测N次
a.len=0;
for(j=0;j<g_SMALL_PRIME_BIT_NUM;j++)
{//产生一个小随机数a
a.value[j]=(((gUInt)rand())<<16)+(gUInt)rand();
a.len++;
}
gMod(&a,&tbi1);//使a<p-1
gAddInt(&a,1);//a=a%(p-1)+1
/*
gMov(&tbi,&a);
gMon(&tbi,&m,&p1);//z=(a^m)%p
if(!gCmpInt(&tbi,1)==0 && !gCmp(&tbi,&tbi1)==0)
{
for(j=0;j<b;j++)
{
if(gCmpInt(&tbi,1)==0)
return 0;//z==1
if(gCmp(&tbi,&tbi1)==0)
break;//z==p-1
gMul(&tbi,&tbi);//z=z^2
gMod(&tbi,&p1);//z=z%p
}
if(gCmp(&tbi,&tbi1)!=0)
return 0;//z!=p-1
}*/
gMovInt(&z,1);
for(j=n-1;j>=0;j--)
{
gMov(&tbi,&z);//x=z;
gMul(&z,&z);//z=(z*z) % p;
gMod(&z,&p1);
if(gCmpInt(&z,1)==0 && gCmpInt(&tbi,1)!=0
&& gCmp(&tbi,&tbi1)!=0)
return 0;
gMov(&tbi,&tbi1);
for(k=j;k>0;k--)
gDivInt(&tbi,2);//(p-1)>>j
if((tbi.value[0] & 0x01)>0)
{
gMul(&z,&a);
gMod(&z,&p1);
}
}
if(gCmpInt(&z,1)!=0)
return 0;
}
return 1;
}
gChar gGeneratePrime(gBigInt *p)
{//随机生成一个大素数p
int i=0;
if(p==NULL) return 0;
gMovInt(p,0);
do{//循环
do{
for(i=0;i<g_PRIME_BIT_NUM;i++)
{//产生N个随机位
p->value[i]=(((gUInt)rand())<<16)+(gUInt)rand();
}
p->value[i-1]=p->value[i-1] | 0x8000;//最高位置1
p->value[0]=p->value[0] | 0x0001;//最低位置1
p->len=g_PRIME_BIT_NUM;
}while(gIsNotPrime(p));//不是素数继续找
}while(!gRabinMillerTest(p,g_RM_TEST_NUM));//Rabin-Miller检测
//while(!Miller_Rabin(p->value[0],g_RM_TEST_NUM));
return 1;
}
gChar gGeneratePrimeEx(gBigInt *p, int flg)
{//找p附近的大素数
if(p==NULL) return 0;
do{//循环
do{
if(flg==g_INCREASE)
gAddInt(p,1);
else if(flg==g_DECREASE)
gSubInt(p,1);
else return 0;
}while(gIsNotPrime(p));//不是素数继续找
}while(!gRabinMillerTest(p,g_RM_TEST_NUM));//Rabin-Miller检测
//while(!Miller_Rabin(p->value[0],g_RM_TEST_NUM));
return 1;
}
C. 大数的运算
//gjsBigInt.h的内容如下===========================================
#ifndef _gjs_BIG_INT_H_
#define _gjs_BIG_INT_H_
#define NULL 0
#define OCT_FLG 8
#define DEC_FLG 10
#define HEX_FLG 16
#define BIG_INT_MAX_LEN 80
#define gUIntEx unsigned long
#define gUInt unsigned short
#define gSInt signed short
#define gChar signed char
#define g_UINT_MAX 0xffff
typedef struct _gBigInt
{//大数的结构
int len; //长度 0 - (BIG_INT_MAX_LEN-1)
int sign; //符号 支持带正负号的大数运算 正为1 负为-1
gUInt value[BIG_INT_MAX_LEN];//数值 低位放在value[0]
} gBigInt;
gChar gStr2BigInt(gBigInt *gbi,char *str,int flg);
gChar gBigInt2Str(char *str,gBigInt *gbi,int flg);
//gChar gHexStr2BigInt(gBigInt *gbi,char *str);//16进制与大数间转换
//gChar gBigInt2HexStr(char *str,gBigInt *gbi);
gUInt gIntMul(gUInt *a, gUInt b);//64位整数乘除
gUInt gIntDiv(gUInt *ah, gUInt *al, gUInt b);
gChar gCmp(gBigInt *a, gBigInt *b);//比较
gChar gCmpEx(gBigInt *a, gBigInt *b);
gChar gCmpInt(gBigInt *a, gUInt b);
gChar gMov(gBigInt *a, gBigInt *b);//赋值
gChar gMovInt(gBigInt *a, gUInt b);
gChar gAdd(gBigInt *a, gBigInt *b);//加
gChar gAddInt(gBigInt *a, gSInt b);
gChar gSub(gBigInt *a, gBigInt *b);//减
gChar gSubInt(gBigInt *a, gSInt b);
gChar gMul(gBigInt *a, gBigInt *b);//乘
gChar gMulInt(gBigInt *a, gSInt b);
gChar gDiv(gBigInt *a, gBigInt *b);//除
gChar gDivInt(gBigInt *a, gSInt b);
gChar gMod(gBigInt *a, gBigInt *b);//取余
gChar gModInt(gBigInt *a, gSInt b);
gChar gEuc(gBigInt *a,gBigInt *b);//欧几里德算法
gChar gMon(gBigInt *a, gBigInt *b, gBigInt *c);//蒙格马利算法
gChar gGcd(gBigInt *a, gBigInt *b);//最大公约数
#endif// _gjs_BIG_INT_H__
//gjsBigInt.cpp的内容如下===========================================
#include "stdio.h"
#include "string.h"
#include "gjsBigInt.h"
//------------------------------------------------------------------------------
gChar gStr2BigInt(gBigInt *gbi,char *str,int flg)
{//把flg进制形式的字符串转换成大数
int i=0,j=0,k=0,len=0;
if(gbi==NULL || str==NULL || flg==0)
return 0;
gMovInt(gbi,0);//清零
len=strlen(str);
if(*str=='-')
{ gbi->sign=-1;j=1; }
else if(*str=='+')
{ gbi->sign=1;j=1; }
else if(*str=='\0')
return 0;
else j=0;
for(i=j;i<len;i++)
{
gMulInt(gbi,flg);
if(str[i]<='9'&&str[i]>='0')
k=str[i]-'0';
else if(str[i]<='F'&&str[i]>='A')
k=str[i]+10-'A';
else if(str[i]<='f'&&str[i]>='a')
k=str[i]+10-'a';
else return 0;
gAddInt(gbi,k*gbi->sign);
}
return 1;
}
gChar gBigInt2Str(char *str,gBigInt *gbi,int flg)
{//把大数转换成flg进制形式的字符串
int i=0,len=0;
char tstr[BIG_INT_MAX_LEN*HEX_FLG+1];
gBigInt X,Y;
if(str==NULL || gbi==NULL || flg==0)
return 0;
strcpy(str,"");
memset(tstr,0,BIG_INT_MAX_LEN*HEX_FLG+1);
gMov(&X,gbi);
gMovInt(&Y,0);
tstr[0]='0';//先置零
while(X.value[X.len-1]>0)
{
gMov(&Y,&X);
gDivInt(&X,flg);
gModInt(&Y,flg);
if(Y.value[0]<10)
tstr[i++]=Y.value[0]+'0';
else if(Y.value[0]<16)
tstr[i++]=Y.value[0]-10+'A';
else return 0;
}
if(gbi->sign==-1)
str[0]='-';
else if(gbi->sign==1)
str[0]='+';
else return 0;
len=strlen(tstr);
for(i=0;i<len;i++)
str[i+1]=tstr[len-1-i];
return 1;
}
//------------------------------------------------------------------------------
/*gChar gHexStr2BigInt(gBigInt *gbi,char *str)
{//把16进制形式的字符串转换成大数
int i=0,len=0,j=0,k=0;
char *tstr;
if((gbi==NULL)||(str==NULL))
return 0;
gMovInt(gbi,0);//先清零
tstr=str;//处理 正负号
if(*tstr=='-')
{ gbi->sign=-1;tstr++; }
else if(*tstr=='+')
{ gbi->sign=1;tstr++; }
else if(*tstr=='\0')
return 0;
len=strlen(tstr);
for(i=0;i<len;i++)
{//提前处理 有非法字符则退出
if(tstr[i]>='0' && tstr[i]<='9')
tstr[i]=tstr[i]-'0';
else if(tstr[i]>='a' && tstr[i]<='f')
tstr[i]=str[i]-'a'+10;
else if(tstr[i]>='A' && tstr[i]<='F')
tstr[i]=tstr[i]-'A'+10;
else return 0;
}
j=0;
for(i=len-1;i>=0;i=i-8)
{//4字节组成大数的一位
for(k=7;k>=0;k--)
if(i-k>=0)
gbi->value[j]=(gbi->value[j]<<4)+tstr[i-k];
j++;
}
gbi->len=j;
return 1;
}
gChar gBigInt2HexStr(char *str,gBigInt *gbi)
{//把大数转换成16进制形式的字符串 str要预先分配
int i=0,len=0,j=0,k=0;
if((str==NULL)||(gbi==NULL)||(gbi->len <1))
return 0;
j=0;//处理 正负号
if(gbi->sign==-1)
str[j++]='-';
else if(gbi->sign==1)
str[j++]='+';
else return 0;
k=7;//处理最高位
while(k>=0 && (str[j]=(char)(gbi->value[gbi->len-1] >> (4*k)) &
0x0F)==0)
{ k--; }//清掉最高位前的所有零
j++;//处理最高非零位
for(i=k-1;i>=0;i--)
str[j++]=(char)(gbi->value[gbi->len-1] >> (4*i)) & 0x0F;
for(i=gbi->len-2;i>=0;i--)
{//逐位分解大数
for(k=7;k>=0;k--)
str[j++]=(char)(gbi->value[i] >> (4*k)) & 0x0F;
}
for(i=1;i<j;i++)
{//把数字变成字符
if(str[i]<10)
str[i]=str[i]+'0';
else if(str[i]<16)
str[i]=str[i]-10+'A';
else return 0;
}
return 1;
} */
//------------------------------------------------------------------------------
gUInt gIntMul(gUInt *a, gUInt b)
{//正数a乘正数b 结果放在a中 进位作为返回值
gUIntEx ttt=0;
gUInt carry=0;
if(a==NULL) return 0;
ttt=*a;ttt=ttt*b;
*a=(gUInt)ttt;
carry=(gUInt)(ttt>>8*sizeof(gUInt));
return carry;
/* gUInt t1=0,t2=0,carry=0,n=0;
if(a==NULL) return 0;
t1=*a; *a=0; n=b;//t2高t1低
if(t1==0||n==0) return 0;//有个为零
while(n!=0)
{//循环移位相乘
if(n & 0x01)
{//位为1则累加
*a=*a+t1;
if(*a<t1)//有进位
carry++;
carry=carry+t2;
}
n=n>>1;
t2=t2 << 1;//先将高位左移
if(t1 & 0x80000000)//有进位
t2=t2 | 0x0001;
t1=t1 << 1;
}
return carry;*/
}
gUInt gIntDiv(gUInt *ah, gUInt *al, gUInt b)
{//整数ah和al作为64位除以b 结果放在ah和al中 余数作为返回值
gUIntEx ttt=0;
gUInt carry=0;
if(ah==NULL || al==NULL || ah==al) return 0;
ttt=*ah;
ttt=(ttt<<8*sizeof(gUInt))+*al;
carry=ttt%b;
ttt=ttt/b;
*al=(gUInt)ttt;
*ah=(gUInt)(ttt>>8*sizeof(gUInt));
return carry;
/* gUInt s1=0,surplus=0;
if(ah==NULL || al==NULL || ah==al) return 0;
s1=*ah%b; *ah=*ah/b;//先处理高位
surplus=*al%b;
*al=*al/b;
while((s1!=0)||(surplus>b))
{//循环借位
if(surplus<b)
{//不够则借位
*al=*al+1;s1--;
surplus=g_UINT_MAX-b+surplus+1;
}
else
{//大则除
*al=*al+surplus/b;
surplus=surplus%b;
}
}
return surplus; */
}
//------------------------------------------------------------------------------
gChar gCmp(gBigInt *a, gBigInt *b)
{//比较两个大数 不考虑符号
int i=0;
if(a==NULL || b==NULL) return 0;
if(a->len > b->len)
return 1;//大于
else if(a->len < b->len)
return -1;//小于
else for(i=a->len-1;i>=0;i--)
{//长度相等
if(a->value[i]>b->value[i])
return 1;
if(a->value[i]<b->value[i])
return -1;
}
return 0;
}
gChar gCmpEx(gBigInt *a, gBigInt *b)
{//比较两个大数 考虑符号
int i=0,ret=0;
if(a==NULL || b==NULL) return 0;
if(a->sign > b->sign)
return 1;
else if(a->sign < b->sign)
return -1;
else
{//符号相同
ret=gCmp(a,b);
if(a->sign==-1)
ret=-ret;//两个都为负数
return ret;
}
}
gChar gCmpInt(gBigInt *a, gUInt b)
{//比较大数和整数
int i=0,ret=0;
if(a==NULL) return 0;
if(a->len<=0) return -1;
if(a->len >1) return 1;
if(a->value[0]>b)
return 1;
else if(a->value[0]<b)
return -1;
else return 0;
}
//------------------------------------------------------------------------------
gChar gMov(gBigInt *a, gBigInt *b)
{//将大数b赋值给大数a
int i=0;
if(a==NULL || b==NULL) return 0;
a->len=b->len;
a->sign=b->sign;
for(i=0;i<BIG_INT_MAX_LEN;i++)
a->value[i]=b->value[i];
return 1;
}
gChar gMovInt(gBigInt *a, gUInt b)
{//将整数h和l赋值给大数a(h和l相当于64位)
int i=0;
if(a==NULL) return 0;
a->len=1;
a->sign=1;
a->value[0]=b;
for(i=a->len;i<BIG_INT_MAX_LEN;i++)
a->value[i]=0;
return 1;
}
//------------------------------------------------------------------------------
gChar gAdd(gBigInt *a, gBigInt *b)
{//将大数a和大数b相加 结果放在a中
int i=0,carry=0;
gUInt tmp=0;
if(a==NULL || b==NULL) return 0;
if(a->sign==b->sign)
{
if(a->len < b->len)
a->len = b->len;
for(i=0; i < a->len; i++)
{
tmp=a->value[i];
a->value[i]=a->value[i]+b->value[i]+carry;
if(tmp > a->value[i])
carry=1;//有溢出 要进位
else carry=0;
}
if(a->len < BIG_INT_MAX_LEN)
{
a->value[a->len]=carry;
a->len=a->len+carry;
}
}
else
{
b->sign=- b->sign;
gSub(a,b);
}
return 1;
}
gChar gAddInt(gBigInt *a, gSInt b)
{//将大数a和整数b相加 结果放在a中
int i=0,carry=0;
gUInt tmp=0;
//if(a==NULL) return 0;
if(b==0) return 1;
if(a->sign*b>=0)
{
if(b<0) b=-b;
tmp=a->value[0];
a->value[0]=a->value[0]+b;
if(tmp > a->value[i])
{
i=1;
while(a->value[i]==g_UINT_MAX)
{ a->value[i]=0;i++; }
a->value[i]++;
//if(a->len < BIG_INT_MAX_LEN)
if((a->value[i]==1)&&(a->len < BIG_INT_MAX_LEN))
a->len=i+1;
}
}
else gSubInt(a,-b);
return 1;
}
//------------------------------------------------------------------------------
gChar gSub(gBigInt *a, gBigInt *b)
{//将大数a和大数b相减 结果放在a中
int i=0,cmp=0,len=0,carry=0;
gUInt *s,*d;
if(a==NULL || b==NULL) return 0;
if(a->sign==b->sign)
{//同号
cmp=gCmp(a,b);
if(cmp==0)
{//相等
gMovInt(a,0);
return 1;
}
else if(cmp>0)
{//不考虑符号大于
s=a->value;
d=b->value;
len=a->len;
}
else if(cmp<0)
{//不考虑符号小于
s = b->value;
d = a->value;
len=b->len;
a->sign=- a->sign;
}
else return 0;
for(i=0;i<len;i++)
{
if((s[i]-carry)>=d[i])
{//不要借位
a->value[i]=s[i]-carry-d[i];
carry=0;
}
else
{//要借位
a->value[i]=(gUInt)(g_UINT_MAX-carry-d[i]+s[i]+1);
carry=1;
}
}
while(a->value[len-1]==0) len--;
a->len=len;
}
else
{
b->sign=-b->sign;
gAdd(a,b);
}
return 1;
}
gChar gSubInt(gBigInt *a, gSInt b)
{//将大数a和整数b相减 结果放在a中
int i=0;
if(a==NULL) return 0;
//if(b==0) return 1;
if(a->sign*b>=0)
{
if(b<0) b=-b;
if(a->value[0] >= (gUInt)b)
{
a->value[0] = a->value[0] - b;
return 1;
}
else if(a->len==1)
{
a->value[0]=b - a->value[0];
a->sign= - a->sign;
return 1;
}
a->value[0]=(gUInt)(g_UINT_MAX-b+a->value[0]+1);
i=1;
while(a->value[i]==0)
{ a->value[i]=g_UINT_MAX;i++; }
if(a->value[i]==1)
a->len--;
a->value[i]--;
}
else gAddInt(a,-b);
return 1;
}
//------------------------------------------------------------------------------
gChar gMul(gBigInt *a, gBigInt *b)
{//将大数a和大数b相乘 结果放在a中
int i=0,j=0,k=0;
gUInt carry=0,tc=0;
gBigInt R,T;
if(a==NULL || b==NULL) return 0;
gMovInt(&R,0);
gMovInt(&T,0);
for(i=0;i<b->len;i++)
{//以b的长度循环
carry=0;
T.len=a->len;
for(j=0;j<a->len;j++)
{//b的一位乘以a
T.value[j]=a->value[j];
tc=gIntMul(&T.value[j],b->value[i]);
T.value[j]=T.value[j]+carry;
if(T.value[j]<carry) tc=tc+1;//加有进位
carry=tc;
}
if(carry&&(T.len<BIG_INT_MAX_LEN))
{//乘有进位
T.len++;
T.value[T.len-1]=carry;
}
if(T.len<BIG_INT_MAX_LEN-i)
{//移位使低位对齐
T.len=T.len+i;
for(k=T.len-1;k>=i;k--)
T.value[k]=T.value[k-i];
for(k=0;k<i;k++)
T.value[k]=0;
}
gAdd(&R,&T);//累加
}
if(a->sign+b->sign==0)
R.sign=-1;
else R.sign=1;
gMov(a,&R);
return 1;
}
gChar gMulInt(gBigInt *a, gSInt b)
{//将大数a和整数b相乘 结果放在a中
int i=0;
gUInt carry=0,tc=0;
gBigInt T;
gMov(&T,a);
if(a==NULL) return 0;
for(i=0;i< a->len;i++)
{//b乘以a
T.value[i]=a->value[i];
tc=gIntMul(&T.value[i],b);
T.value[i]=T.value[i]+carry;
if(T.value[i]<carry) tc=tc+1;//加有进位
carry=tc;
}
if(carry&&(T.len<BIG_INT_MAX_LEN))
{//乘有进位
T.len++;
T.value[T.len-1]=carry;
}
if(b<0)
T.sign= -T.sign;
gMov(a,&T);
return 1;
}
//------------------------------------------------------------------------------
gChar gDiv(gBigInt *a, gBigInt *b)
{//将大数a和大数b相除 结果放在a中
int len=0,i=0;
gUInt carry=0,th=0,tl=0;
gBigInt X,Y,Z;
if(a==NULL || b==NULL) return 0;
if(gCmpInt(b,0)==0)
return 0;//除数为零
gMovInt(&X,0);
gMovInt(&Z,0);
gMov(&Y,a);
while(gCmp(&Y,b)>0)
{//大数a比大数b大
if(Y.value[Y.len-1]>b->value[b->len-1])
{//大数a的最高位大于大数b的最高位
len=Y.len-b->len;
tl=Y.value[Y.len-1]/(b->value[b->len-1]+1);
th=0;
}
else if(Y.len>b->len)
{//能借到位
len=Y.len-b->len-1;
th=Y.value[Y.len-1];
tl=Y.value[Y.len-2];
if(b->value[b->len-1]==g_UINT_MAX)
{ tl=th;th=0; }
else gIntDiv(&th,&tl,b->value[b->len-1]+1);
}
else
{//除数肯定为1 如75/71
gAddInt(&X,1);
break;
}
gMovInt(&Z,tl);
if(th!=0)
{//..
Z.value[1]=th;
Z.len++;
}
Z.len+=len;
for(i=Z.len-1;i>=len;i--)
Z.value[i]=Z.value[i-len];
for(i=0;i<len;i++)//低位对齐
Z.value[i]=0;
gAdd(&X,&Z);
gMul(&Z,b);
gSub(&Y,&Z);
}
if(gCmp(&Y,b)==0)
gAddInt(&X,1);
if(a->sign+b->sign==0)
X.sign=-1;
else X.sign=1;
gMov(a,&X);
return 1;
}
gChar gDivInt(gBigInt *a, gSInt b)
{//将大数a和整数b相除 结果放在a中
int i=0;
gUInt carry=0,th=0,tl=0;
gBigInt X;
if(a==NULL || b==0) return 0;
gMov(&X,a);
if(X.len==1)
{//只有1位
X.value[0]=X.value[0]/b;
gMov(a,&X);
return 1;
}
for(i=X.len-1;i>=0;i--)
{//从高到低除
th=carry;
tl=X.value[i];
carry=gIntDiv(&th,&tl,b);
X.value[i]=tl;
}
if(X.value[X.len-1]==0)
X.len--;
if(b<0)
X.sign= -X.sign;
gMov(a,&X);
return 1;
}
//------------------------------------------------------------------------------
gChar gMod(gBigInt *a, gBigInt *b)
{//大数a对大数b取余 结果放在a中
int len=0,i=0;
gUInt carry=0,th=0,tl=0;
gBigInt X,Y;
if(a==NULL || b==NULL) return 0;
if(gCmpInt(b,0)==0) return 0;
gMovInt(&Y,0);
gMov(&X,a);
while(gCmp(&X,b)>0)
{//大数a比大数b大
if(X.value[X.len-1]>b->value[b->len-1])
{//大数a的最高位大
len=X.len-b->len;
tl=X.value[X.len-1]/(b->value[b->len-1]+1);
th=0;
}
else if(X.len>b->len)
{//大数a的位数多
len=X.len-b->len-1;
th=X.value[X.len-1];
tl=X.value[X.len-2];
if(b->value[b->len-1]==g_UINT_MAX)
{ tl=th;th=0; }
else gIntDiv(&th,&tl,b->value[b->len-1]+1);
}
else
{//如75%71结果为75-71
gSub(&X,b);
break;
}
gMovInt(&Y,tl);
if(th!=0)
{//..
Y.value[1]=th;
Y.len++;
}
gMul(&Y,b);
Y.len+=len;
for(i=Y.len-1;i>=len;i--)
Y.value[i]=Y.value[i-len];
for(i=0;i<len;i++)
Y.value[i]=0;
gSub(&X,&Y);
}
if(gCmp(&X,b)==0)
gMovInt(&X,0);
gMov(a,&X);
return 1;
}
gChar gModInt(gBigInt *a, gSInt b)
{//大数a对整数b取余 结果放在a中
int i=0;
gUInt carry=0,th=0,tl=0;
if(a==NULL || b==0) return 0;
if(a->len==1)
{//只有1位
a->value[0]=a->value[0] % b;
return 1;
}
for(i=a->len-1;i>=0;i--)
{
th=carry;
tl=a->value[i];
carry=gIntDiv(&th,&tl,b);
}
gMovInt(a,carry);
return 1;
}
//------------------------------------------------------------------------------
gChar gEuc(gBigInt *a,gBigInt *b)
{//欧几里德算法求满足aX mod b=1的X 辗转相除
gBigInt X,Y;
if(a==NULL || b==NULL) return 0;
if(gCmpInt(a,0)==0) return 0;
if(gCmpInt(b,0)==0) return 0;
gMov(&X,a);
gMov(&Y,b);
if((X.len==1)&&(X.value[0]==1))
{//a=1则X=1 ax-by=1
return 1;
}
if((Y.len==1)&&(Y.value[0]==1))
{//b=1则Y=a-1 ax-by=1
gSubInt(&X,1);
gMov(b,&X);
return 1;
}
if(gCmp(&X,&Y)>0)
{//a>b 返回x计算y
gMod(&X,&Y);//X=X%Y
gEuc(&X,&Y);//递归
gMov(&Y,&X);
gMul(&Y,a);
gSubInt(&Y,1);
gDiv(&Y,b);
gMov(b,&Y);
gMov(a,&X);
}
else
{//a<b 返回y计算x
gMod(&Y,&X);//Y=Y%X
gEuc(&X,&Y);//递归
gMov(&X,&Y);
gMul(&X,b);
gAddInt(&X,1);
gDiv(&X,a);
gMov(a,&X);
gMov(b,&Y);
}
return 1;
}
//------------------------------------------------------------------------------
gChar gMon(gBigInt *a, gBigInt *b, gBigInt *c)
{//蒙格马利算法求X=a^b mod c的值
gBigInt X,Y,Z;
if(a==NULL || b==NULL || c==NULL) return 0;
if(gCmpInt(c,0)==0) return 0;
gMovInt(&X,1);
gMov(&Y,a);
gMov(&Z,b);
while((Z.len!=1)||(Z.value[0]!=0))//Z!=0
{//对b进行降阶
if(Z.value[0] & 0x01)
{//b不能整除2
gMul(&X,&Y);
gMod(&X,c);
}
gDivInt(&Z,2);
gMul(&Y,&Y);
gMod(&Y,c);
}
gMov(a,&X);
return 1;
}
gChar gGcd(gBigInt *a, gBigInt *b)
{//最大公约数
gBigInt b1,t;
if(a==NULL || b==NULL) return 0;
gMov(&b1,b);//t=b
gMovInt(&t,0);
do{
gMod(a,&b1);
gMov(&t,a);
gMov(a,&b1);//a,b互换;
gMov(&b1,&t);
}while(gCmpInt(&b1,0)!=0);
return 1;
}