RSA就是公钥加密的经典。这个主要是基于大整数的素数分解问题,这个难题的。大概过程是这样的,首先,产生二个大素数p,q.然后计算n=p*q,则f=(p-1)*(q-1),然后,我们在<n中寻找一个数e,是的gcd(e,f)=1,gcd()函数就是求解最大公约数的函数,也就是e和f互素。这样,根据扩展的欧几里得算法,可以知道x*e+y*f=1,这个中的x=d,也就是d*e mod f=1,假如明文是m,则加密就是c=m^e mod n,c就是密文,m就是明文,而解密就是c^d mod n=m;这样的公钥就是(e,n),私钥就是(d,n);
这样过来的话,就有很大的几个问题需要解决,如何产生大素数。
还有这里,为什么能解密。我们首先看一下,c^d mod n=(m^e mod n)^d mod n=m^ed mod n;
所以,我们要证明为什么能够解密,就需要证明,m^ed mod n=m;
首先,考虑,这种情况,当gcd(m,n)=1时,即m,n互素时,ed mod f=1,则ed=k*f+1;m^ed=m^(k*f+1),则根据欧拉定理,m^f mod n=1则m^(k*f+1) mod n=m;
但是当gcd(m,n)!=1时,这是,因为n=pq,则m与n不互素时,只能是m=kq或者kp,假如,我们设为m=kq,则k一定是与p是互素的,因为q是素数,只有自己和1能整除,则
kq^(p-1) mod p=1;(kq)^kf mod p=1,则(kq)^(kf+1)=(kq)mod n,这样的话,即证明了。更详细的解说见下面的链接:“http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html”。
附上RSA的完整代码(c++版的):
#include<iostream>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <cmath>
#include <fstream>
#include <bitset>
using namespace std;
//快速指数算法;
typedef struct RSA{
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;
} RSA_ALL;
const static long Prime[]=
{
3,5,7,11,13,17,19,23,29,31,37,41,43,
47,53,59,61,67,71,73,79,83,89,97
};
unsigned __int64 randseed;
const unsigned __int64 multiplier=12747293821;
const unsigned __int64 adder=1343545677842234541;
long long g,x,y,temp;
//广义欧几里得算法;
void G_gcd(unsigned __int64 p,unsigned __int64 q)
{
if(q)
{
G_gcd(q,p%q);
temp=x;
x=y;
y=temp-(p/q)*y;
}else{
g=p;
x=1;
y=0;
}
}
unsigned __int64 PowMod(unsigned __int64 base,unsigned __int64 p,unsigned __int64 n)//base^p%n
{
unsigned __int64 a=1,c=p,b=base;
while(c)
{
if(c&1)
{
a=a*b%n;
}
b=b*b%n;
c>>=1;
}
return a;
}
unsigned __int64 random(unsigned __int64 n)
{
randseed=(multiplier *randseed + adder)%n;
return randseed;
}
//这个函数就是如果这个n是一个素数,则返回false,如果是合数,返回true;
bool witness(unsigned __int64 a,unsigned __int64 n)
{
unsigned __int64 m=n-1,t=0,u,xx,yy,p=1;//n-1=2^t*u;x是a^u%n;
while(!(m&1))
{
t++;
m>>=1;
}
for(int i=0;i<t;i++)
{
p=2*p;
}
u=(n-1)/p;
xx=PowMod(a,u,n);
if(xx==1)
{
return 0;
}
for(int i=0;i<t;i++)
{
yy=xx*xx%n;
if((yy==1)&&(xx!=1)&&(xx!=n-1))
{
return 1;
}
xx=yy;
}
if(yy!=1)
{
return 1;
}
return 0;
}
//这个函数是rabin检测素数,n是待检测的素数,t是检测的次数;
bool Miller_Rabin(unsigned __int64 n,int t)
{
unsigned __int64 a;
for(int i=0;i<sizeof(Prime)/sizeof(int);i++)
{
if(n%Prime[i]==0)
{
return false;
}
}
for(int j=0;j<t;j++)
{
a=random(n-1);
if(witness(a,n))
{
return false;
}
}
return true;
}
unsigned __int64 CreatePrime()
{
const unsigned __int64 n=65536 ;
unsigned __int64 prime;
do{
prime=random(n);
if(prime%2==0)
{
prime++;
}
}while(!Miller_Rabin(prime,30));
return prime;
}
//用辗转想除法求最大公约数;
int main()
{
RSA_ALL r;
srand((unsigned)time(0));
randseed=rand();
r.p=CreatePrime();
r.q=CreatePrime();
r.n=r.p*r.q;
r.f=(r.p-1)*(r.q-1);
do{
r.e=random(65536);
r.e|=1;
G_gcd(r.f,r.e);
}while(g!=1);
cout<<"二个大素数:"<<endl;
cout<<r.p<<" "<<r.q<<endl;
cout<<"二个大素数的积:"<<r.n<<endl;
cout<<"f的值:"<<r.f<<endl;
cout<<"e:"<<r.e<<endl;
cout<<"扩展的欧几里得算法x*r.f+y*r.e:"<<x*r.f+y*r.e<<endl;
if(y<0)
{
r.d=r.f+y;
}else{
r.d=y;
}
cout<<"e*d%f:y*r.e%r.f:"<<(r.d)*(r.e)%(r.f)<<endl;
cout<<"x:"<<x<<" "<<"y:"<<y<<endl;
string plain;
int i;
cin>>plain;
cout<<"明文"<<plain<<endl;
const int len=plain.size();
unsigned __int64 ctext[100],ptext[100];
for(i=0;i<len;i++)
{
ctext[i]=PowMod(plain[i],r.e,r.n);
}
cout<<"密文"<<ctext<<endl;
for(i=0;i<len;i++)
{
ptext[i]=PowMod(ctext[i],r.d,r.n);
}
cout<<"明文"<<(char)ptext[0];
for(i=1;i<len;i++)
{
cout<<(char)ptext[i];
}
system("pause");
return 0;
}