您的位置:首页 > 编程语言 > C语言/C++

RSA算法的介绍与C语言实现

2012-08-03 11:01 302 查看
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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: