?? rsa
字號:
RSA算法
1978年就出現了這種算法,它是第一個既能用于數據加密也能用于數字簽名的算法。它易于理解和操作,也很流行。算法的名字以發明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。但RSA的安全性一直未能得到理論上的證明。
RSA的安全性依賴于大數難于分解這一特點。公鑰和私鑰都是兩個大素數(大于100個十進制位)的函數。據猜測,從一個密鑰和密文推斷出明文的難度等同于分解兩個大素數的積。
密鑰對的產生。選擇兩個大素數,p 和q 。計算:n = p * q 然后隨機選擇加密密鑰e,要求 e 和 ( p - 1 ) * ( q - 1 )互質。最后,利用Euclid 算法計算解密密鑰d, 滿足e * d = 1 ( mod ( p - 1 ) * ( q - 1 ) )其中n和d也要互質。數e和n是公鑰,d是私鑰。兩個素數p和q不再需要,應該丟棄,不要讓任何人知道。加密信息 m(二進制表示)時,首先把m分成等長數據塊 m1 ,m2,..., mi ,塊長s,其中 2^s <= n, s 盡可能的大。對應的密文是:ci = mi^e ( mod n ) ( a ) 解密時作如下計算:mi = ci^d ( mod n ) ( b )
RSA 可用于數字簽名,方案是用 ( a ) 式簽名, ( b )式驗證。具體操作時考慮到安全性和 m信息量較大等因素,一般是先作HASH 運算。RSA 的安全性。RSA的安全性依賴于大數分解,但是否等同于大數分解一直未能得到理論上的證明,因為沒有證明破解RSA就一定需要作大數分解。假設存在一種無須分解大數的算法,那它肯定可以修改成為大數分解算法。目前,RSA的一些變種算法已被證明等價于大數分解。不管怎樣,分解n是最顯然的攻擊方法。現在,人們已能分解140多個十進制位的大素數。因此,模數n必須選大一些,因具體適用情況而定。
由于進行的都是大數計算,使得RSA最快的情況也比DES慢上100倍,無論是軟件還是硬件實現。速度一直是RSA的缺陷。一般來說只用于少量數據加密。
*/
#include <iostream>
#include <stdlib>
#include <time>using namespace std;//RSA算法所需參數
typedef struct RSA_PARAM_Tag
{
unsigned __int64 p, q; //兩個素數,不參與加密解密運算
unsigned __int64 f; //f=(p-1)*(q-1),不參與加密解密運算
unsigned __int64 n, e; //公匙,n=p*q,gcd(e,f)=1
unsigned __int64 d; //私匙,e*d=1 (mod f),gcd(n,d)=1
unsigned __int64 s; //塊長,滿足2^s<=n的最大的s,即log2(n)
} RSA_PARAM;//小素數表
const static long g_PrimeTable[]=
{
3,
5,
7,
11,
13,
17,
19,
23,
29,
31,
37,
41,
43,
47,
53,
59,
61,
67,
71,
73,
79,
83,
89,
97
};
const static long g_PrimeCount=sizeof(g_PrimeTable) / sizeof(long);const unsigned __int64 multiplier=12747293821;
const unsigned __int64 adder=1343545677842234541;//隨機數類
class RandNumber
{
/* */
private:
unsigned __int64 randSeed;/* */
public:
RandNumber(unsigned __int64 s=0);
unsigned __int64 Random(unsigned __int64 n);
};/* */
RandNumber::RandNumber(unsigned __int64 s)
{
if(!s)
{
randSeed= (unsigned __int64)time(NULL);
}
else
{
randSeed=s;
}
}/* */
unsigned __int64 RandNumber::Random(unsigned __int64 n)
{
randSeed=multiplier * randSeed + adder;
return randSeed % n;
}static RandNumber g_Rnd;/*
模乘運算,返回值 x=a*b mod n
*/
inline unsigned __int64 MulMod(unsigned __int64 a, unsigned __int64 b, unsigned __int64 n)
{
return a * b % n;
}/*
模冪運算,返回值 x=base^pow mod n
*/
unsigned __int64 PowMod(unsigned __int64 &base, unsigned __int64 &pow, unsigned __int64 &n)
{
unsigned __int64 a=base, b=pow, c=1;
while(b)
{
while(!(b & 1))
{
b>>=1; //a=a * a % n; //函數看起來可以處理64位的整數,但由于這里a*a在a>=2^32時已經造成了溢出,因此實際處理范圍沒有64位
a=MulMod(a, a, n);
} b--; //c=a * c % n; //這里也會溢出,若把64位整數拆為兩個32位整數不知是否可以解決這個問題。
c=MulMod(a, c, n);
} return c;
}/*
Rabin-Miller素數測試,通過測試返回1,否則返回0。
n是待測素數。
注意:通過測試并不一定就是素數,非素數通過測試的概率是1/4
*/
long RabinMillerKnl(unsigned __int64 &n)
{
unsigned __int64 b, m, j, v, i;
m=n - 1;
j=0; //0、先計算出m、j,使得n-1=m*2^j,其中m是正奇數,j是非負整數
while(!(m & 1))
{
++j;
m>>=1;
} //1、隨機取一個b,2<=b<n-1
b=2 + g_Rnd.Random(n - 3); //2、計算v=b^m mod n
v=PowMod(b, m, n); //3、如果v==1,通過測試
if(v == 1)
{
return 1;
} //4、令i=1
i=1; //5、如果v=n-1,通過測試
while(v != n - 1)
{
//6、如果i==l,非素數,結束
if(i == j)
{
return 0;
} //7、v=v^2 mod n,i=i+1
v=PowMod(v, 2, n);
++i; //8、循環到5
} return 1;
}/*
Rabin-Miller素數測試,循環調用核心loop次
全部通過返回1,否則返回0
*/
long RabinMiller(unsigned __int64 &n, long loop)
{
//先用小素數篩選一次,提高效率
for(long i=0; i < g_PrimeCount; i++)
{
if(n % g_PrimeTable[i] == 0)
{
return 0;
}
} //循環調用Rabin-Miller測試loop次,使得非素數通過測試的概率降為(1/4)^loop
for(long i=0; i < loop; i++)
{
if(!RabinMillerKnl(n))
{
return 0;
}
} return 1;
}/*
隨機生成一個bits位(二進制位)的素數,最多32位
*/
unsigned __int64 RandomPrime(char bits)
{
unsigned __int64 base;
do
{
base= (unsigned long)1 << (bits - 1); //保證最高位是1
base+=g_Rnd.Random(base); //再加上一個隨機數
base|=1; //保證最低位是1,即保證是奇數
} while(!RabinMiller(base, 30)); //進行拉賓-米勒測試30次
return base; //全部通過認為是素數
}/*
歐幾里得法求最大公約數
*/
unsigned __int64 EuclidGcd(unsigned __int64 &p, unsigned __int64 &q)
{
unsigned __int64 a=p > q ? p : q;
unsigned __int64 b=p < q ? p : q;
unsigned __int64 t;
if(p == q)
{
return p; //兩數相等,最大公約數就是本身
}
else
{
while(b) //輾轉相除法,gcd(a,b)=gcd(b,a-qb)
{
a=a % b;
t=a;
a=b;
b=t;
} return a;
}
}/*
Stein法求最大公約數
*/
unsigned __int64 SteinGcd(unsigned __int64 &p, unsigned __int64 &q)
{
unsigned __int64 a=p > q ? p : q;
unsigned __int64 b=p < q ? p : q;
unsigned __int64 t, r=1;
if(p == q)
{
return p; //兩數相等,最大公約數就是本身
}
else
{
while((!(a & 1)) && (!(b & 1)))
{
r<<=1; //a、b均為偶數時,gcd(a,b)=2*gcd(a/2,b/2)
a>>=1;
b>>=1;
} if(!(a & 1))
{
t=a; //如果a為偶數,交換a,b
a=b;
b=t;
} do
{
while(!(b & 1))
{
b>>=1; //b為偶數,a為奇數時,gcd(b,a)=gcd(b/2,a)
} if(b < a)
{
t=a; //如果b小于a,交換a,b
a=b;
b=t;
} b=(b - a) >> 1; //b、a都是奇數,gcd(b,a)=gcd((b-a)/2,a)
} while(b);
return r * a;
}
}/*
已知a、b,求x,滿足a*x =1 (mod b)
相當于求解a*x-b*y=1的最小整數解
*/
unsigned __int64 Euclid(unsigned __int64 &a, unsigned __int64 &b)
{
unsigned __int64 m, e, i, j, x, y;
long xx, yy;
m=b;
e=a;
x=0;
y=1;
xx=1;
yy=1;
while(e)
{
i=m / e;
j=m % e;
m=e;
e=j;
j=y;
y*=i;
if(xx == yy)
{
if(x > y)
{
y=x - y;
}
else
{
y-=x;
yy=0;
}
}
else
{
y+=x;
xx=1 - xx;
yy=1 - yy;
} x=j;
} if(xx == 0)
{
x=b - x;
} return x;
}/*
隨機產生一個RSA加密參數
*/
RSA_PARAM RsaGetParam(void)
{
RSA_PARAM Rsa={ 0 };
unsigned __int64 t;
Rsa.p=RandomPrime(16); //隨機生成兩個素數
Rsa.q=RandomPrime(16);
Rsa.n=Rsa.p * Rsa.q;
Rsa.f=(Rsa.p - 1) * (Rsa.q - 1);
do
{
Rsa.e=g_Rnd.Random(65536); //小于2^16,65536=2^16
Rsa.e|=1; //保證最低位是1,即保證是奇數,因f一定是偶數,要互素,只能是奇數
} while(SteinGcd(Rsa.e, Rsa.f) != 1); Rsa.d=Euclid(Rsa.e, Rsa.f);
Rsa.s=0;
t=Rsa.n >> 1;
while(t)
{
Rsa.s++; //s=log2(n)
t>>=1;
} return Rsa;
}/*
拉賓-米勒測試
*/
void TestRM(void)
{
unsigned long k=0;
cout << " - Rabin-Miller prime check.\n" << endl;
for(unsigned __int64 i=4197900001; i < 4198000000; i+=2)
{
if(RabinMiller(i, 30))
{
k++;
cout << i << endl;
}
} cout << "Total: " << k << endl;
}/*
RSA加密解密
*/
void TestRSA(void)
{
RSA_PARAM r;
char pSrc[]="abcdefghijklmnopqrstuvwxyz";
const unsigned long n=sizeof(pSrc);
unsigned char *q, pDec[n];
unsigned __int64 pEnc[n];
r=RsaGetParam();
cout << "p=" << r.p << endl;
cout << "q=" << r.q << endl;
cout << "f=(p-1)*(q-1)=" << r.f << endl;
cout << "n=p*q=" << r.n << endl;
cout << "e=" << r.e << endl;
cout << "d=" << r.d << endl;
cout << "s=" << r.s << endl;
cout << "Source:" << pSrc << endl;
q= (unsigned char *)pSrc;
cout << "Encode:";
for(unsigned long i=0; i < n; i++)
{
pEnc[i]=PowMod(q[i], r.e, r.n);
cout << hex << pEnc[i] << " ";
} cout << endl;
cout << "Decode:";
for(unsigned long i=0; i < n; i++)
{
pDec[i]=PowMod(pEnc[i], r.d, r.n);
cout << hex << (unsigned long)pDec[i] << " ";
} cout << endl;
cout << (char *)pDec << endl;
}/* */
int main(void)
{
TestRSA();
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -