前言
这是课程学习中的一个作业,把手写过程转成程序实现
题目
4、 已知RSA算法中,素数p=5,q=7,模数n=35,公钥e=5,明文为bed,对明文进行加解密,使用手工完成RSA公开秘钥密码体制算法加密运算。字母数字映射表如下:
可以参考, 用实例给新手讲解RSA加密算法
但并不保证网页内容完全正确,请自行判断
解题分析
加解密过程:
- 设计公私密钥(e,n)和(d,n):
由题目需求p = 5 ,q = 7,模数n = 35 ,公钥e = 5 得 f(n) = (p-1)*(q-1)=24,e = 5 与f(n) = 24 互素 故e满足要求。 - 计算密钥d:
d的计算公式为 d*e ≡ 1(mod f(n)),即 5*d ≡1 mod 24,d值的推导如下表:
d | e*d = 5*d | (e*d)mod(p-1)(q-1)= (5*d) mod 2 |
---|---|---|
1 | 5 | 5 |
2 | 10 | 10 |
3 | 15 | 15 |
4 | 20 | 20 |
5 | 25 | 1 |
由此可得d = 5。
- 得出公钥私钥:
从上述步骤得出公钥KU = (e,n)=(5,35),私钥KR =(d,n) = (5,35) - 英文数字化
将明文信息数字化,并将每块两个数字分组。假定明文英文字母编码表为按字母顺序排列数值,即:
字母 | a | b | c | d | e | f | g | h | i | j | k | l | m |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
码值 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 |
字母 | n | o | p | q | r | s | t | u | v | w | x | y | z |
码值 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
明文bed数字化,即为:02,05,04
- 明文加密
由加密公式 Y=X^e mod n 得密文:
Y1 = 2^5 mod 35 = 32 mod 35 = 32
Y2 = 5^5 mod 35 = 3125 mod 35 = 10
Y3 = 4^5 mod 35 = 1024 mod 35 = 9 - 密文解密
由解密公式 X=Y^d mod n 恢复明文:
X1 = 32^5 mod 35 = 33554432 mod 35 = 2
X2 = 10^5 mod 35 = 100000 mod 35 = 5
X3 = 9^5 mod 35 = 59049 mod 35 = 4
即恢复明文为bed。
运行截图
代码
/*
*
*简单RSA加解密算法
*HB
*需输入p,q,e
*/
#include <iostream>
#include<string.h>
using namespace std;
/*
*判断素数
*/
bool isPrime(int n)
{
if(n%2==0)return false;
for(int i= 2;i<n/2+1;i++)
if(n%i==0)return false;
return true;
}
//判断互质
bool isMutuality(int e,int fn)
{
if(e>fn||e<1)return false;
if(isPrime(e)&&fn%e!=0)return true;
for(int i = 2;i<=e;i++)
if(e%i==0&&fn%i==0)return false;
return true;
}
//计算d
int getTheD(int e,int fn)
{
for(int i=1;;i++)
if((e*i)%fn==1)return i;
}
//英文数字化
//英文小写
void charToNum(char *str,int *num,int n)
{
for(int i=0;i<n;i++)
num[i]=str[i]-'a'+1;
}
//数字转英文
//英文小写
void numToChar(int *num,char *str,int n)
{
for(int i=0;i<n;i++)
{
str[i]=(num[i]+'a'-1)%256;
}
}
//模指数n运算
int fMod(int c,int n,int e)
{
if(c>n)return 0;
int temp = c;
//cout<<" "<<endl;
//cout<<"c="<<c<<" n="<<n<<" e="<<e<<endl;
for(int i=1;i<e;i++)
{
c*=temp;
c%=n;//防止c过大
}
return c;
}
int num[100];//密文数组最长100
void RSA(int p,int q,int e,char *str)
{
int len = strlen(str);
if(len<=0) return;
if(!(isPrime(p)&&isPrime(q)))return;//非素数
int n = p*q;
int fn = (p-1)*(q-1);
if(!isMutuality(e,fn))return;//e和fn不互质
int d = getTheD(e,fn);//计算d
cout<<"公钥"<<"("<<e<<","<<n<<")"<<endl;
cout<<"密钥"<<"("<<d<<","<<n<<")"<<endl;
charToNum(str,num,len);
cout<<"密文数组:"<<endl;
for(int i=0;i<len;i++)
{
num[i] = fMod(num[i],n,e);
cout<<num[i]<<" ";
}
cout<<endl;
}
//*arrNum 密文数组
void DeRSA(int p,int q,int e,int len)
{
cout<<"\n\n-------解密程序--------"<<endl;
cout<<"当前需要解密的密文数组:"<<endl;
for(int i=0;i<len;i++)
{
cout<<num[i]<<" ";
}
cout<<"\n";
if(len<=0) return;
if(!(isPrime(p)&&isPrime(q)))return;//非素数
int n = p*q;
int fn = (p-1)*(q-1);
if(!isMutuality(e,fn))return;//e和fn不互质
int d = getTheD(e,fn);//计算d
cout<<"公钥"<<"("<<e<<","<<n<<")"<<endl;
cout<<"密钥"<<"("<<d<<","<<n<<")"<<endl;
cout<<"解密后明文数组:"<<endl;
for(int i=0;i<len;i++)
{
num[i] = fMod(num[i],n,d);
cout<<num[i]<<" ";
}
cout<<endl;
char str[100];
numToChar(num,str,len);
cout<<"解密后明文:"<<endl;
cout<<str<<endl;
}
int main()
{
string strM;
int p,q,e;
cout<<"**************************************"<<endl;
cout<<"* 简单RSA加解密程序 *"<<endl;
cout<<"* 需输入p,q,e *"<<endl;
cout<<"* p,q为质数,p*q<32767 *"<<endl;
cout<<"* e与fn=(p-1)*(q-1)互质 *"<<endl;
cout<<"**************************************"<<endl;
cout<<"请输入p:";
cin>>p;
while(!isPrime(p))cout<<"p非素数请重新输入:",cin>>p;
cout<<"请输入q:";
cin>>q;
while(!isPrime(q))cout<<"q非素数请重新输入:",cin>>q;
int fn = (p-1)*(q-1);
cout<<"fn:"<<fn<<endl;
cout<<"请输入e:";
cin>>e;
while(!isMutuality(e,fn))cout<<"e与fn非互质重新输入:",cin>>e;
cout<<"请输入需加密的明文:";
cin>>strM;
RSA(p,q,e,(char*)strM.c_str());
DeRSA(p,q,e,strM.length());
return 0;
}