实验四
北京电子科技学院(BESTI)
实 验 报 告
课程:Java程序设计 班级:1351 姓名:黄君如 学号:20135117
成绩: 指导教师:娄嘉鹏 实验日期:2015.6.9
实验密级: 预习程度: 实验时间:15:30-18:30
仪器组次: 必修/选修:选修 实验序号:4
实验名称:
实验目的与要求:1.没有Linux基础的同学建议先学习《Linux基础入门(新版)》《Vim编辑器》课程
2.完成实验、撰写实验报告,实验报告以博客方式发表在博客园,注意实验报告重点是运行结果,遇到的问题(工具查找,安装,使用,程序的编辑,调试,运行等)、解决办法(空洞的方法如“查网络”、“问同学”、“看书”等一律得0分)以及分析(从中可以得到什么启示,有什么收获、教训等)
3. 严禁抄袭,有该行为者实验成绩归零,并附加其他惩罚措施。
实验仪器:
名称 |
型号 |
数量 |
PC |
MacBookAir |
1 |
一、实验内容
1、先运行教材上TCP代码,一人服务器,一人客户端
2、下载加解密代码,先编译运行代码,一人加密一人解密,适当修改代码
3、然后集成代码,一人加密后通过TCP发送
加密使用AES或DES,加密密钥Key的发送,使用服务器的公钥加密,公钥算法用RSA或DH,发送信息的完整性验证使用MD5或SHA3
4、使用实验楼Git服务托管代码
代码:
package client;
import java.net.*;
import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.spec.*;
import javax.crypto.interfaces.*;
import java.security.interfaces.*;
import java.math.*;
public class ComputeTCPClient {
public static void main(String srgs[]) throws Exception {
try {
//获取密钥生成器实例
KeyGenerator kg = KeyGenerator.getInstance("DESede");
//设置密钥长度
kg.init(168);
//生成对应的DESede密钥
SecretKey k = kg.generateKey();
//获取密钥的字节表示
byte[] ptext2 = k.getEncoded();
// String kstr=parseByte2HexStr(kb);
// 创建连接特定服务器的指定端口的Socket对象
Socket socket = new Socket("localhost", 12345);
// 获得从服务器端来的网络输入流
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
// 获得从客户端向服务器端输出数据的网络输出流
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
// 创建键盘输入流,以便客户端从键盘上输入信息
BufferedReader stdin = new BufferedReader(new InputStreamReader(
System.in));
FileInputStream f3 = new FileInputStream(new File("Skey_RSA_pub.dat"));
ObjectInputStream b2 = new ObjectInputStream(f3);
RSAPublicKey pbk = (RSAPublicKey) b2.readObject();
BigInteger e = pbk.getPublicExponent();
BigInteger n = pbk.getModulus();
BigInteger m = new BigInteger(ptext2);
BigInteger c = m.modPow(e, n);
// System.out.println("c= "+c);
String cs = c.toString();
out.println(cs); // 通过网络传送到服务器
System.out.print("请输入待发送的数据:");
String s = stdin.readLine(); // 从键盘读入待发送的数据
Cipher cp = Cipher.getInstance("DESede");
cp.init(Cipher.ENCRYPT_MODE, k);
byte ptext[] = s.getBytes("UTF8");
byte ctext[] = cp.doFinal(ptext);
String str = parseByte2HexStr(ctext);
out.println(str); // 通过网络传送到服务器
String x = s;
MessageDigest m2 = MessageDigest.getInstance("MD5");
m2.update(x.getBytes());
byte a[] = m2.digest();
String result = "";
for (int i = 0; i < a.length; i++) {
result += Integer.toHexString((0x000000ff & a[i]) |
0xffffff00).substring(6);
}
System.out.println(result);
out.println(result);
str = in.readLine();// 从网络输入流读取结果
System.out.println("从服务器接收到的结果为:" + str); // 输出服务器返回的结果
}
catch (Exception e) {
System.out.println(e);
}
finally {
// stdin.close();
// in.close();
// out.close();
// socket.close();
}
}
public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
}
package com.junru.server;
import java.net.*;
import java.io.*;
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.crypto.interfaces.*;
import java.security.interfaces.*;
import java.math.*;
public class ComputeTCPServer {
public static void main(String srgs[]) throws Exception {
ServerSocket sc = null;
Socket socket = null;
try {
sc = new ServerSocket(12345);// 创建服务器套接字
System.out.println("端口号:" + sc.getLocalPort());
System.out.println("服务器已经启动...");
socket = sc.accept(); // 等待客户端连接
System.out.println("已经建立连接");
// 获得网络输入流对象的引用
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
// //获得网络输出流对象的引用
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
// 解密模块,最后的keykb即明文;使用Dec_RSA代码
String aline2 = in.readLine();
BigInteger c = new BigInteger(aline2);
FileInputStream f = new FileInputStream(new File("Skey_RSA_priv.dat"));
ObjectInputStream b = new ObjectInputStream(f);
RSAPrivateKey prk = (RSAPrivateKey) b.readObject();
BigInteger d = prk.getPrivateExponent();
BigInteger n = prk.getModulus();
// System.out.println("d= "+d);
// System.out.println("n= "+n);
BigInteger m = c.modPow(d, n);
// System.out.println("m= "+m);
byte[] keykb = m.toByteArray();
// String aline3=new String(mt,"UTF8");
// String aline3=parseByte2HexStr(byte buf[]);
// 源自SDec代码,用于解密
String aline = in.readLine();// 读取客户端传送来的数据
// FileInputStream f2=new FileInputStream("keykb1.dat");
// int num2=f2.available();
// byte[] keykb=new byte[num2];
// f2.read(keykb);
byte[] ctext = parseHexStr2Byte(aline);
Key k = new SecretKeySpec(keykb, "DESede");
Cipher cp = Cipher.getInstance("DESede");
cp.init(Cipher.DECRYPT_MODE, k);
byte[] ptext = cp.doFinal(ctext);
String p = new String(ptext, "UTF8");
System.out.println("从客户端接收到信息为:" + p); // 通过网络输出流返回结果给客户端
String aline3 = in.readLine();
String x = p;
MessageDigest m2 = MessageDigest.getInstance("MD5");
m2.update(x.getBytes());
byte a[] = m2.digest();
String result = "";
for (int i = 0; i < a.length; i++) {
result += Integer.toHexString((0x000000ff & a[i]) |
0xffffff00).substring(6);
}
System.out.println(result);
// 输出结果
if (aline3.equals(result)) {
System.out.println("匹配成功");
}
out.println("匹配成功");
out.close();
in.close();
sc.close();
} catch (Exception e) {
System.out.println(e);
}
}
public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
}
二、总结
- 实验体会
本次实验是java的最后一次实验,这次实验将java和密码学结合在一起,让我更看出了学科之间的融会贯通。老师提供的代码块看起来比较容易,但是修改、调试,并使它运行起来还是有一定的难度。说明以后要加强代码设计的思维训练,不要只专注于一部分的代码块,并要多对程序进行优化,才能更好地掌握知识。
2.PSP时间
步骤 |
耗时 |
百分比 |
需求分析 |
36min |
20% |
设计 |
54min |
30% |
代码实现 |
36min |
20% |
测试 |
18min |
10% |
分析总结 |
36min |
20% |