zoukankan      html  css  js  c++  java
  • 20135313_exp5

    课程: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("连接服务器成功!" + " ");
                return true;
            } catch (Exception e) {
                System.out.print("连接服务器失败!" + " ");
                return false;
            }
     
        }
     
        private void sendMessage() {
            if (cs == null)
                return;
            try {
                cs.sendMessage(sendMessage);
            } catch (Exception e) {
                System.out.print("发送消息失败!" + " ");
            }
        }
     
        private void getMessage() {
            if (cs == null)
                return;
            DataInputStream inputStream = null;
            try {
                inputStream = cs.getMessageStream();
            } catch (Exception e) {
                System.out.print("接收消息缓存错误 ");
                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 + " ");
                System.out.println("开始接收文件!" + " ");
                        
                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) + "% ");
                    fileOut.write(buf, 0, read);
                }
                System.out.println("接收完成,文件存为" + savePath + " ");
     
                fileOut.close();
            } catch (Exception e) {
                System.out.println("接收消息错误" + " ");
                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%

  • 相关阅读:
    Gmail、还有人需要吗?
    Google 打不开
    不能忽视的Doctype
    ASP.NET2.0中用ICallbackEventHandler实现客户端与服务器端异步交互
    DataGrid常用小技巧
    ASP.NET程序安全性(三) 表单提交、过滤用户输入
    Objection!!!
    编写3dmax插件需要注意的几个问题
    又一个IGame的bug
    VC2010中的C++0x特性 Part 1:Lambdas,auto, static_assert
  • 原文地址:https://www.cnblogs.com/paperfish/p/4575956.html
Copyright © 2011-2022 走看看