一、实验内容

1.运行教材上TCP代码,结对进行,一人服务器,一人客户端;

2.利用加解密代码包,编译运行代码,一人加密,一人解密;

3.集成代码,一人加密后通过TCP发送;

注:加密使用AES或者DES/AES或者DES加密密钥key并发送,使用服务器的公钥加密/公钥算法使用RSA或DH/检验发送信息的完整性使用MD5或者SHA3;

4.完成Blog。

二、实验步骤

1.综述

本次实验的实验内容较少,但是准备工作非常多;在此次实验中,本小组仍然采用“编学习,边实验”的方法,虽然过程较曲折,但最后结果很成功。

2.学习TCP

根据课本如下程序,体会TCP含义。

服务器端:

package chapter9;

import java.io.*;

import java.net.ServerSocket;

import java.net.Socket;

public class ServerTest

{

public static final int PORT = 8081;

public static void main(String[] args) throws IOException

{

ServerSocket s = new ServerSocket(PORT);

System.out.println("Started:"+s);

try

{

Socket socket = s.accept();

try

{

System.out.println("Connection accepted:"+socket);

BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);

while(true)

{

String str=in.readLine();

if(str.equals("END"))

break;

System.out.print("Echoing:"+str);

out.println(str);

}

}

finally

{

System.out.println("closing...");

socket.close();

}

}

finally

{

s.close();

}

}

}

图1 服务器端开始运行

客户端:

package chapter9;

import java.io.*;

import java.net.InetAddress;

import java.net.Socket;;

public class ClientTest

{

public static void main(String[] args) throws IOException

{

InetAddress addr = InetAddress.getByName("192.168.1.35");

System.out.println("addr ="+addr);

Socket socket = new Socket(addr,ServerTest.PORT);

try

{

System.out.println("socket="+socket);

BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);

for(int i =0;i<0;i++)

{

out.println("howdy"+i);

String str = in.readLine();

System.out.println(str);

}

out.println("END");

}

finally

{

System.out.println("closing...");

socket.close();

}

}

}

图2 客户端运行

资料补充:

Java网络编程的一般步骤

(1)客户端(Client)

客户端是指网络编程中首先发起连接的程序,客户端一般实现程序界面和基本逻辑实现,在进行实际的客户端编程时,客户端的编程主要由三个步骤实现:

① 建立网络连接:连接时需要指定连接到的服务器的IP地址和端口号,建立完成以后,会形成一条虚拟的连接,后续的操作就可以通过该连接实现数据交换了。

②交换数据:连接建立以后,就可以通过这个连接交换数据了。交换数据严格按照请求响应模型进行,由客户端发送一个请求数据到服务器,服务器反馈一个响应数据给客户端,如果客户端不发送请求则服务器端就不响应。根据逻辑需要,可以多次交换数据,但是还是必须遵循请求响应模型。

③关闭网络连接:在数据交换完成以后,关闭网络连接,释放程序占用的端口、内存等系统资源,结束网络编程。

(2)服务器端(Server)

服务器端(Server)是指在网络编程中被动等待连接的程序,服务器端一般实现程序的核心逻辑以及数据存储等核心功能。服务器端的编程步骤和客户端不同,是由四个步骤实现,依次是:

①监听端口: 服务器端属于被动等待连接,所以服务器端启动以后,不需要发起连接,而只需要监听本地计算机的某个固定端口即可。这个端口就是服务器端开放给客户端的端口,服务器端程序运行的本地计算机的IP地址就是服务器端程序的IP地址。

②获得连接:当客户端连接到服务器端时,服务器端就可以获得一个连接,这个连接包含客户端的信息,例如客户端IP地址等等,服务器端和客户端也通过该连接进行数据交换。一般在服务器端编程中,当获得连接时,需要开启专门的线程处理该连接,每个连接都由独立的线程实现。

③交换数据:服务器端通过获得的连接进行数据交换。服务器端的数据交换步骤是首先接收客户端发送过来的数据,然后进行逻辑处理,再把处理以后的结果数据发送给客户端。简单来说,就是先接收再发送,这个和客户端的数据交换数序不同。其实,服务器端获得的连接和客户端连接是一样的,只是数据交换的步骤不同。当然,服务器端的数据交换也是可以多次进行的。

④关闭连接:当服务器程序关闭时,需要关闭服务器端,通过关闭服务器端使得服务器监听的端口以及占用的内存可以释放出来,实现了连接的关闭。

经过以上学习,我们初步掌握了服务器代码与客户端代码特点、运行方式,为进一步开展代码整合打下基础。

