对称和非对称加密
对称
对称加密很简单,就是明文通过密钥加密成为密文之后,接收方通过同样的密钥(密钥的逆算法)对密钥进行解密
比如说我的明文是1,经过密钥*2计算后变成2那么解密过程就是2/2=1
非对称
非对称加密算法中,有两个密钥:公钥和私钥。它们是一对,如果用公钥进行加密,只有用对应的私钥才能解密;如果用私钥进行加密,只有用对应的公钥才能解密。
非对称加密算法实现机密信息的交换过程为:甲方生成一对密钥并将其中一个作为公钥向其他方公开;得到该公钥的乙方使用该密钥对机密信息进行加密后发送给甲方;甲方再用自己的另一个专用密钥对加密后的信息进行解密。
RSA算法:
公钥私钥计算过程
过程懂了,原理懂不了一点
- 选择两个质数 p=3 q=11
- 质数相乘得到公钥N: N=p*q=33
- 使用欧拉函数计算T=(p-1)*(q-1)=20
- 选出一个公钥E有如下要求:
- E是质数
- 1<公钥E<T
- 不是T的因子
所以E的范围就是[3,33),这里选择3
- 算私钥D (D*E)%T=1;D=7
得到公钥(3,33) 私钥(7,33)
使用公钥私钥加解密过程
比如有三个十进制数字 3 1 15
公钥(3,33) | 原文3 ,1 ,15 | 私钥(7,33) | 密文27,1,9 |
---|---|---|---|
使用3求幂 | 27,1,3375 | 使用7求幂 | 10460353203,1,4782969 |
对33求余 | 27,1,9 | 对33求余 | 3,1,15 |
得到密文 | 27,1,9 | 得到原文 | 3,1,15 |
就到这里有点神奇,数学的魅力
来个公私钥生成代码
#include<iostream>
#include<vector>
#include<math.h>
#include<cstdio>
#include<time.h>
using namespace std;
//0-65535所有质数的个数
#define Prime_Count 6541
vector<int> Prime;
//判断素数
bool isPrime(int n)
{
for(int i=2;i<=sqrt(n)+1;i++)
{
if(n%i==0)
{
return false;
}
}
return true;
}
//计算3-65535的所有质数并放入Prime之中
void getAllPrime()
{
for(int i=3;i<65535;i+=2)
{
if(isPrime(i))
{
Prime.push_back(i);
}
}
}
//选择随机的两个质数
void getRandPrime(int &p,int &q)
{
unsigned Choose_P =(unsigned)rand() % (Prime_Count );//在从[0,6540]共6541个数里面随机选一个
cout << "Choose_P=" << Choose_P << endl;
//Plus_Q表示在P的数组标号上的增量,为了P,Q不相等(即数组下标不相等),增量的范围是[1,6540]
unsigned Plus_Q = (unsigned)rand() % (Prime_Count - 1)+1;//增量的范围是[1,6540]
//cout << "Plus_Q=" << Plus_Q << endl;
unsigned Choose_Q = (Choose_P + Plus_Q) % (Prime_Count );// % Prime_Count 是因为Choose_P + Plus_Q可能会超过6541
//cout << "Choose_Q=" << Choose_Q << endl;
p = Prime[Choose_P];
q = Prime[Choose_Q];
cout << "计算密钥的两素数为:p= " << p << " , " << " q= " << q << endl;
}
int main()
{
getAllPrime();
srand(time(0));
//两个质数p,q
int p,q;
getRandPrime(p,q);
//欧拉公式得到T
int T=(p-1)*(q-1);
//计算公钥E,从小到大计算了
int E;
for(int i=2;i<T;i++)
{
if(T%i!=0&&isPrime(i))
{
E=i;
cout<<"公钥E = ("<<i<<" , "<<p*q<<")"<<endl;
break;
}
}
//计算私钥,不懂数学优化只能暴力计算
int D;
for(int i=2;;i++)
{
if((i*E)%T==1)
{
D=i;
cout<<"私钥D = ("<<i<<" , "<<p*q<<" )"<<endl;
break;
}
}
}