(7).解密:
计算x=ydmodn,恢复出明文x
(B)附:
Rabin-Miller素数检验算法
(1)选择一个小于p随机数a
(2)设j=0且z=ammodp
(3)如果z=1或z=p-1,那么p通过测试,可能是素数
(4)如果j>0且z=1,那么p不是素数
(5)设j=j+1。
如果j
如果z=p-1,那么p通过测试,可能是素数
(6)如果j=b且z≠p-1,那么p不是素数
2.源程序有良好人机界面,书写实验报告,于11月22日提交。
四、实验内容与步骤
1. 实现公钥密码算法RSA算法流程
2.实验步骤(主要代码)
(1)随机产生素数randomprimep、randomprimeq并判断randomprimep、randomprimeq是否为素数:
intrandomprimep=0;//素数p初始赋值为零
intrandomprimeq=0;//素数q初始赋值为零
Randomrand=newRandom();
randomprimep=10+rand.nextInt(200);//随机产生素数p
while(ifPrime(randomprimep))//判断p是否为素数
{
randomprimep=10+rand.nextInt(200);
}
randomprimeq=10+rand.nextInt(200);//随机产生素数q
while(ifPrime(randomprimeq))//判断q是否为素数
{
randomprimeq=10+rand.nextInt(200);
}
(2)计算模keyn(keyn公开):
keyn=randomprimep*randomprimeq;
(3)计算欧拉函数eulern(eulern保密),丢弃randomprimep和randomprimeq:
eulern=(randomprimep-1)*(randomprimeq-1);
randomprimep=randomprimeq=0;//销毁两个随机素数
(4)生成公钥:
publickeye=10+rand.nextInt(200);//随机产生公钥
while(relativePrime(publickeye,eulern))//判断随机公钥与公私钥相同部分的欧拉数是否为相对素数
{
publickeye=10+rand.nextInt(200);
}
(5)用简捷方法求私钥:
booleanmark=true;//用简捷方法求私钥,从模逆运算原始定义出发
intk=0;
while(mark)
{
k++;
if((k*eulern+1)%publickeye==0)
mark=false;
}
privatekeyd=(k*eulern+1)/publickeye;//计算私钥
(6)加密:
RandomAccessFilerafr=newRandomAccessFile(source,"r");//定义源文件
RandomAccessFilerafw=newRandomAccessFile(destination,"rw");//定义目标文件
Stringunderstandtxts="";//明文初始赋值
Stringpasswordtxts="";//密文初始赋值
understandtxts=rafr.readLine();//从源文件中读取数据赋值给明文变量
passwordtxts=passwordtxts+fastPowerMultiplication((int)eachchar[i],publickeye,keyn)+getRandomString();//用公钥将明文加密后并赋值给密文变量rafw.writeBytes(passwordtxts);//将密文写入目标文件中
rafr.close();//关闭源文件
rafw.close();//关闭目标文件
(7)解密:
RandomAccessFilerafr=newRandomAccessFile(source,"r");//定义源文件
RandomAccessFilerafw=newRandomAccessFile(destination,"rw");//定义目标文件
Stringunderstandtxts="";//明文初始赋值
Stringpasswordtxts="";//密文初始赋值
passwordtxts=rafr.readLine();//从源文件中读取加密后的数据并赋值给密文变量
understandtxts=understandtxts+(char)fastPowerMultiplication(intchar,privatekeyd,keyn);//用私钥将密文解密后并赋给明文变量
rafw.writeBytes(understandtxts);//将解密后的明文写入目标文件中
rafr.close();//关闭源文件
rafw.close();//关闭目标文件
3、主要的函数
(1)判断一个整型数据是否为素数:
publicbooleanifPrime(intnumber)//number为素数,mark返回false;否则,返回true
{
booleanmark=false;//mark初始赋值为false
for(inti=2;i{
if(number%i==0)//整型数据number能被除1和它本身之外的数i整除
{
mark=true;//mark赋值为true
break;//结束if循环体
}
}
returnmark;//返回mark值
}
(2)判断两个整型数据是否互为素数:
publicbooleanrelativePrime(inte,intn)//number为素数,mark返回false;否则,返回true
{
booleanmark=false;//mark初始赋值为false
for(inti=2;i<=n;i++)
{
if(n%i==0)//整型数据n能被除1和它本身之外的数i整除
if(e%i==0)//整型数据e能被除1和它本身之外的数i整除{
mark=true;//mark赋值为true
break;//结束if循环体
}
}
returnmark;//返回mark值
}
(3)求一个整型数据的欧拉数:
publicintgetPrivateKeyexp(intnumber)
{
inteulernumber=0;//eulernumber初始化
for(inti=2;i{
if(relativePrime(i,number)==false)//判断两个整型数据是否互为素数
{
System.out.println("相互素数:
"+i+","+number);
eulernumber++;//互为素数,则欧拉数加1
}
}
System.out.println(eulernumber);//输出欧拉数
returneulernumber+1;//返回欧拉数+1
}
(4)模n的大数幂乘快速运算(a底数、b指数、n模数、c大数幂乘结果)
publicintfastPowerMultiplication(inta,intb,intn)
{
intc=1;
while(b!
=0)//指数b不为零
{
while(b%2==0)//指数b是偶数
{
b=b/2;
a=(a*a)%n;
}
b=b-1;//指数b不是偶数,则减1
c=(c*a)%n;
}
returnc;
}
(5)主函数:
publicstaticvoidmain(String[]args)
{
Rsarsa=newRsa();
rsa.dataEncryption("b.txt","c.txt");//调用加密函数,b.txt存放初始明文,c.txt存放加密后的密文
rsa.dataDeciphering("c.txt","d.txt");//调用解密函数,d.txt存放解密后的明文
}
}
4、实验结果
五、实验总结
通过本次实验,了解并明白了RSA算法以及与之有关的数学公式,同时也掌握了如何编写随机生成素数以及计算私钥的程序的核心概念,并且学会了在编程里怎么运用读写文件的操作。
在编程的过程中,遇到不明白的地方都会向XX或者Google请教,很多问题都逐个地解决了。
不足的地方就是缺乏没能实现图形界面,在今后的实验当中尽力弥补。
源代码:
importjava.io.*;
importjava.util.Random;
publicclassRsa
{
privateintkeyn;
privateintpublickeye;
privateintprivatekeyd;
publicRsa()
{
intrandomprimep=0;
intrandomprimeq=0;
inteulern=0;
Randomrand=newRandom();
randomprimep=10+rand.nextInt(200);
while(ifPrime(randomprimep))
{
randomprimep=10+rand.nextInt(200);
}
randomprimeq=10+rand.nextInt(200);
while(ifPrime(randomprimeq))
{
randomprimeq=10+rand.nextInt(200);
}
keyn=randomprimep*randomprimeq;
eulern=(randomprimep-1)*(randomprimeq-1);
randomprimep=randomprimeq=0;
publickeye=10+rand.nextInt(200);
while(relativePrime(publickeye,eulern))
{
publickeye=10+rand.nextInt(200);
}
booleanmark=true;
intk=0;
while(mark)
{
k++;
if((k*eulern+1)%publickeye==0)
mark=false;
}
privatekeyd=(k*eulern+1)/publickeye;
System.out.println("公钥为:
("+publickeye+","+keyn+")");
System.out.println("私钥为:
("+privatekeyd+","+keyn+")");
}
publicbooleanifPrime(intnumber)
{
booleanmark=false;
for(inti=2;i{
if(number%i==0)
{
mark=true;
break;
}
}
returnmark;
}
publicbooleanrelativePrime(inte,intn)
{
booleanmark=false;
for(inti=2;i<=n;i++)
{
if(n%i==0)
if(e%i==0)
{
mark=true;
break;
}
}
returnmark;
}
publicintfastPowerMultiplication(inta,intb,intn)
{
intc=1;
while(b!
=0)
{
while(b%2==0)
{
b=b/2;
a=(a*a)%n;
}
b=b-1;
c=(c*a)%n;
}
returnc;
}
publicintgetPrivateKeyexp(intnumber)
{
inteulernumber=0;
for(inti=2;i{
if(relativePrime(i,number)==false)
{
System.out.println("相互素数:
"+i+","+number);
eulernumber++;
}
}
System.out.println(eulernumber);
returneulernumber+1;
}
publicvoiddataEncryption(Stringsource,Stringdestination)
{
try
{
RandomAccessFilerafr=newRandomAccessFile(source,"r");
RandomAccessFilerafw=newRandomAccessFile(destination,"rw");
Stringunderstandtxts="";
Stringpasswordtxts="";
char[]eachchar;
intcharint=0;
booleanmark=false;
try
{
longfilelength=rafr.length();
longpos=0;
while(pos!
=filelength)
{
understandtxts=rafr.readLine();
eachchar=understandtxts.toCharArray();
for(inti=0;i{
charint=(int)eachchar[i];
if(charint>127||charint<10)
{
System.out.println("加密失败!
原文中包含不能加密的字符。
");
mark=true;
break;
}
}
if(mark)
{
break;
}
pos=rafr.getFilePointer();
}
rafr.seek(0);
pos=0;
if(!
mark)
{
System.out.println("从文件读入明文:
");
while(pos!
=filelength)
{
System.out.println(rafr.readLine());
pos=rafr.getFilePointer();
}
rafr.seek(0);
pos=0;
System.out.println("明文加密后密文:
");
while(true)
{
understandtxts=rafr.readLine();
eachchar=understandtxts.toCharArray();
for(inti=0;i{
passwordtxts=passwordtxts+fastPowerMultiplication((int)eachchar[i],publickeye,keyn)+getRandomString();
}
System.out.println(passwordtxts);
rafw.writeBytes(passwordtxts);
pos=rafr.getFilePointer();
if(pos==filelength)
{
break;
}
passwordtxts="";
rafw.writeChar('');
}
}
}
catch(Exceptione)
{
e.printStackTrace(System.out);
}
finally
{
rafr.close();
rafw.close();
}
}
catch(IOExceptionex)
{
ex.printStackTrace(System.out);
}
}
publicStringgetRandomString()
{
Randomrand=newRandom();
Stringrandstr="";
intnumber=1+rand.nextInt(5);
intcharint=65+rand.nextInt(26);
for(inti=0;i{
randstr=randstr+(char)charint;
charint=65+rand.nextInt(26);
}
returnrandstr;
}
publicvoiddataDeciphering(Stringsource,Stringdestination)
{
try
{
RandomAccessFilerafr=newRandomAccessFile(source,"r");
RandomAccessFilerafw=newRandomAccessFile(destination,"rw");
Stringunderstandtxts="";
Stringpasswordtxts="";
char[]eachchar;
intintchar=0;
booleanmark=false;
try
{
longfilelength=rafr.length();
longpos=0;
intj=0;
System.out.println("密文解密后明文:
");
while(true)
{
passwordtxts=rafr.readLine();
eachchar=passwordtxts.toCharArray();
for(inti=0;i{
if(Character.isDigit(eachchar[i]))
{
intchar=10*intchar+Integer.valueOf(String.valueOf(eachchar[i]));
}
else
{
j=i-1;
if(Character.isDigit(eachchar[j])&&!
Character.isDigit(eachchar[i]))
{
understandtxts=understandtxts+(char)fastPowerMultiplication(intchar,privatekeyd,keyn);
intchar=0;
}
}
}
System.out.println(understandtxts);
rafw.writeBytes(understandtxts);
pos=rafr.getFilePointer();
if(pos==filelength)
{
break;
}
System.out.println('');
understandtxts="";
}
}
catch(Exceptione)
{
e.printStackTrace(System.out);
}
finally
{
rafr.close();
rafw.close();
}
}
catch(IOExceptionex)
{
ex.printStackTrace(System.out);
}
}
publicstaticvoidmain(String[]args)
{
Rsarsa=newRsa();
rsa.dataEncryption("b.txt","c.txt");
rsa.dataDeciphering("c.txt","d.txt");