对称加密都非常好理解,而且十分容易实现。
其实小的时候就早早知道了非对称加密的概念。但是就算在现实中找到海枯石烂也找到不到一个实例去实现。
然后上课老师举了一个很形象的例子:
非对称加密就像一个邮箱。邮箱的外壳就是加密秘钥,而邮箱的钥匙是解密秘钥。大家都可以使用这个加密秘钥把自己的信息发送出去而其他人也是同样的手法加密信息。但是过程是不可逆的,只有拥有解密秘钥的人,也就是拥有邮箱钥匙的人才能读取信息,解密信息。
概念介绍完了。那就是这个算法的大致过程了。
1.首先我们需要两个素数p,q,两个数越大,隔得越远越不容易被破解。
2.求出n=q*p这是秘钥的一部分。求其欧拉值euler=(p-1)*(q-1)
3.生成公钥(也就是加密秘钥)keyE,2<=keyE<euler而且gcd(keyE,euler)=1
4.生成私钥(也就是解密密钥)keyD(两种方法)
5.加密操作 C=M^keyE mod n M是明文,C是密文(这里直接简化成单个数字)
6.解密操作 M=C^keyD mod n
模拟实现的代码很简单,大部分都是直接暴力或者直接随机数,故意将数字做的很小没有让它溢出,否则就需要用到大数操作。
素数并没有做的很大,而且求逆元的方法速度也堪忧。不过终究还是实现了一个可以用的,对单个数字加密的RSA
附上源码
#include<bits/stdc++.h>
using namespace std;
long long p,q,n,euler,KeyE,KeyD;
long long mod;
long long gcd(long long a,long long b)//欧几里得算法,即辗转相除算法
{
return b==0?a:gcd(b,a%b);
}
//扩展欧几里得算法,返回d=gcd(a,b),同时ax+by=d
long long extend_gcd(long long a , long long b , long long &x ,long long &y)
{
if(a==0&&b==0)return -1;//无结果
if(b==0)
{
x=1;
y=0;
return a;
}
long long d=extend_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
//模逆算法
long long mod_reverse(long long a,long long n)
{
long long x,y;
long long d=extend_gcd(a,n,x,y);
if(d==1)
return (x%n+n)%n;
else return -1;
}
long long qpow(long long a,long long b)//快速幂
{
long long r=1,base=a%mod;
while(b!=0)
{
if(b&1)
r*=base;
base*=base;
r%=mod;
base%=mod;
b>>=1;
}
return r%mod;
}
bool isPrime(long long x)//素数判断算法
{
for(int i=2; i*i<=x; i++)
if(x%i==0)
return 0;
return 1;
}
long long ProductPrime()//生成素数
{
long long temp=0;
srand(time(NULL));
while(1)
{
temp=rand()%100+100;
if(isPrime(temp))
break;
}
return temp;
}
long long ProductKeyE()//生成加密密钥
{
long long temp;
while(1)
{
temp=rand()%euler;
if(temp>=2&&gcd(temp,euler)==1)
break;
}
return temp;
}
long long ProductKeyD()//生成解密秘钥方法1
{
long long temp=euler/KeyE;
while(1)
{
if((temp*KeyE)%euler==1)
break;
else temp++;
}
return temp;
}
int main()
{
p=ProductPrime();
q=ProductPrime();
while(p==q)
{
q=ProductPrime();
}
//cout<<p<<" "<<q<<endl;
n=q*p;
euler=(q-1)*(p-1);
KeyE=ProductKeyE();
KeyD=ProductKeyD();
long long KeyD2;
KeyD2=mod_reverse(KeyE,euler);//方法2
cout<<"p:"<<p<<" q:"<<q<<" n:"<<n<<" euler:"<<euler<<endl;
cout<<"keye:"<<KeyE<<" keyd:"<<KeyD<<" "<<KeyD2<<endl;
mod=n;
long long ming,temp;
cout<<"plain text(number):";
cin>>ming;
temp=qpow(ming,KeyE)%mod;
cout<<"encryption:"<<temp<<endl;
cout<<"decryption:"<<qpow(temp,KeyD)%mod<<endl;
return 0;
}