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

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;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值