- 論壇徽章:
- 0
|
- 基于以下原因,俺估計(jì)RSA算法會被越來越多的共享軟件采用:
- 1、原理簡潔易懂
- 2、加密強(qiáng)度高
- 3、專利限制已過期
- 4、看雪老大三番五次呼吁共享軟件采用成熟的非對稱加密技術(shù)
- 所以,大家應(yīng)該對RSA算法進(jìn)行深入了解。
- RSA依賴大數(shù)運(yùn)算,目前主流RSA算法都建立在512位到1024位的
- 大數(shù)運(yùn)算之上,所以我們在現(xiàn)階段首先需要掌握1024位的大數(shù)
- 運(yùn)算原理。
- 大多數(shù)的編譯器只能支持到64位的整數(shù)運(yùn)算,即我們在運(yùn)算中
- 所使用的整數(shù)必須小于等于64位,即:0xffffffffffffffff
- 也就是18446744073709551615,這遠(yuǎn)遠(yuǎn)達(dá)不到RSA的需要,于是
- 需要專門建立大數(shù)運(yùn)算庫來解決這一問題。
- 最簡單的辦法是將大數(shù)當(dāng)作字符串進(jìn)行處理,也就是將大數(shù)用
- 10進(jìn)制字符數(shù)組進(jìn)行表示,然后模擬人們手工進(jìn)行“豎式計(jì)算”
- 的過程編寫其加減乘除函數(shù)。但是這樣做效率很低,因?yàn)?024
- 位的大數(shù)其10進(jìn)制數(shù)字個數(shù)就有數(shù)百個,對于任何一種運(yùn)算,
- 都需要在兩個有數(shù)百個元素的數(shù)組空間上做多重循環(huán),還需要
- 許多額外的空間存放計(jì)算的進(jìn)位退位標(biāo)志及中間結(jié)果。當(dāng)然其
- 優(yōu)點(diǎn)是算法符合人們的日常習(xí)慣,易于理解。
- 另一種思路是將大數(shù)當(dāng)作一個二進(jìn)制流進(jìn)行處理,使用各種移
- 位和邏輯操作來進(jìn)行加減乘除運(yùn)算,但是這樣做代碼設(shè)計(jì)非常
- 復(fù)雜,可讀性很低,難以理解也難以調(diào)試。
- 于是俺琢磨了一種介于兩者之間的思路:
- 將大數(shù)看作一個n進(jìn)制數(shù)組,對于目前的32位系統(tǒng)而言n可以取
- 值為2的32次方,即0x10000000,假如將一個1024位的大數(shù)轉(zhuǎn)
- 化成0x10000000進(jìn)制,它就變成了32位,而每一位的取值范圍
- 就不是0-1或0-9,而是0-0xffffffff。我們正好可以用一個無
- 符號長整數(shù)來表示這一數(shù)值。所以1024位的大數(shù)就是一個有32
- 個元素的unsigned long數(shù)組。而且0x100000000進(jìn)制的數(shù)組排列
- 與2進(jìn)制流對于計(jì)算機(jī)來說,實(shí)際上是一回事,但是我們完全
- 可以針對unsigned long數(shù)組進(jìn)行“豎式計(jì)算”,而循環(huán)規(guī)模
- 被降低到了32次之內(nèi),并且算法很容易理解。
- 例如大數(shù)18446744073709551615,等于“ffffffff ffffffff”,
- 它就相當(dāng)于10進(jìn)制的“99”:有兩位,每位都是ffffffff。
- 而大數(shù)18446744073709551616,等于“00000001 00000000
- 00000000”,它就相當(dāng)于10進(jìn)制的“100”:有三位,第一位是
- 1,其它兩位是0。如果我們要計(jì)算18446744073709551616
- -18446744073709551615,就類似于100-99:
-
- 00000001 00000000 00000000
- - ffffffff ffffffff
- -----------------------------
- = 0 0 1
- 所以,可以聲明大數(shù)類如下:
- /****************************************************************/
- //大數(shù)運(yùn)算庫頭文件:BigInt.h
- //作者:afanty@vip.sina.com
- //版本:1.0 (2003.4.26)
- //說明:適用于MFC
- /****************************************************************/
- #define BI_MAXLEN 40
- #define DEC 10
- #define HEX 16
- class CBigInt
- {
- public:
- int m_nSign; //記錄大數(shù)的符號,支持負(fù)值運(yùn)算
- int m_nLength; //記錄0x10000000進(jìn)制的位數(shù),0-40之間,相當(dāng)于2進(jìn)制的0-1280位
- unsigned long m_ulvalue[BI_MAXLEN]; //記錄每一位的“數(shù)字”
- CBigInt();
- ~CBigInt();
- //將大數(shù)賦值為另一個大數(shù)
- CBigInt& Mov(CBigInt& A);
- //將大數(shù)賦值為編譯器能夠理解的任何整形常數(shù)或變量
- CBigInt& Mov(unsigned __int64 A);
- //比較兩個大數(shù)大小
- int Cmp(CBigInt& A);
- //計(jì)算兩個大數(shù)的和
- CBigInt Add(CBigInt& A);
- //重載函數(shù)以支持大數(shù)與普通整數(shù)相加
- CBigInt Add(long A);
- //計(jì)算兩個大數(shù)的差
- CBigInt Sub(CBigInt& A);
- //重載函數(shù)以支持大數(shù)與普通整數(shù)相減
- CBigInt Sub(long A);
- //計(jì)算兩個大數(shù)的積
- CBigInt Mul(CBigInt& A);
- //重載函數(shù)以支持大數(shù)與普通整數(shù)相乘
- CBigInt Mul(long A);
- //計(jì)算兩個大數(shù)的商
- CBigInt Div(CBigInt& A);
- //重載函數(shù)以支持大數(shù)與普通整數(shù)相除
- CBigInt Div(long A);
- //計(jì)算兩個大數(shù)相除的余數(shù)
- CBigInt Mod(CBigInt& A);
- //重載函數(shù)以支持大數(shù)與普通整數(shù)相除求模
- long Mod(long A);
- //將輸入的10進(jìn)制或16進(jìn)制字符串轉(zhuǎn)換成大數(shù)
- int InPutFromStr(CString& str, const unsigned int system);
- //將大數(shù)按10進(jìn)制或16進(jìn)制格式輸出到字符串
- int OutPutToStr(CString& str, const unsigned int system);
- //歐幾里德算法求:Y=X.Euc(A),使?jié)M足:YX mod A = 1
- CBigInt Euc(CBigInt& A);
- //蒙哥馬利算法求:Y=X.Mon(A,B),使?jié)M足:X^A mod B = Y
- CBigInt Mon(CBigInt& A, CBigInt& B);
- };
- 注意以上函數(shù)的聲明格式,完全遵循普通整數(shù)運(yùn)算的習(xí)慣,例如大數(shù)
- Y=X+Z 相當(dāng)于 Y.Mov(X.(Add(Z)),這樣似乎沒有Mov(Y,Add(X,Z))
- 看起來舒服,但是一旦我們重載運(yùn)算符“=”為“Mov”,“+”為“Add”,
- 則Y.Mov(X.(Add(Z))的形式就等價于 Y=X+Z。
- 俺不知道其他編程語言里是否支持運(yùn)算浮重載,至少這樣定義函數(shù)格式
- 在C++里可以帶來很大的方便。
- 下面讓我們來實(shí)現(xiàn)大數(shù)類的主要成員函數(shù):
- /****************************************************************/
- //大數(shù)運(yùn)算庫源文件:BigInt.cpp
- //作者:afanty@vip.sina.com
- //版本:1.0 (2003.4.26)
- //說明:適用于MFC
- /****************************************************************/
- #include "stdafx.h"
- #include "BigInt.h"
- //初始化大數(shù)為0
- CBigInt::CBigInt()
- {
- m_nSign=1;
- m_nLength=1;
- for(int i=0;i<BI_MAXLEN;i++)m_ulvalue[i]=0;
- }
- //采用缺省的解構(gòu)函數(shù)
- CBigInt::~CBigInt()
- {
- }
- //大數(shù)比較,如果大數(shù)A位數(shù)比大數(shù)B多,當(dāng)然A>;B
- //如果位數(shù)相同,則從高位開始比較,直到分出大小
- int CBigInt::Cmp(CBigInt& A)
- {
- if(m_nLength>;A.m_nLength)return 1;
- if(m_nLength<A.m_nLength)return -1;
- for(int i=m_nLength-1;i>;=0;i--)
- {
- if(m_ulvalue[i]>;A.m_ulvalue[i])return 1;
- if(m_ulvalue[i]<A.m_ulvalue[i])return -1;
- }
- return 0;
- }
- //照搬參數(shù)的各屬性
- CBigInt& CBigInt::Mov(CBigInt& A)
- {
- m_nLength=A.m_nLength;
- for(int i=0;i<BI_MAXLEN;i++)m_ulvalue[i]=A.m_ulvalue[i];
- return *this;
- }
- //大數(shù)相加
- //調(diào)用形式:N.Add(A),返回值:N+A
- //若兩大數(shù)符號相同,其值相加,否則改變參數(shù)符號再調(diào)用大數(shù)相減函數(shù)
- /******************************************************************/
- 例如:
- A B C
- + D E
- --------------
- = S F G H
- 其中,若C+E<=0xffffffff,則H=C+E,carry(進(jìn)位標(biāo)志)=0
- 若C+E>;0xffffffff,則H=C+E-0x100000000,carry=1
- 若B+D+carry<=0xfffffff,則G=B+D,carry=0
- 若B+D+carry>;0xfffffff,則G=B+D+carry-0x10000000,carry=1
- 若carry=0,則F=A,S=0
- 若carry=1,A<0xfffffff,則F=A+1,S=0
- 若carry=1,A=0xfffffff,則F=0,S=1
- /*****************************************************************/
- CBigInt CBigInt::Add(CBigInt& A)
- {
- CBigInt X;
- if(X.m_nSign==A.m_nSign)
- {
- X.Mov(*this);
- int carry=0;
- unsigned __int64 sum=0;
- if(X.m_nLength<A.m_nLength)X.m_nLength=A.m_nLength;
- for(int i=0;i<X.m_nLength;i++)
- {
- sum=A.m_ulvalue[i];
- sum=sum+X.m_ulvalue[i]+carry;
- X.m_ulvalue[i]=(unsigned long)sum;
- if(sum>;0xffffffff)carry=1;
- else carry=0;
- }
- if(X.m_nLength<BI_MAXLEN)
- {
- X.m_ulvalue[X.m_nLength]=carry;
- X.m_nLength+=carry;
- }
- return X;
- }
- else{X.Mov(A);X.m_nSign=1-X.m_nSign;return Sub(X);}
- }
- //大數(shù)相減
- //調(diào)用形式:N.Sub(A),返回值:N-A
- //若兩大數(shù)符號相同,其值相減,否則改變參數(shù)符號再調(diào)用大數(shù)相加函數(shù)
- /******************************************************************/
- 例如:
- A B C
- - D E
- --------------
- = F G H
- 其中,若C>;=E,則H=C-E,carry(借位標(biāo)志)=0
- 若C<E,則H=C-E+0x100000000,carry=1
- 若B-carry>;=D,則G=B-carry-D,carry=0
- 若B-carry<D,則G=B-carry-D+0x10000000,carry=1
- 若carry=0,則F=A
- 若carry=1,A>;1,則F=A-1
- 若carry=1,A=1,則F=0
- /*****************************************************************/
- CBigInt CBigInt::Sub(CBigInt& A)
- {
- CBigInt X;
- if(m_nSign==A.m_nSign)
- {
- X.Mov(*this);
- int cmp=X.Cmp(A);
- if(cmp==0){X.Mov(0);return X;}
- int len,carry=0;
- unsigned __int64 num;
- unsigned long *s,*d;
- if(cmp>;0)
- {
- s=X.m_ulvalue;
- d=A.m_ulvalue;
- len=X.m_nLength;
- }
- if(cmp<0)
- {
- s=A.m_ulvalue;
- d=X.m_ulvalue;
- len=A.m_nLength;
- X.m_nSign=1-X.m_nSign;
- }
- for(int i=0;i<len;i++)
- {
- if((s[i]-carry)>;=d[i])
- {
- X.m_ulvalue[i]=s[i]-carry-d[i];
- carry=0;
- }
- else
- {
- num=0x100000000+s[i];
- X.m_ulvalue[i]=(unsigned long)(num-carry-d[i]);
- carry=1;
- }
- }
- while(X.m_ulvalue[len-1]==0)len--;
- X.m_nLength=len;
- return X;
- }
- else{X.Mov(A);X.m_nSign=1-X.m_nSign;return Add(X);}
- }
- //大數(shù)相乘
- //調(diào)用形式:N.Mul(A),返回值:N*A
- /******************************************************************/
- 例如:
- A B C
- * D E
- ----------------
- = S F G H
- + T I J K
- ----------------
- = U V L M N
- 其中,SFGH=ABC*E,TIJK=ABC*D
- 而對于:
- A B C
- * E
- -------------
- = S F G H
- 其中,若C*E<=0xffffffff,則H=C*E,carry(進(jìn)位標(biāo)志)=0
- 若C*E>;0xffffffff,則H=(C*E)&0xffffffff
- carry=(C*E)/0xffffffff
- 若B*E+carry<=0xffffffff,則G=B*E+carry,carry=0
- 若B*E+carry>;0xffffffff,則G=(B*E+carry)&0xffffffff
- carry=(B*E+carry)/0xffffffff
- 若A*E+carry<=0xffffffff,則F=A*E+carry,carry=0
- 若A*E+carry>;0xffffffff,則F=(A*E+carry)&0xffffffff
- carry=(A*E+carry)/0xffffffff
- S=carry
- /*****************************************************************/
- CBigInt CBigInt::Mul(CBigInt& A)
- {
- CBigInt X,Y;
- unsigned __int64 mul;
- unsigned long carry;
- for(int i=0;i<A.m_nLength;i++)
- {
- Y.m_nLength=m_nLength;
- carry=0;
- for(int j=0;j<m_nLength;j++)
- {
- mul=m_ulvalue[j];
- mul=mul*A.m_ulvalue[i]+carry;
- Y.m_ulvalue[j]=(unsigned long)mul;
- carry=(unsigned long)(mul>;>;32);
- }
- if(carry&&(Y.m_nLength<BI_MAXLEN))
- {
- Y.m_nLength++;
- Y.m_ulvalue[Y.m_nLength-1]=carry;
- }
- if(Y.m_nLength<BI_MAXLEN-i)
- {
- Y.m_nLength+=i;
- for(int k=Y.m_nLength-1;k>;=i;k--)Y.m_ulvalue[k]=Y.m_ulvalue[k-i];
- for(k=0;k<i;k++)Y.m_ulvalue[k]=0;
- }
- X.Mov(X.Add(Y));
- }
- if(m_nSign+A.m_nSign==1)X.m_nSign=0;
- else X.m_nSign=1;
- return X;
- }
- //大數(shù)相除
- //調(diào)用形式:N.Div(A),返回值:N/A
- //除法的關(guān)鍵在于“試商”,然后就變成了乘法和減法
- //這里將被除數(shù)與除數(shù)的試商轉(zhuǎn)化成了被除數(shù)最高位與除數(shù)最高位的試商
- CBigInt CBigInt::Div(CBigInt& A)
- {
- CBigInt X,Y,Z;
- int len;
- unsigned __int64 num,div;
- unsigned long carry=0;
- Y.Mov(*this);
- while(Y.Cmp(A)>;0)
- {
- if(Y.m_ulvalue[Y.m_nLength-1]>;A.m_ulvalue[A.m_nLength-1])
- {
- len=Y.m_nLength-A.m_nLength;
- div=Y.m_ulvalue[Y.m_nLength-1]/(A.m_ulvalue[A.m_nLength-1]+1);
- }
- else if(Y.m_nLength>;A.m_nLength)
- {
- len=Y.m_nLength-A.m_nLength-1;
- num=Y.m_ulvalue[Y.m_nLength-1];
- num=(num<<32)+Y.m_ulvalue[Y.m_nLength-2];
- if(A.m_ulvalue[A.m_nLength-1]==0xffffffff)div=(num>;>;32);
- else div=num/(A.m_ulvalue[A.m_nLength-1]+1);
- }
- else
- {
- X.Mov(X.Add(1));
- break;
- }
- Z.Mov(div);
- Z.m_nLength+=len;
- for(int i=Z.m_nLength-1;i>;=len;i--)Z.m_ulvalue[i]=Z.m_ulvalue[i-len];
- for(i=0;i<len;i++)Z.m_ulvalue[i]=0;
- X.Mov(X.Add(Z));
- Z.Mov(Z.Mul(A));
- Y.Mov(Y.Sub(Z));
- }
- if(Y.Cmp(A)==0)X.Mov(X.Add(1));
- if(m_nSign+A.m_nSign==1)X.m_nSign=0;
- else X.m_nSign=1;
- return X;
- }
- //大數(shù)求模
- //調(diào)用形式:N.Mod(A),返回值:N%A
- //求模與求商原理相同
- CBigInt CBigInt::Mod(CBigInt& A)
- {
- CBigInt X,Y;
- int len;
- unsigned __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<<32)+X.m_ulvalue[X.m_nLength-2];
- if(A.m_ulvalue[A.m_nLength-1]==0xffffffff)div=(num>;>;32);
- else div=num/(A.m_ulvalue[A.m_nLength-1]+1);
- }
- else
- {
- X.Mov(X.Sub(A));
- break;
- }
- Y.Mov(div);
- Y.Mov(Y.Mul(A));
- Y.m_nLength+=len;
- for(int 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));
- }
- if(X.Cmp(A)==0)X.Mov(0);
- return X;
- }
- //暫時只給出了十進(jìn)制字符串的轉(zhuǎn)化
- int CBigInt::InPutFromStr(CString& str, const unsigned int system=DEC)
- {
- int len=str.GetLength();
- Mov(0);
- for(int i=0;i<len;i++)
- {
- Mov(Mul(system));
- int k=str[i]-48;
- Mov(Add(k));
- }
- return 0;
- }
- //暫時只給出了十進(jìn)制字符串的轉(zhuǎn)化
- int CBigInt::OutPutToStr(CString& str, const unsigned int system=DEC)
- {
- str="";
- char 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;
- }
- //歐幾里德算法求:Y=X.Euc(A),使?jié)M足:YX mod A=1
- //相當(dāng)于對不定方程ax-by=1求最小整數(shù)解
- //實(shí)際上就是初中學(xué)過的輾轉(zhuǎn)相除法
- /********************************************************************/
- 例如: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,Y;
- 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));
- else Y.Mov(Y.Mod(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;
- }
- //蒙哥馬利算法求:Y=X.Mon(A,B),使?jié)M足:X^A mod B=Y
- //俺估計(jì)就是高中學(xué)過的反復(fù)平方法
- CBigInt CBigInt::Mon(CBigInt& A, CBigInt& B)
- {
- CBigInt X,Y,Z;
- X.Mov(1);
- Y.Mov(*this);
- Z.Mov(A);
- 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;
- }
- 最后需要說明的是因?yàn)樵赩C里面存在一個__int64類型可以
- 用來計(jì)算進(jìn)位與借位值,所以將大數(shù)當(dāng)作0x100000000進(jìn)制
- 進(jìn)行運(yùn)算是可能的,而在其他編譯系統(tǒng)中如果不存在64位
- 整形,則可以采用0x40000000進(jìn)制,由于在0x40000000
- 進(jìn)制中,對任何兩個“數(shù)字”進(jìn)行四則運(yùn)算,結(jié)果都在
- 0x3fffffff*03fffffff之間,小于0xffffffff,都可以用
- 一個32位無符號整數(shù)來表示。事實(shí)上《楚漢棋緣》采用的
- freelip大數(shù)庫正是運(yùn)用了0x40000000進(jìn)制來表示大數(shù)的,
- 所以其反匯編后大數(shù)的值在內(nèi)存中表現(xiàn)出來有些“奇怪”。
復(fù)制代碼 |
|