RSA密码

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

猜你喜欢

转载自blog.csdn.net/daydayup_666/article/details/78241536
RSA