实验三 RSA算法设计和实现
(4学时)
一、实验目的
掌握并实现RSA算法。
二、实验内容
利用C\C++实现RSA算法的加、解密运算。
具体包括:
1) 利用扩展的EUCLID计算 a mod n 的乘法逆元;
2) Miller-Rabin素性测试算法对一个给定的大数进行测试;
3) 实现的运算,并计算;
4) 利用Fermat定理手工计算,并与3)计算的结果对比;
5) 实现RSA算法。并对"I LOVE THE PEOPLE'S REPUBLIC OF CHINA"加解密。说明:为了方便实现,分组可以小一点,比如两个字母一组。
字母及其数字编码 |
字母及其数字编码 |
空格 00 |
N 14 |
A 01 |
O 15 |
B 02 |
P 16 |
C 03 |
Q 17 |
D 04 |
R 18 |
E 05 |
S 19 |
F 06 |
T 20 |
G 07 |
U 21 |
H 08 |
V 22 |
I 09 |
W 23 |
J 10 |
X 24 |
K 11 |
Y 25 |
L 12 |
Z 26 |
M 13 |
|
三、实验原理
1、RSA算法
1) 密钥的产生
① 选两个保密的大素数p和q。
② 计算n=p×q,φ(n)=(p-1)(q-1),其中φ(n)是n的欧拉函数值。
③ 选一整数e,满足1<e<φ(n),且gcd(φ(n),e)=1。
④ 计算d,满足d·e≡1 mod φ(n),即d是e在模φ(n)下的乘法逆元,因e与φ(n)互素,由模运算可知,它的乘法逆元一定存在。
⑤ 以{e,n}为公开钥,{d,n}为秘密钥。
2) 加密
加密时首先将明文比特串分组,使得每个分组对应的十进制数小于n,即分组长度小于log2n。然后对每个明文分组m,作加密运算: c≡me mod n
3) 解密
对密文分组的解密运算为:
m≡cd mod n
2、涉及的计算
1) 欧几里得(Euclid)算法和扩展的欧几里得(Euclid)算法求乘法逆元
欧几里得(Euclid)算法是数论中的一个基本技术,是求两个正整数的最大公因子的简化过程。而推广的Euclid算法不仅可求两个正整数的最大公因子,而且当两个正整数互素时,还可求出其中一个数关于另一个数的乘法逆元。
欧几里得(Euclid)算法描述如下:
Euclid(f, d) //求最大公因子
1. X←f; Y←d;
2. if Y=0 then return X=gcd(f,d);
3. R=X mod Y;
4. X=Y;
5. Y=R;
6. goto 2。
扩展的欧几里得(Euclid)算法描述如下:
Extended Euclid(f, d) (设 f >d) //扩展的Euclid算法,求出d-1 mod f ,使得d*d-1≡1modf
1. (X1,X2,X3)←(1,0,f);(Y1,Y2,Y3)←(0,1,d);
2. if Y3=0 then return X3=gcd(f, d);no inverse;
3. if Y3=1 then return Y3=gcd(f, d);Y2=d-1 mod f;
4. Q=INT[X3/Y3] ;
5. (T1,T2,T3)←(X1-QY1,X2-QY2,X3-QY3);
6. (X1,X2,X3)←(Y1,Y2,Y3);
7. (Y1,Y2,Y3)←(T1,T2,T3);
8. goto 2。
2) 快速指数算法:给定a,m,n,求d=am mod n, m需要先转换为二进制表示:bkbk-1……b0
算法描述如下:
d=1;
For i=k Downto 0
DO {
d=(d×d) mod n;
if bi=1 then {
d=(d×a) mod n
}
}
return d.
3) 素性检测,其原理基于以下定理:
费尔玛定理 (Fermat) :若p是素数,a是正整数且gcd(a, p)=1,则ap-1≡1 mod p。
引理 :如果p为大于2的素数,则方程x2≡1(mod p)的解只有x≡1和x≡-1。
引理的逆否命题为:如果方程x2≡1 mod p有一解x0∈{-1,1},那么p不为素数
根据上述定理,得到下面的素性检测算法。
任意选择正整数a ,计算d=a n-1 mod n,n-1需要先转换为二进制形式bkbk-1……b0;
为了确定一个数是否素数,此算法需要多次执行,可选择5个不同的a重复执行下列算法,如果每次均返回true 则以很高的几率认为n是素数,否则,不是素数。
Witness(a,n)
for i=k downto 0 do
{
x←d;
d←(d×d) mod n;
if d=1 and(x≠1)and(x≠n-1)then return False;
if bi=1 then d←(d×a) mod n
}
if d≠1 then return False;
return True.
实现代码一:
//devc++可以直接运行 ,其它编译器运行时可能要修改部分代码
#include
#include
#include
using namespace std;
//n大于a
int Euclid(int a,int n){
int x,y,r;
x=n;y=a;
for(int i=0;;){
if(y==0)
return x;
if(y==1)
return y;
r=x%y;
x=y;
y=r;
}
}
//利用扩展的EUCLID计算a mod n的乘法逆元
double extenEuclid(double a,double n){
double x1=1,x2=0,x3=n,y1=0,y2=1,y3=a,Q;
double t1,t2,t3;
for(int i=0;;){
if(y3==0){
return x3;
cout<<"no reverse"< b;
unsigned int N=n-1;
for(int i=0,j=1;; i++){//将n-1表示成二进制形式
if(j>N)
break;
if( (N>> i) & (unsigned int)1 ){
b.push_back(1);
return true;
}
else{
b.push_back(0);
return false;
}
j*=2;
}
}
void transfer(char cypher[],double c[]){
int m[100]={0};
for(int i=0,j=0;cypher[j]!='\0';i+=2){
if(cypher[j]==' '){
m[i]=0;m[i+1]=0;
}
else{
m[i]=cypher[j]-64;
if(m[i]<10){
m[i+1]=m[i];
m[i]=0;
}
else{
m[i+1]=m[i]%10;
m[i]=m[i]/10;
}
}
j++;
}
for(int k2=0;k2<2*strlen(cypher);k2++)
cout<b;
unsigned int N=m;
for(int ii=0,j=1;;ii++){
if(j>N)
break;
if((N>>ii)& (unsigned int) 1)
b.push_back(1);
else
b.push_back(0);
j*=2;
}
double c=0,d=1;
for(int i=b.size()-1;i>=0;i--){
c*=2;
d=(d*d)-int((d*d)/n)*n;
if(b[i]==1){
c+=1;
d=(d*a)-int((d*a)/n)*n;
}
}
return d;
}
//主函数
int main(){
double c[100]={0};
double a[100]={0};
double b[100]={0};
char cypher[]="I LOVE THE PEOPLE'S REPUBLIC OF CHINA";//对“我爱中华人民共和国”加解密
transfer(cypher,c);//字母变数字的过程
for(int k1=0;c[k1]!='\0';k1++)
cout<
#include
#include
#include
using namespace std;
typedef int Elemtype;
Elemtype p, q, e;
Elemtype fn;
Elemtype m, c;
int flag = 0;
typedef void(*Msghandler)(void);
struct MsgMap
{
char ch;
Msghandler handler;
};
/*公钥*/
struct PU
{
Elemtype e;
Elemtype n;
} pu;
/*私钥*/
struct PR
{
Elemtype d;
Elemtype n;
} pr;
/*判定一个数是否为素数*/
bool test_prime(Elemtype m)
{
if(m <= 1)
{
return false;
}
else if(m == 2)
{
return true;
}
else
{
for(int i = 2; i <= sqrt(m); i++)
{
if((m % i) == 0)
{
return false;
break;
}
}
return true;
}
}
/*将十进制数据转化为二进制数组*/
void switch_to_bit(Elemtype b, Elemtype bin[32])
{
int n = 0;
while(b > 0)
{
bin[n] = b % 2;
n++;
b /= 2;
}
}
/*初始化主界面*/
void Init()
{
cout << "1.设置密钥" << endl;
cout << "2.加密" << endl;
cout << "3.解密" << endl;
cout << "4.退出" << endl;
//cout << "输入选择: " ;
}
/*将两个数排序,大的在前面*/
void order(Elemtype &in1, Elemtype &in2)
{
Elemtype a = (in1 > in2 ? in1 : in2);
Elemtype b = (in1 < in2 ? in1 : in2);
in1 = a;
in2 = b;
}
/*求最大公约数*/
Elemtype gcd(Elemtype a, Elemtype b)
{
order(a, b);
int r;
if(b == 0)
{
return a;
}
else
{
while(true)
{
r = a % b;
a = b;
b = r;
if(b == 0)
{
return a;
break;
}
}
}
}
/*用扩展的欧几里得算法求乘法逆元*/
Elemtype extend_euclid(Elemtype m, Elemtype bin)
{
order(m, bin);
Elemtype a[3], b[3], t[3];
a[0] = 1, a[1] = 0, a[2] = m;
b[0] = 0, b[1] = 1, b[2] = bin;
if(b[2] == 0)
{
return a[2] = gcd(m, bin);
}
if(b[2] == 1)
{
return b[2] = gcd(m, bin);
}
while(true)
{
if(b[2] == 1)
{
return b[1];
break;
}
int q = a[2] / b[2];
for(int i = 0; i < 3; i++)
{
t[i] = a[i] - q * b[i];
a[i] = b[i];
b[i] = t[i];
}
}
}
/*快速模幂算法*/
Elemtype modular_multiplication(Elemtype a, Elemtype b, Elemtype n)
{
Elemtype f = 1;
Elemtype bin[32];
switch_to_bit(b, bin);
for(int i = 31; i >= 0; i--)
{
f = (f * f) % n;
if(bin[i] == 1)
{
f = (f * a) % n;
}
}
return f;
}
/*产生密钥*/
void produce_key()
{
cout << "输入素数 p 和 q:";
cin >> p >> q;
while(!(test_prime(p) && test_prime(q)))
{
cout << "输入错误,请重新输入!" << endl;
cout << "输入素数 p 和 q:";
cin >> p >> q;
};
pr.n = p * q;
pu.n = p * q;
fn = (p - 1) * (q - 1);
cout << "fn为:" << fn << endl;
cout << "输入随机数e:";
cin >> e;
while((gcd(fn, e) != 1))
{
cout << "e输入错误,请重新输入!" << endl;
cout << "输入随机数e:";
cin >> e;
}
pr.d = (extend_euclid(fn, e) + fn) % fn;
pu.e = e;
flag = 1;
cout << "公钥(e,n):" << pu.e << "," << pu.n << endl;
cout << "私钥d:" << pr.d << endl;
cout << "请输入下一步操作序号:" << endl;
}
/*加密*/
void encrypt()
{
if(flag == 0)
{
cout << "setkey first:" << endl;
produce_key();
}
cout << "输入明文 m:";
cin >> m;
c = modular_multiplication(m, pu.e, pu.n);
cout << "密文c 为:" << c << endl;
cout << "请输入下一步操作序号:" << endl;
}
/*解密*/
void decrypt()
{
if(flag == 0)
{
cout << "setkey first:" << endl;
produce_key();
}
cout << "输入密文 c:";
cin >> c;
m = modular_multiplication(c, pr.d, pr.n);
cout << "明文m 为:" << m << endl;
cout << "请输入下一步操作序号:" << endl;
}
/*消息映射*/
MsgMap Messagemap[] =
{
{'1', produce_key},
{'3', decrypt},
{'2', encrypt},
{'4', NULL}
};
/*主函数,提供循环*/
int main()
{
Init();
char d;
while((d = getchar()) != '4')
{
int i = 0;
while(Messagemap[i].ch)
{
if(Messagemap[i].ch == d)
{
Messagemap[i].handler();
break;
}
i++;
}
}
return 0;
}