课程: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. 执行 sql 报错未缓冲查询,错误码 2014

    sql语句为 SELECT COUNT(id) AS tp_count FROM `tableName` WHERE `status` = 0 AND `source` = 1 AND ( `end_ ...

  2. php以数组做为配置文件的读取和写入操作

    最近想用php开发个简单的文章管理系统,主要是做一批垃圾采集站,目前网上的cms都太多功能了,导致修改个模板要很多文件,花费很多功夫.开始用thinkphp框架做,感觉还是麻烦,后来改用ci,做好了后 ...

  3. vue相关理论知识

    es6常用语法简介 es是js的规范标准 let 特点: 1.有全局和函数作用域,以及块级作用域(用{}表示块级作用域范围) 2.不会存在变量提升 3.变量不能重复声明 const 特点: 1.有块级 ...

  4. (数据科学学习手札47)基于Python的网络数据采集实战(2)

    一.简介 马上大四了,最近在暑期实习,在数据挖掘的主业之外,也帮助同事做了很多网络数据采集的内容,接下来的数篇文章就将一一罗列出来,来续写几个月前开的这个网络数据采集实战的坑. 二.马蜂窝评论数据采集 ...

  5. 20155233 2016-2017-2 《Java程序设计》第1周学习总结

    20155233 2016-2017-2 <Java程序设计>第1周学习总结 教材学习内容总结 本周主要学习教材的第一章.第二章,了解了Java的发展历程,最基本的Java环境的搭建,以及 ...

  6. 2017-2018-1 20155320《信息安全技术》实验二——Windows口令破解

    2017-2018-1 20155320<信息安全技术>实验二--Windows口令破解 实验目的 了解Windows口令破解原理 对信息安全有直观感性认识 能够运用工具实现口令破解 实验 ...

  7. 20155328 2016-2017-2 《Java程序设计》第四周学习总结

    学号 2016-2017-2 <Java程序设计>第四周学习总结 教材学习内容总结 继承:避免多各类间重复定义行为,extends关键字表示继承后再扩充原本没有的行为.如果没有使用exte ...

  8. 20155329胡佩伦《Java程序设计》第2周学习总结

    学号 20155329 <Java程序设计>第2周学习总结 教材学习内容总结 基本类型 整数(short.int.long) 字节(byte) 浮点数(float/double) 字符(c ...

  9. !important用法:

    如果不加important特性,则超链接的颜色为蓝色,但是加上important之后优先级提高了,显示颜色为绿色 <style type="text/css"> a{ ...

  10. 人脸识别引擎SeetaFaceEngine中Alignment模块使用的测试代码

    人脸识别引擎SeetaFaceEngine中Alignment模块用于检测人脸关键点,包括5个点,两个眼的中心.鼻尖.两个嘴角,以下是测试代码: int test_alignment() { std: ...