密码学实验4.docx
《密码学实验4.docx》由会员分享,可在线阅读,更多相关《密码学实验4.docx(15页珍藏版)》请在冰豆网上搜索。
![密码学实验4.docx](https://file1.bdocx.com/fileroot1/2023-2/5/4f87ef8b-7081-41c7-9158-b6cdf4b4101d/4f87ef8b-7081-41c7-9158-b6cdf4b4101d1.gif)
密码学实验4
实验4非对称密码算法RSA
一、实验目的
通过实际编程了解非对称密码算法RSA的加密和解密过程,加深对非对称密码算法的认识。
二、实验原理
1、算法原理
步骤如下(这里设B为是实现者)
(1)B寻找出两个大素数p和q。
(2)B计算出n=p*q和
(n)=)(p-1)*(q-1)。
(3)B选择一个随机数e(0(n)),满足(e,
(n))=1(即e与欧拉函数互素
(n))。
(4)B使用欧几里得算法计算e的模余
(n)的乘法逆元素d。
(5)B在目录中公开n和e作为他的公开密钥,保密p、q和d。
加密时,对每一明文m计算密文
cΞme(modn)
解密时,对每一密文c计算明文
mΞcd(modn)
三、实验环境
运行Windows或者Linux操作系统的PC机,具有gcc(Linux)、VC(Windows)等C语言编译环境。
四、实验内容
1、为了加深对
算法的了解,根据输入的参数p,q,M,手工计算公私钥,并对明文进行加密,然后对密文进行解密。
2、编写
程序,加密一段文字,了解
算法原理。
尝试加密一大段文字,记录程序的运行时间。
使用DES算法加密相同的文字,比较两种算法加密的速度。
3、编写一个程序,随机选择3个较大的数
,计算
,记录程序运行时间。
查阅资料给出简单说明大数在计算机上是如何表示,如何进行运算。
4、查阅资料,找出目前实际可行的素数判定法则,并比较各自的优缺点。
五、实验步骤
1、主要函数说明
(1)判断一个数是否为素数函数
boolprime(intn)
{
intm=sqrt(n);
for(inti=2;i{
if(n%i==0)
break;
}
if(i>=m)
return1;
elsereturn0;
}
(2)模幂算法(这里以明文m为一个为例)
①令f=1;
②用for循环遍历从i=1到i=b,令f=(f*a)%n
③输出f,f的值即为模幂的结果。
intmultiplication(inta,intb,intn)
{
intf=1;
for(inti=1;i<=b;i++)
{
f=(f*a)%n;
}
returnf;
}
(3)扩展欧几里得算法
由扩展欧几里得算法可以计算整数s和t,使得s*e+t*N=(e,N)=1,则e的乘法逆元等价于smodN。
①定义变量x1,x2,x3,y1,y2,y3,t1,t2,t3,q;
②令x1=y2=1;x2=y1=0;
③计算q=x3/y3;t1=x1-q*y1;
t2=x2-q*y2;t3=x3-q*y3;
④x1=y1;x2=y2;x3=y3;y1=t1;y2=t2;y3=t3;
⑤当y3=1时,*result=y2;result的结果即为所求乘法逆元;如果y3!
=1,则返回顺序执行③、④步直到满足y3=1
intExtendedEuclid(intf,intd,int*result)
{
intx1,x2,x3,y1,y2,y3,t1,t2,t3,q;
x1=y2=1;
x2=y1=0;
if(f>=d)
{
x3=f;
y3=d;
}
else
{
x3=d;
y3=f;
}
while
(1)
{
if(y3==1)
{
*result=y2;/*两个数互素则resutl为其乘法逆元,此时返回值为1*/
return1;
}
q=x3/y3;
t1=x1-q*y1;
t2=x2-q*y2;
t3=x3-q*y3;
x1=y1;
x2=y2;
x3=y3;
y1=t1;
y2=t2;
y3=t3;
}
}
(4)主函数
①输入两个数字判断是否为素数,当不为素数时重新输入。
如输入1711
②输入e,得到公钥。
如输入e为7
③调用ExtendedEuclid(e,N,&d)函数,得到d,和私钥。
如d=23
④输入明文长度。
如输入5如输入明文为5688781223
⑤开始加密,调用加密函数Encryption()。
则输入密文为781156177133
⑥开始解密,调用解密函数Decipher()。
则解密后明文为5688781223
2、打开VC++,编写程序如下:
#include
#include
intp,q,n,e,d,N,m1[100],m2[100],len;
//判断一个数是否为素数,为素数返回1,否则返回0
boolprime(intn)
{
intm=sqrt(n);
for(inti=2;i{
if(n%i==0)
break;
}
if(i>=m)
return1;
elsereturn0;
}
//扩展欧几里得算法求乘法逆元,两数互素返回1
intExtendedEuclid(intf,intd,int*result)
{
intx1,x2,x3,y1,y2,y3,t1,t2,t3,q;
x1=y2=1;
x2=y1=0;
if(f>=d)
{
x3=f;
y3=d;
}
else
{
x3=d;
y3=f;
}
while
(1)
{
if(y3==1)
{
*result=y2;/*两个数互素则resutl为其乘法逆元,此时返回值为1*/
return1;
}
q=x3/y3;
t1=x1-q*y1;
t2=x2-q*y2;
t3=x3-q*y3;
x1=y1;
x2=y2;
x3=y3;
y1=t1;
y2=t2;
y3=t3;
}
}
//将十进制数据转化为二进制数组
voidto_bit(intb,intbit[32])
{
intn=0;
while(b>0)
{
bit[n]=b%2;
n++;
b/=2;
}
}
//模幂算法
intmultiplication(inta,intb,intn)
{
intf=1;
for(inti=1;i<=b;i++)
{
f=(f*a)%n;
}
returnf;
}
//加密函数
voidEncryption()
{
cout<<"******************开始加密*****************"<inti;
cout<<"请输入明文:
";
for(i=0;icin>>m1[i];
for(i=0;im2[i]=multiplication(m1[i],e,n);
cout<<"加密后的密文为:
";
for(i=0;icout<cout<}
//解密函数
voidDecipher()
{
inti;
cout<<"*************开始解密*************"<for(i=0;im2[i]=multiplication(m2[i],d,n);
cout<<"解密后的明文为:
";
for(i=0;icout<cout<}
voidmain()
{
cout<<"输入两个素数p和q:
\n";
while
(1)
{
cin>>p;
if(prime(p))
{
cout<
break;
}
else
{
cout<
continue;
}
}
while
(1)
{
cin>>q;
if(prime(q))
{
cout<break;
}
else
{
cout<continue;
}
}
cout<<"两个素数为:
"<
n=p*q;
N=(p-1)*(q-1);
for(inti=2;i{
if(N%i==0)
{
cout<
}
}
cout<cout<<"请输入一个随机数,该数不等于上面的任何一个数!
"<cin>>e;
cout<<"公钥为<"<"<if(ExtendedEuclid(e,N,&d))
cout<"<cout<<"私钥为<"<"<cout<<"请输入明文长度:
";
cin>>len;
Encryption();
Decipher();
}
调试程序,程序运行如下:
3、打开VC++,编写程序如下:
(此程序错误,因为数值过大产生溢出,请改之)
#include
#include
#include
#include
#include
#include
#include
//usingnamespacestd;
intmain(){
clock_tstart,end;
longtimes;
longx,e,n;
cout<<"随机产生3个大数:
"<//x=1000*(rand()%11)+100*(rand()%11)+10*(rand()%11)+rand()%11;
x=1000000*(rand()%11)+100000*(rand()%11)+10000*(rand()%11)+1000*(rand()%11)+
100*(rand()%11)+10*(rand()%11)+rand()%11;
e=1000000*(rand()%11)+100000*(rand()%11)+10000*(rand()%11)+1000*(rand()%11)+
100*(rand()%11)+10*(rand()%11)+rand()%11;
n=1000000*(rand()%11)+100000*(rand()%11)+10000*(rand()%11)+1000*(rand()%11)+
100*(rand()%11)+10*(rand()%11)+rand()%11;
cout<<"x="<start=clock();
cout<longanswer=(int)pow(x,e)%n;//指数运算
end=clock();
times=1000*(end-start);
cout<<"花费的时间为:
"<return0;
}
调试运行如下:
计算机上大数表示方法:
将大数看作一个n进制数组,对于目前的32位系统而言,n可以取值为2的32次方,即0x10000000,假如将一个1024位的大数转化成0x10000000进制,它就变成了32位,而每一位的取值范围就不是0-1或0-9,而是0-0xfffffff.我们正好可以用一个无符号长整数来表示这一数值.所以1024位的大整数就是一个有32个元素的unsignedlong数组.而且0x10000000进制的数组排列与2进制流对于计算机来说,实际上是一回事,但是我们完全可以针对unsighedlong数组进行”竖式计算”,而循环规模被降低到了32次之内,并且算法很容易理解.
4、素性测试方法:
所谓素数,是指除了能被1和它本身整除而不能被其他任何数整除的数。
据此,只需用2到N-1去除N,如果都除不尽,则为素数
(1)flag=1,i=2
(2)Ifnmodi=0thenflag=1elsei=i+1
(3)Ifflag=0andi(2)else(4)
(4)Ifflag=0thenwriteyeselseno
在最坏的情况下,即N为素数,算法需要执行N-2次,时间复杂性太大。
只需用2到根下N去除N,即可,于是上述算法改为
(3)Ifflag=0andi<=int(根N)then
(2)else(4)
虽然快了不小,但有重复计算,如果用2去除N时若不尽,则用2的倍数去除N也除不尽,由此得
(1)for(i=2;int(根N);i++)mark[i]=0;//mark是标记其初值为0,只要它的因子除不尽其值变为1
(2)i=2,flag=0
(3)while(flag=0andiIfmark[i]=0
Then{
Ifnmodi=0
Thenflag=1
S=i+i
WhilesMark[s]=1
S=s+i
}
}
I=i+1
}
(4)ifflag=0thenyeselseno