在编译客户端时,eclipse显示此处有错误:InetAddress addr = InetAddress.getByName(192.168.1.35);经检查,是没有合法输入,将IP地址用引号表示,程序可以正常运行。

3.运行加解密包中的程序

1.运行DES加密代码

import java.io.*;

import javax.crypto.*;

public class Skey_DES{

public static void main(String args[]) throws Exception{

KeyGenerator kg=KeyGenerator.getInstance("DESede");

kg.init(168);

SecretKey k=kg.generateKey( );

FileOutputStream  f=new FileOutputStream("key1.dat");

ObjectOutputStream b=new  ObjectOutputStream(f);

b.writeObject(k);

}

}

import java.io.*;

import java.security.*;

public class Skey_kb{

public static void main(String args[]) throws Exception{

FileInputStream f=new FileInputStream("key1.dat");

ObjectInputStream b=new ObjectInputStream(f);

Key k=(Key)b.readObject( );

byte[ ] kb=k.getEncoded( );

FileOutputStream  f2=new FileOutputStream("keykb1.dat");

f2.write(kb);

// 打印密钥编码中的内容

for(int i=0;i<kb.length;i++){

System.out.print(kb[i]+",");

}

}

}

图3 DES代码运行结果

原理解释:

(1)throws Exception {}//表示该方法可能产生异常,并使用throws声明异常,//则该方法产生异常也不必捕获

(2)例如想用“abcd”作为密钥利用DES进行加密和解密:

String keyString=”abcd”;

byte[]keyData=keyString.getBytes();

secretKey myDeskey=new SecretKeySpec(keyData,”DES”);

(3) 获取密钥生成器

KeyGenerator kg=KeyGenerator.getInstance("DESede");

Java中KeyGenerator类中提供了创建对称密钥的方法。Java中的类一般使用new操作符通过构造器创建对象,但KeyGenerator类不是这样,它预定义了一个静态方法getInstance(),通过它获得KeyGenerator类型的对象。这种类成为工厂类或工厂。

方法getInstance( )的参数为字符串类型,指定加密算法的名称。可以是 “Blowfish”、“DES”、“DESede”、“HmacMD5”或“HmacSHA1”等。这些算法都可以实现加密,这里我们不关心这些算法的细节,只要知道其使用上的特点即可。

(4)初始化密钥生成器

kg.init(168);

该步骤一般指定密钥的长度。如果该步骤省略的话,会根据算法自动使用默认的密钥长度。指定长度时,若第一步密钥生成器使用的是“DES”算法,则密钥长度必须是56位;若是“DESede”,则可以是112或168位,其中112位有效;若是“AES”,可以是128, 192或256位。

(5)生成密钥SecretKey k=kg.generateKey( );

使用第一步获得的KeyGenerator类型的对象中generateKey( )方法可以获得密钥。其类型为SecretKey类型,可用于以后的加密和解密。

(6)通过对象序列化方式将密钥保存在文件中

FileOutputStream  f=new FileOutputStream("key1.dat");

ObjectOutputStream b=new  ObjectOutputStream(f); b.writeObject(k);

ObjectOutputStream类中提供的writeObject方法可以将对象序列化,以流的方式进行处理。这里将文件输出流作为参数传递给ObjectOutputStream类的构造器,这样创建好的密钥将保存在文件key1.data中。

4.整合代码

本次实验中,我们小组成员尝试的方法是先在个人PC上开辟两个窗口作为客户端client和服务器server,模拟TCP传输;再连网进行TCP传输。

服务器代码

// file name:ComputeTCPServer.java

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(4421);//创建服务器套接字

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("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 aline2=in.readLine();

BigInteger c=new BigInteger(aline2);

FileInputStream f=new FileInputStream("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[] mt=m.toByteArray();

//String aline3=new String(mt,"UTF8");*/

//代码源自DigestCalc,用于检验信息完整性

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;

}

}

代码解释:代码分为如下部分:启动端口等待连接——已经连接后,若客户端请求,则发送公钥——接受客户端传来的信息(明文)并译码显示——检查状态,是否匹配成功——加密并显示

整合程序过程如下:

图4 server端等候时间过长

图5 Client端连接超时

图6 服务器正常响应

图7 客户端正常响应

图8 服务器正常响应2

图9 客户端正常响应2

图10 当前IP地址

图11 两台PC机上进行传送

注:20135211 cnblog地址:http://www.cnblogs.com/shadow135211/

