大连海事大学本科生实验报告
《电子商务安全技术》实验报告
院 (系): 交通运输管理学院
专业班级:电子商务 2011级1班
课程名称: 电子商务安全技术
姓 名: 周慧敏
学 号: 2220113494
指导教师: 张 偲
完成日期:20##年 11月20日
实验一:RSA算法
一、 实验名称:
编程实现RSA算法
二、 实验目的
RSA算法是理论上最为成熟的公开密钥体制,目前在电子商务安全技术领域得到了广泛应用。
1.理解RSA算法原理及其应用。
2.掌握RSA算法的程序实现过程。
3. 学会使用RSA算法对数据进行加密和解密
三、 实验要求
1. 编写程序,完成下列功能,运行程序并记录运行结果。
(A)RSA算法的7个步骤:
(1).取两个随机素数p和q( p和q保密)
(2).计算模 n=p*q(n公开)
(3).计算欧拉函数j(n) =(p-1)*(q-1)( j(n)保密),丢弃p和q
(4).随机选取整数e,满足 gcd(e, j(n))=1 ( e和n为公钥)
(5).计算d满足d*e≡1 mod j(n)(d和n为私钥)
(6).加密:将明文分组,每组长度x<n, 计算 y =xe mod n,产生密文 y
(7).解密:计算 x= y d mod n,恢复出明文 x
(B)附:Rabin-Miller素数检验算法
(1)选择一个小于p随机数a
(2)设 j=0且 z=am mod p
(3)如果z=1或z=p-1,那么p通过测试,可能是素数
(4)如果j>0且z=1,那么p不是素数
(5)设j=j+1。如果j<b且z≠p-1,设z=z2 mod p,然后回到第(4)步。
如果z=p-1,那么p通过测试,可能是素数
(6)如果j=b且z≠p-1,那么p不是素数
2.源程序有良好人机界面,书写实验报告,于11月22日提交。
四、 实验内容与步骤
1. 实现公钥密码算法RSA算法流程
2. 实验步骤(主要代码)
(1)随机产生素数randomprimep、randomprimeq并判断randomprimep、randomprimeq是否为素数:
int randomprimep = 0; //素数p初始赋值为零
int randomprimeq = 0; //素数q初始赋值为零
Random rand = new Random();
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)用简捷方法求私钥:
boolean mark = true; //用简捷方法求私钥,从模逆运算原始定义出发
int k = 0;
while (mark)
{
k++;
if((k * eulern + 1)%publickeye == 0)
mark = false;
}
privatekeyd = (k * eulern + 1)/publickeye; //计算私钥
(6)加密:
RandomAccessFile rafr = new RandomAccessFile(source,"r");//定义源文件
RandomAccessFile rafw = new RandomAccessFile(destination,"rw"); //定义目标文件
String understandtxts = "";//明文初始赋值
String passwordtxts = "";//密文初始赋值
understandtxts = rafr.readLine();//从源文件中读取数据赋值给明文变量
passwordtxts = passwordtxts + fastPowerMultiplication((int)eachchar[i],publickeye,keyn) + getRandomString();//用公钥将明文加密后并赋值给密文变量 rafw.writeBytes(passwordtxts);//将密文写入目标文件中
rafr.close();//关闭源文件
rafw.close();//关闭目标文件
(7)解密:
RandomAccessFile rafr = new RandomAccessFile(source,"r");//定义源文件
RandomAccessFile rafw = new RandomAccessFile(destination,"rw"); //定义目标文件
String understandtxts = "";//明文初始赋值
String passwordtxts = "";//密文初始赋值
passwordtxts = rafr.readLine();//从源文件中读取加密后的数据并赋值给密文变量
understandtxts = understandtxts + (char)fastPowerMultiplication(intchar,privatekeyd,keyn);//用私钥将密文解密后并赋给明文变量
rafw.writeBytes(understandtxts);//将解密后的明文写入目标文件中
rafr.close();//关闭源文件
rafw.close();//关闭目标文件
3、主要的函数
(1)判断一个整型数据是否为素数:
public boolean ifPrime(int number)//number为素数,mark返回false;否则,返回true
{
boolean mark = false;//mark初始赋值为false
for (int i = 2;i < number/2 ;i++ )
{
if (number%i == 0)//整型数据number能被除1和它本身之外的数i整除
{
mark = true;//mark赋值为true
break;//结束if循环体
}
}
return mark;//返回mark值
}
(2)判断两个整型数据是否互为素数:
public boolean relativePrime(int e,int n) //number为素数,mark返回false;否则,返回true
{
boolean mark = false; //mark初始赋值为false
for (int i = 2;i <= n ;i++ )
{
if (n%i == 0) //整型数据n能被除1和它本身之外的数i整除
if (e%i == 0) //整型数据e能被除1和它本身之外的数i整除 {
mark = true; //mark赋值为true
break; //结束if循环体
}
}
return mark; //返回mark值
}
(3)求一个整型数据的欧拉数:
public int getPrivateKeyexp(int number)
{
int eulernumber = 0;// eulernumber初始化
for (int i = 2;i < number ;i++ )
{
if(relativePrime(i,number) == false)//判断两个整型数据是否互为素数
{
System.out.println("相互素数:" + i + "," + number);
eulernumber++;//互为素数,则欧拉数加1
}
}
System.out.println(eulernumber);//输出欧拉数
return eulernumber + 1;//返回欧拉数+1
}
(4)模n的大数幂乘快速运算(a底数、b指数、n模数、c大数幂乘结果)
public int fastPowerMultiplication(int a,int b,int n)
{
int c = 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;
}
return c;
}
(5)主函数:
public static void main(String[] args)
{
Rsa rsa = new Rsa();
rsa.dataEncryption("b.txt","c.txt");//调用加密函数,b.txt存放初始明文,c.txt存放加密后的密文
rsa.dataDeciphering("c.txt","d.txt");//调用解密函数,d.txt存放解密后的明文
}
}
4、实验结果
五、实验总结
通过本次实验,了解并明白了RSA算法以及与之有关的数学公式,同时也掌握了如何编写随机生成素数以及计算私钥的程序的核心概念,并且学会了在编程里怎么运用读写文件的操作。在编程的过程中,遇到不明白的地方都会向百度或者Google请教,很多问题都逐个地解决了。不足的地方就是缺乏没能实现图形界面,在今后的实验当中尽力弥补。
源代码:
import java.io.*;
import java.util.Random;
publicclass Rsa
{
privateint keyn;
privateint publickeye;
privateint privatekeyd;
public Rsa()
{
int randomprimep = 0;
int randomprimeq = 0;
int eulern = 0;
Random rand = new Random();
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);
}
boolean mark = true;
int k = 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 + ")");
}
publicboolean ifPrime(int number)
{
boolean mark = false;
for (int i = 2;i < number/2 ;i++ )
{
if (number%i == 0)
{
mark = true;
break;
}
}
return mark;
}
publicboolean relativePrime(int e,int n)
{
boolean mark = false;
for (int i = 2;i <= n ;i++ )
{
if (n%i == 0)
if (e%i == 0)
{
mark = true;
break;
}
}
return mark;
}
publicint fastPowerMultiplication(int a,int b,int n)
{
int c = 1;
while (b != 0)
{
while (b%2 == 0)
{
b = b/2;
a = ( a * a )%n;
}
b = b - 1;
c = ( c * a )%n;
}
return c;
}
publicint getPrivateKeyexp(int number)
{
int eulernumber = 0;
for (int i = 2;i < number ;i++ )
{
if(relativePrime(i,number) == false)
{
System.out.println("相互素数:" + i + "," + number);
eulernumber++;
}
}
System.out.println(eulernumber);
return eulernumber + 1;
}
publicvoid dataEncryption(String source,String destination)
{
try
{
RandomAccessFile rafr = new RandomAccessFile(source,"r");
RandomAccessFile rafw = new RandomAccessFile(destination,"rw");
String understandtxts = "";
String passwordtxts = "";
char [] eachchar;
int charint = 0;
boolean mark = false;
try
{
long filelength = rafr.length();
long pos = 0;
while (pos != filelength)
{
understandtxts = rafr.readLine();
eachchar = understandtxts.toCharArray();
for (int i = 0 ;i < eachchar.length ;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 (int i = 0;i < eachchar.length ;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 (Exception e)
{
e.printStackTrace(System.out);
}
finally
{
rafr.close();
rafw.close();
}
}
catch (IOException ex)
{
ex.printStackTrace(System.out);
}
}
public String getRandomString()
{
Random rand = new Random();
String randstr = "";
int number = 1 + rand.nextInt(5);
int charint = 65 + rand.nextInt(26);
for (int i = 0;i < number ;i++ )
{
randstr = randstr + (char)charint;
charint = 65 + rand.nextInt(26);
}
return randstr;
}
publicvoid dataDeciphering(String source,String destination)
{
try
{
RandomAccessFile rafr = new RandomAccessFile(source,"r");
RandomAccessFile rafw = new RandomAccessFile(destination,"rw");
String understandtxts = "";
String passwordtxts = "";
char [] eachchar;
int intchar = 0;
booleanmark = false;
try
{
long filelength = rafr.length();
long pos = 0;
int j = 0;
System.out.println("密文解密后明文:");
while (true)
{
passwordtxts = rafr.readLine();
eachchar = passwordtxts.toCharArray();
for (int i = 0;i < eachchar.length ;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 (Exception e)
{
e.printStackTrace(System.out);
}
finally
{
rafr.close();
rafw.close();
}
}
catch (IOException ex)
{
ex.printStackTrace(System.out);
}
}
publicstaticvoid main(String[] args)
{
Rsa rsa = new Rsa();
rsa.dataEncryption("b.txt","c.txt");
rsa.dataDeciphering("c.txt","d.txt");
}
}