课程:Java程序与设计     班级:1353  姓 名:吴子怡   学号:20135313

小组成员: 20135113肖昱

成绩:             指导教师:娄嘉鹏       实验日期:2015.6.9

实验密级:          预习程度:         实验时间:15:30-18:00

仪器组次:          必修/选修:选修        实验序号:5

实验名称:Java网络编程及安全

实验目的与要求:结对编程,实现客户端和服务器之间数据的发送与接收,实现加解密和验证Hash函数值。

实验仪器:

名称

型号

数量

PC

DELL

1

Eclipse

1

 

一、实验内容

1.用TCP代码,实现服务器与客户端。

2.客户端与服务器连接

3.客户端中输入明文,利用DES算法加密,DES的秘钥用RSA公钥密码中服务器的公钥加密.

4.客户端用RSA公钥密码中服务器的私钥解密DES的,秘钥,用秘钥对密文进行解密,得出明文。

二.实验过程。

1.客户端 与服务器的连接。

服务器代码:

 
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.ServerSocket;
import java.net.Socket;
 
import java.security.SecureRandom;
 
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
public class ServerTest {
    int port = 8821;
 
    void start() {
        Socket s = null;
        try {
            ServerSocket ss = new ServerSocket(port);   //创建一个ServerSocket套接字对象,并绑定在8821端口上
            while (true) {
                // 选择进行传输的文件
                String filePath = "C:\\Users\\wzy\\Desktop\\服务器\\jiami.txt";
                File fi = new File(filePath);  //通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例
                System.out.println("文件长度:" + (int) fi.length());
 
                s = ss.accept();
                System.out.println("建立socket链接");
                DataInputStream dis = new DataInputStream(new BufferedInputStream(s.getInputStream()));   //DataInputStream:使用指定的底层 InputStream 创建一个 DataInputStream;
                dis.readByte();  //返回此输入流的下一个字节,以有符号 8 位 byte 的形式表示。
 
                DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
                DataOutputStream ps = new DataOutputStream(s.getOutputStream());//创建一个新的数据输出流,将数据写入指定基础输出流
 
 
                ps.writeUTF(fi.getName());
                ps.flush();
                ps.writeLong((long) fi.length());
                ps.flush();
 
                int bufferSize = 8192; //缓冲区,1k
                byte[] buf = new byte[bufferSize];
 
                while (true) {
                    int read = 0;
                    if (fis != null) {
                        read = fis.read(buf);
                    }
 
                    if (read == -1) {
                        break;
                    }
                    ps.write(buf, 0, read);
                }
                ps.flush();// 直到socket超时,导致数据不完整。                
                fis.close();
                s.close();                
                System.out.println("文件传输完成");
            }
 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    public static void main(String arg[]) {
        new ServerTest().start();
    }
}

客户端Socket代码:

import java.net.*;
import java.io.*;
 
public class ClientSocket {
    private String ip;
 
    private int port;
 
    private Socket socket = null;
 
    DataOutputStream out = null;
 
    DataInputStream getMessageStream = null;
 
    public ClientSocket(String ip, int port) {
        this.ip = ip;
        this.port = port;
    }
 
    /** *//**
     * 创建socket连接
     * 
     * @throws Exception
     *             exception
     */
    public void CreateConnection() throws Exception {
        try {
            socket = new Socket(ip, port);
        } catch (Exception e) {
            e.printStackTrace();
            if (socket != null)
                socket.close();
            throw e;
        } finally {
        }
    }
 
    public void sendMessage(String sendMessage) throws Exception {
        try {
            out = new DataOutputStream(socket.getOutputStream());
            if (sendMessage.equals("Windows")) {
                out.writeByte(0x1);
                out.flush();
                return;
            }
            if (sendMessage.equals("Unix")) {
                out.writeByte(0x2);
                out.flush();
                return;
            }
            if (sendMessage.equals("Linux")) {
                out.writeByte(0x3);
                out.flush();
            } else {
                out.writeUTF(sendMessage);
                out.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (out != null)
                out.close();
            throw e;
        } finally {
        }
    }
 
    public DataInputStream getMessageStream() throws Exception {
        try {
            getMessageStream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
            return getMessageStream;
        } catch (Exception e) {
            e.printStackTrace();
            if (getMessageStream != null)
                getMessageStream.close();
            throw e;
        } finally {
        }
    }
 
    public void shutDownConnection() {
        try {
            if (out != null)
                out.close();
            if (getMessageStream != null)
                getMessageStream.close();
            if (socket != null)
                socket.close();
        } catch (Exception e) {
 
        }
    }
}

客户端Test代码:

 
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
 
public class ClientTest {
    private ClientSocket cs = null;
 
    private String ip = "192.168.253.1";// 设置成服务器IP
 
    private int port = 8821;
 
    private String sendMessage = "Windwos";
 
    public ClientTest() {
        try {
            if (createConnection()) {
                sendMessage();
                getMessage();
            }
 
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
 
    private boolean createConnection() {
        cs = new ClientSocket(ip, port);
        try {
            cs.CreateConnection();
            System.out.print("连接服务器成功!" + "\n");
            return true;
        } catch (Exception e) {
            System.out.print("连接服务器失败!" + "\n");
            return false;
        }
 
    }
 
    private void sendMessage() {
        if (cs == null)
            return;
        try {
            cs.sendMessage(sendMessage);
        } catch (Exception e) {
            System.out.print("发送消息失败!" + "\n");
        }
    }
 
    private void getMessage() {
        if (cs == null)
            return;
        DataInputStream inputStream = null;
        try {
            inputStream = cs.getMessageStream();
        } catch (Exception e) {
            System.out.print("接收消息缓存错误\n");
            return;
        }
 
        try {
            //本地保存路径,文件名会自动从服务器端继承而来。
            String savePath = "E:\\客户端\\";
            int bufferSize = 8192;
            byte[] buf = new byte[bufferSize];
            int passedlen = 0;
            long len=0;
            
            savePath += inputStream.readUTF();
            DataOutputStream fileOut = new DataOutputStream(new BufferedOutputStream(new BufferedOutputStream(new FileOutputStream(savePath))));
            len = inputStream.readLong();
            
            System.out.println("文件的长度为:" + len + "\n");
            System.out.println("开始接收文件!" + "\n");
                    
            while (true) {
                int read = 0;
                if (inputStream != null) {
                    read = inputStream.read(buf);
                }
                passedlen += read;
                if (read == -1) {
                    break;
                }
                //下面进度条本为图形界面的prograssBar做的,这里如果是打文件,可能会重复打印出一些相同的百分比
                System.out.println("文件接收了" +  (passedlen * 100/ len) + "%\n");
                fileOut.write(buf, 0, read);
            }
            System.out.println("接收完成,文件存为" + savePath + "\n");
 
            fileOut.close();
        } catch (Exception e) {
            System.out.println("接收消息错误" + "\n");
            return;
        }
    }
 
    public static void main(String arg[]) {
        new ClientTest();
    }
}

在这只做简单代码展示,具体传输文件见下述步骤。

2.用DES加密明文,并传输给服务器密文。

DES加密代码:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.SecureRandom;
 
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
 
public class DESJiaMi {
    public static void main(String[] args) throws Exception {
 
        // DES算法要求有一个可信任的随机数源
        SecureRandom sr = new SecureRandom();
        // 获得密匙数据
        FileInputStream fi = new FileInputStream(new File("key.txt"));
        byte rawKeyData[] = new byte[fi.available()];
        fi.read(rawKeyData);
        fi.close();
        // 从原始密匙数据创建DESKeySpec对象
        DESKeySpec dks = new DESKeySpec(rawKeyData);
        // 创建一个密匙工厂,然后用它把DESKeySpec转换成一个SecretKey对象
        SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(dks);
        // Cipher对象实际完成加密操作
        Cipher cipher = Cipher.getInstance("DES");
        // 用密匙初始化Cipher对象
        cipher.init(Cipher.ENCRYPT_MODE, key, sr);
        // 现在,获取要加密的文件数据
        FileInputStream fi2 = new FileInputStream(new File("lib.txt"));
        byte data[] = new byte[fi2.available()];
        fi2.read(data);
        fi2.close();
        // 正式执行加密操作
        byte encryptedData[] = cipher.doFinal(data);
        // 用加密后的数据文件
        FileOutputStream fo = new FileOutputStream(new File("jiami.txt"));
        fo.write(encryptedData);
        fo.close();
new ServerTest().start();
    }
}

DES解密代码:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.SecureRandom;
 
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
 
public class DESJieMi {
    public static void main(String[] args) throws Exception {
new ClientTest();
 
        // DES算法要求有一个可信任的随机数源
        SecureRandom sr = new SecureRandom();
        // 获得密匙数据
        FileInputStream fi = new FileInputStream(new File("key.txt"));
        byte rawKeyData[] = new byte[fi.available()];// = new byte[5];
        fi.read(rawKeyData);
        fi.close();
        // 从原始密匙数据创建一个DESKeySpec对象
        DESKeySpec dks = new DESKeySpec(rawKeyData);
        // 创建一个密匙工厂,然后用它把DESKeySpec对象转换成一个 SecretKey对象
        SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(dks);
        // Cipher对象实际完成解密操作
        Cipher cipher = Cipher.getInstance("DES");
        // 用密匙初始化Cipher对象
        cipher.init(Cipher.DECRYPT_MODE, key, sr);
        // 现在,获取数据并解密
        FileInputStream fi2 = new FileInputStream(new File("jiami.txt"));
        byte encryptedData[] = new byte[fi2.available()];
        fi2.read(encryptedData);
        fi2.close();
        // 正式执行解密操作
        byte decryptedData[] = cipher.doFinal(encryptedData);
        // 这时把数据还原成原有的类文件
        FileOutputStream fo = new FileOutputStream(new File("jiemi.txt"));
        fo.write(decryptedData);
 
    }
}
密钥 key.txt 

lib.txt表示明文

通过服务器与客户端相连,服务器将加密后的文件jiami.txt传输给客户端待用。

加密后的密文 jiami.txt

3.RSA加密密钥,传输,RSA解密获得密钥。

服务器使用已给出的代码加密密钥。原理相近,不作截图展示。

代码为老师上课在Java学习群中给出的代码包,也不作截图展示。

将所加密内容发给客户端。并进行解密,得到客户端解密后的密钥。

4.用密钥解密密文。

解密代码所生成的jiemi.txt。

【实验体会】

本次实验中大部分代码都是老师既定给好的,而我们的主要任务是对要实现的传输、加解密、连接等进行处理衔接,让我们从编程一跃提升到有目的性的实战。这次实验主要分为三个部分,一是多线程客户端和服务器的连接,而是RSA公钥加密,三是DES加密。我认为,这些内容都是要跨科目实现的,不管是密码学还是计网,都在这过程中起着很大的作用。然而,实验中也遇到不少问题,也较为琐碎。和搭档讨论后,对方给了我很多指导,也逐渐能够看到实验结果离我越来越近。以后还是需要更多地寻找实验操作,多和在Java方面学习更深入的同学探讨来提升自己的能力。

步骤

耗时

百分比

需求分析

30m

30%

设计

10m

10%

代码实现

10m

10%

测试

40m

40%

分析总结

10m

10%

20135313_exp5的更多相关文章

随机推荐

  1. TopJUI Combobox 联动

    这里给联动进行一个简单定义:因Combobox选择或输入的值发生改变时对自身或者其它组件产生影响称为联动.(注:editable确定是否可以手动输入) 有两种实现方法: 一.自己写对应的onChang ...

  2. 【五】安装fcig

    安装fcig 安装fcig 此步骤是为了让spawn-fcgi能够识别自定义的demo 编译文件 自定义c文件 测试成功后,启动spawn cgi进行代理托管 此步骤是为了让spawn-fcgi能够识 ...

  3. python学习笔记:第9天 函数初步

    1. 函数的定义及调用 函数:所谓的函数可以看作是对一段代码的封装,也是对一个功能模块的封装,这样方便在下次想用这个功能的时候直接调用这个功能模块,而不用重新去写. 函数的定义:我们使用def关键字来 ...

  4. Linux--ps及top、ls命令

    day8  ps系统管理命令 ps是强大的后台进程检测命令 格式:ps [options] [--help] 选项参数: 1.-a :显示所有进程,包括PID等,包括其他用户运行的程序 2.-ef:显 ...

  5. 【Hutool】Hutool工具类之日期时间工具——DateUtil

    一.用于取代Date对象的DateTime对象 再也不用Date SimpleDateFormat Calendar之间倒腾来倒腾去了!日期创建-获取-操作一步到位! 如果JDK版本更新到了8及以上, ...

  6. 20155211 《Java程序设计》实验一(Java开发环境的熟悉)实验报告

    20155211 <Java程序设计>实验一(Java开发环境的熟悉)实验报告 一.实验内容及步骤 (一)使用JDK编译.运行简单的java程序 命令行下的程序开发 步骤一(新建文件夹): ...

  7. C语言复习20170805

    循环控制结构 重复处理次数时已知的循环称为计数控制的循环,若重复处理次数为未知,是由给定情况控制的,称为条件控制的循环. C语言提供for.while.do while三种循环语句实现循环结构. 循环 ...

  8. 20155325 2016-2017-2 《Java程序设计》第九周学习总结

    教材学习内容总结 SRP高内聚 开发工作原则:对扩充开发,对修改封闭.(对模块的行为可以扩充:模块的源代码不可更改) OO设计 依赖倒置原则:高层模块不依赖于 Linux视频笔记 安装时的说明(非ub ...

  9. Drupal views中实现两列布局

    Views中的format有table,grid,unformatted list等,但是没有2 columns等选项. 如果要达到如下效果: 左侧一列有title,content,右侧一列image ...

  10. 八月暑期福利,10本Python热门书籍免费送!

    八月第一周,网易云社区联合博文视点为大家带来Python专场送书福利,10本关于Python的书籍内容涉及Python入门.绝技.开发.数据分析.深度学习.量化投资等.以下为书籍简介,送书福利请见文末 ...