Java实验五报告——TCP传输及加解密的更多相关文章

  1. 实验五 TCP传输及加解密

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计                         班级:1353            姓名:陈巧然     ...

  2. 第七周学习总结&JAVA实验五报告。

    JAVA实验报告五: 实验四 类的继承 实验目的 理解抽象类与接口的使用: 了解包的作用,掌握包的设计方法. 实验要求 掌握使用抽象类的方法. 掌握使用系统接口的技术和创建自定义接口的方法. 了解 J ...

  3. java实验五20135104

    课程:Java程序设计                   班级:1351            姓名:刘帅      学号:20135104 成绩:             指导教师:娄嘉鹏     ...

  4. java实验五实验报告

    一.实验内容 Cmp传输与加解密 结对编程,一人服务器,一人客户端,服务器向客户端发送经RSA加密的密钥和用密钥加密的密文(使用DES算法),客户端负责接收加密后的密钥和密文,并解密得出明文. 二.实 ...

  5. 20165324 Java实验五 网络编程与安全

    20165324 Java实验五 网络编程与安全 一.实验报告封面 课程:Java程序设计 班级:1653班 姓名:何春江 学号:20165324 指导教师:娄嘉鹏 实验日期:2018年5月28日 实 ...

  6. 2018-2019-2-20175323 java实验五 网络编程与安全

    20175323 java实验五 网络编程与安全 任务一 ①编写MyBC.java实现中缀表达式转后缀表达式的功能 ②编写MyDC.java实现从上面功能中获取的表达式中实现后缀表达式求值的功能 基本 ...

  7. 20165310 Java实验五《网络编程与安全》

    20165310 Java实验五<网络编程与安全> 任务一 题目:①编写MyBC.java实现中缀表达式转后缀表达式的功能:②编写MyDC.java实现从上面功能中获取的表达式中实现后缀表 ...

  8. Java实验五

    20145113 Java实验五 网络编程及安全 实验内容 对于客户端与服务器端:修改原代码,使其可以实现连续的传消息,并且传送文件. 对于加解密部分: 对于原先的加密只加密"hello w ...

  9. 20145302张薇《Java程序设计》实验五报告

    20145302张薇 实验五:Java网络编程及安全 实验内容 掌握Socket程序的编写: 掌握密码技术的使用: 设计安全传输系统. 实验要求 基于Java Socket实现安全传输 基于TCP实现 ...

随机推荐

  1. ural 1153. Supercomputer

    1153. Supercomputer Time limit: 2.0 secondMemory limit: 64 MB To check the speed of JCN Corporation ...

  2. RETINA显示屏下ICON优化方法

    便于理解,先来了解几个名词: dpi(dots per inch),每英寸的点数,用来测量任何设备的硬件分辨率.一个21”的屏幕可以拥有1680 X 1050 的分辨率,27”的屏幕也可以拥有相同的分 ...

  3. BestCoder Round #72

    由于第一次打,只能在div2打.(这么好的机会还没AK真是丢人) T1 Clarke and chemistry 枚举题不解释(我不会告诉你我上来WA了四发的) T2 Clarke and point ...

  4. BZOJ3513: [MUTC2013]idiots

    Description 给定n个长度分别为a_i的木棒,问随机选择3个木棒能够拼成三角形的概率. Input 第一行T(T<=100),表示数据组数.接下来若干行描述T组数据,每组数据第一行是n ...

  5. Java实现FTP上传下载功能

    Java FTP客户端工具包很多,在此我选用的Apache的FTPClient.这个包的获取可以通过http://commons.apache.org/net/来获取,我使用的是最新的commons- ...

  6. 1.Java为什么能跨平台运行?请简述原理。

    使用不同操作系统的JVM(JAVA虚拟机)解释运行编译好的字节码文件(.class)

  7. Json 数据

    来自:极课学院 简介: json与xml json语法 json对象 json对象数组 用到的包 读取json数据例子 创建json数据

  8. angJs使选中的li背景颜色不同

    <!doctype html><html><head><meta charset="UTF-8"><title>test ...

  9. pox目录中的交换机mac地址学习模块 l2_multi源码

    # Copyright 2012-2013 James McCauley # # Licensed under the Apache License, Version 2.0 (the "L ...

  10. ThinkPHP 3.2.2 实现持久登录 ( 记住我 )

    实现持久登录,即用户在登录时,勾选了"记住我"之后,无论是否关闭浏览器,只要不退出登录,在指定的时间内始终保持登录状态(缺点是在另一台电脑上登录过后,之前那台电脑就不能继续保持登录 ...