提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、算法
实验目标:实现RSA加密算法,根据已知明文计算出RSA的加密密文,并解密。
实验算法:
1、 选择一对不同的、足够大的素数p,q。
2、 计算n=pq。
3、 计算Euler(n)=(p-1)(q-1),同时对p, q严加保密,不让任何人知道。
4、 找一个与Euler(n)互质的数e,且1<e<Euler(n)。
5、 计算d,使得de≡1 mod f(n)。这个公式也可以表达为d ≡e-1 mod f(n)
*这里要解释一下,≡是数论中表示同余的符号。公式中,≡符号的左边必须和符号右边同余,也就是两边模运算结果相同。显而易见, 不管f(n)取什么值,符号右边1 mod f(n)的结果都等于1;符号的左边d与e的乘积做模运算后的结果也必须等于1。这就需要计算出d的值,让这个同余等式能够成立。*本实验采用平方乘算法。
6、 公钥KU=(e,n),私钥KR=(d,n)。
7、 加密时,先将明文变换成0至n-1的一个整数M。若明文较长,可先分割成适当的组,然后再进行交换。
二、源码
1.加密
#include<bits/stdc++.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <math.h>
//#include <cstddef.h>
using namespace std;
/*使用三个rand()生成伪随机数组合生成一个奇数随机数,作为伪素数
**系统时间为种子
**并返回生成的这个大奇数
*/
unsigned int ProduceRandomOdd(){//UINT无符号整形,各伪随机数放在RandomArray数组中
time_t t;//c++时间类型
unsigned int RandomNumber;//记录随机数
do{
srand((unsigned)time(&t));//srand(seed)用于给rand()函数设定种子,此处用系统时间
//生成
RandomNumber=(rand()<<3);
cout<<RandomNumber<<endl;
}while(RandomNumber%2==0||RandomNumber<100000000);
//返回
return RandomNumber;
}
//模重复平方算法求(b^n)%m
size_t repeatMod(size_t base, size_t n, size_t mod){
size_t a = 1;
while(n){
if(n&1){
a=(a*base)%mod;
}
base=(base*base)%mod;
n=n>>1;
}
return a;
}
//Miller-Rabin素数检测
bool rabinmiller(size_t n, size_t k){
int s=0;
int temp=n-1;
//将n-1表示为(2^s)*t
while ((temp&0x1)==0&&temp){
temp=temp>>1;
s++;
}
size_t t = temp;
//判断k轮误判概率不大于(1/4)^k
while(k--){
srand((unsigned)time(0));
size_t b = rand()%(n-2)+2; //生成一个b(2≤a ≤n-2)
size_t y = repeatMod(b,t,n);
if (y == 1 || y == (n-1))
return true;
for(int j = 1; j<=(s-1) && y != (n-1); ++j){
y = repeatMod(y,2,n);
if (y == 1)
return false;
}
if (y != (n-1))
return false;
}
return true;
}
unsigned int Euler(unsigned int n)//欧拉函数 求1到n中有多少个整数与n互质
{
unsigned int rs=1;
for(unsigned int i=2;i*i<=n;i++)
{
if(n%i==0)
{
rs*=(i-1);
n/=i;
while(n%i==0)
{
rs*=(i-1);
n/=i;
}
}
}
if(n>1)
rs*=(n-1);
return rs;
}
unsigned int gcd(unsigned int a,unsigned int b)//求a,b的最大公约数
{
if(b==0)
return a;
return gcd(b,a%b);
}
unsigned int check(unsigned int n)//判断n是不是素数
{
if(n==1)
return 0;
if(n==2)
return 1;
for(int i=3;i*i<=n;i=i+2)
{
if(n%i==0)
return 0;
}
return 1;
}
unsigned int gnerating_primes(unsigned int n)//产生小于等于n的第一个素数
{
if(n%2==0)
n--;
for(unsigned int i=n;i>1;i=i-2)
{
if(check(i)==1)
return i;
}
return -1;//表示没有小于等于n的素数
}
unsigned int multiplicative_inverse_element(unsigned int a,unsigned int r)//求a对于r的乘法逆元
{
unsigned int rs=1;
if(check(r)==1)//r是素数 采用费马小定理
{
for(unsigned int i=1;i<=r-2;i++)
rs*=a,rs%=r;
}else //r不是素数,采用欧拉定理的推论
{
unsigned int k=Euler(r)-1;
for(unsigned int i=1;i<=k;i++)
rs*=a,rs%=r;
}
return rs;
}
unsigned int get_pk(int w)
{
unsigned int pk=2;
for(pk=2;pk<w;pk++)
{
if(gcd(w,pk)==1)
return pk;
}
return pk;
}
unsigned int square_multiplication(unsigned int x,unsigned int c,unsigned int r)//平方乘算法,x的c次方%r
{
string str="";
while(c)
{
str=(char)(c%2+'0')+str;
c/=2;
}
unsigned int rs=x;
unsigned int l=str.length();
for(unsigned int i=1;i<l;i++)
{
if(str[i]=='0')
rs=((rs%r)*(rs%r))%r;
else
rs=(((rs%r)*(rs%r))%r*x)%r;
}
return rs;
}
int main()
{
size_t k=20;//进行20轮测试
unsigned int RandomOdd_1;
unsigned int RandomOdd_2;
bool flag_1;
bool flag_2;
//直至找到过关的伪素数
do{
RandomOdd_1=ProduceRandomOdd();
//cout<<RandomOdd<<endl;
flag_1=rabinmiller(RandomOdd_1,k);
}while(flag_1==false);
//cout<<"=========================="<<endl;
cout<<"生成的第一个大素数为:" <<RandomOdd_1;
do{
RandomOdd_2=ProduceRandomOdd();
//cout<<RandomOdd<<endl;
flag_2=rabinmiller(RandomOdd_2,k);
}while(flag_2==false||RandomOdd_2==RandomOdd_1);
//cout<<"=========================="<<endl;
cout<<"生成的第二个大素数为:" <<RandomOdd_2;
int p=RandomOdd_1;
int q=RandomOdd_2;
unsigned int r=p*q;//公开模数
cout<<"r="<<r<<endl;
unsigned int w=Euler(r);//1到r中与r互质的数的个数
//求得公钥
unsigned int pk=get_pk(w);
//pk=167;
cout<<"公钥(pk,r):("<<pk<<","<<r<<")"<<endl;
//求得私钥
unsigned int sk=multiplicative_inverse_element(pk,w);
cout<<"私钥(sk,r):("<<sk<<","<<r<<")"<<endl;
unsigned int M=123456789;//明文
unsigned int K=3;//K位一组
unsigned int temp=1;
for(unsigned int k=1;k<=K;k++)
temp*=10;
cout<<"密文:";
for(unsigned int i=1;i<=K;i++)
{
cout<<square_multiplication(M%temp,pk,r)<<" ";
M/=temp;
}
cout<<endl;
return 0;
}
2.解密
#include<bits/stdc++.h>
using namespace std;
unsigned int Euler(unsigned int n)//欧拉函数 求1到n中有多少个整数与n互质
{
unsigned int rs=1;
for(unsigned int i=2;i*i<=n;i++)
{
if(n%i==0)
{
rs*=(i-1);
n/=i;
while(n%i==0)
{
rs*=(i-1);
n/=i;
}
}
}
if(n>1)
rs*=(n-1);
return rs;
}
unsigned int gcd(unsigned int a,unsigned int b)//求a,b的最大公约数
{
if(b==0)
return a;
return gcd(b,a%b);
}
unsigned int check(unsigned int n)//判断n是不是素数
{
if(n==1)
return 0;
if(n==2)
return 1;
for(int i=3;i*i<=n;i=i+2)
{
if(n%i==0)
return 0;
}
return 1;
}
unsigned int gnerating_primes(unsigned int n)//产生小于等于n的第一个素数
{
if(n%2==0)
n--;
for(unsigned int i=n;i>1;i=i-2)
{
if(check(i)==1)
return i;
}
return -1;//表示没有小于等于n的素数
}
unsigned int multiplicative_inverse_element(unsigned int a,unsigned int r)//求a对于r的乘法逆元
{
unsigned int rs=1;
if(check(r)==1)//r是素数 采用费马小定理
{
for(unsigned int i=1;i<=r-2;i++)
rs*=a,rs%=r;
}else //r不是素数,采用欧拉定理的推论
{
unsigned int k=Euler(r)-1;
for(unsigned int i=1;i<=k;i++)
rs*=a,rs%=r;
}
return rs;
}
unsigned int get_pk(int w)
{
unsigned int pk=2;
for(pk=2;pk<w;pk++)
{
if(gcd(w,pk)==1)
return pk;
}
return pk;
}
unsigned int square_multiplication(unsigned int x,unsigned int c,unsigned int r)//平方乘算法,x的c次方%r
{
string str="";
while(c)
{
str=(char)(c%2+'0')+str;
c/=2;
}
unsigned int rs=x;
unsigned int l=str.length();
for(unsigned int i=1;i<l;i++)
{
if(str[i]=='0')
rs=((rs%r)*(rs%r))%r;
else
rs=(((rs%r)*(rs%r))%r*x)%r;
}
return rs;
}
int main()
{
unsigned int p=991;
unsigned int q=997;
cout<<"生成的第一个大素数为:" <<p<<endl;
cout<<"生成的第二个大素数为:" <<q<<endl;
unsigned int r=p*q;//公开模数
cout<<"r="<<r<<endl;
unsigned int w=Euler(r);//1到r中与r互质的数的个数
//求得公钥
unsigned int pk=get_pk(w);
//pk=167;
cout<<"公钥(pk,r):("<<pk<<","<<r<<")"<<endl;
//求得私钥
unsigned int sk=multiplicative_inverse_element(pk,w);
cout<<"私钥(sk,r):("<<sk<<","<<r<<")"<<endl;
unsigned int M=123456789;//明文
unsigned int K=3;//K位一组
unsigned int temp=1;
for(unsigned int k=1;k<=K;k++)
temp*=10;
cout<<"密文:";
for(unsigned int i=1;i<=K;i++)
{
cout<<square_multiplication(M%temp,pk,r)<<" ";
M/=temp;
}
cout<<endl;
cout<<"解密得到的明文:"<<M<<endl;
return 0;
}
}