zoukankan      html  css  js  c++  java
  • 20172319 实验五 《网络编程与安全》实验报告

    20172319 2018.06.13-20

    实验五《网络编程与安全》 实验报告

    课程名称:《程序设计与数据结构》  
    学生班级:1723班  
    学生姓名:唐才铭  
    学生学号:20172319 
    实验教师:王志强老师
    课程助教:刘伟康、张旭升学长
    实验时间:2018年6月13日——2018年6月20日
    必修/选修:必修
    

    目录


    实验内容

    1. 参考数据结构应用
      结对实现中缀表达式转后缀表达式的功能 MyBC.java
      结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java
      上传测试代码运行结果截图和码云链接;
    2. 结对编程:1人负责客户端,一人负责服务器
      注意责任归宿,要会通过测试证明自己没有问题
      基于Java Socket实现客户端/服务器功能,传输方式用TCP
      客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器
      服务器接收到后缀表达式,调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
      客户端显示服务器发送过来的结果
      上传测试代码运行结果截图和码云链接;
    3. 加密结对编程:1人负责客户端,一人负责服务器
      注意责任归宿,要会通过测试证明自己没有问题
      基于Java Socket实现客户端/服务器功能,传输方式用TCP
      客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
      服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
      客户端显示服务器发送过来的结果
      上传测试结果截图和码云链接;
    4. 密钥分发结对编程:1人负责客户端,一人负责服务器
      注意责任归宿,要会通过测试证明自己没有问题
      基于Java Socket实现客户端/服务器功能,传输方式用TCP
      客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文发送给服务器
      客户端和服务器用DH算法进行3DES或AES算法的密钥交换
      服务器接收到后缀表达式表达式后,进行解密,然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
      客户端显示服务器发送过来的结果
      上传测试结果截图和码云链接;
    5. 完整性校验结对编程:1人负责客户端,一人负责服务器
      注意责任归宿,要会通过测试证明自己没有问题
      基于Java Socket实现客户端/服务器功能,传输方式用TCP
      客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文和明文的MD5値发送给服务器
      客户端和服务器用DH算法进行3DES或AES算法的密钥交换
      服务器接收到后缀表达式表达式后,进行解密,解密后计算明文的MD5值,和客户端传来的MD5进行比较,一致则调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
      客户端显示服务器发送过来的结果
      上传测试结果截图和码云链接:

    返回目录


    实验要求

    1. 完成蓝墨云上与实验五《网络编程与安全》相关的活动,及时提交代码运行截图和码云Git链接,截图要有学号水印,否则会扣分。
    2. 完成实验、撰写实验报告,实验报告以博客方式发表在博客园,注意实验报告重点是运行结果,遇到的问题(工具查找,安装,使用,程序的编辑,调试,运行等)、解决办法(空洞的方法如“查网络”、“问同学”、“看书”等一律得0分)以及分析(从中可以得到什么启示,有什么收获,教训等)。报告可以参考范飞龙老师的指导
    3. 严禁抄袭,有该行为者实验成绩归零,并附加其他惩罚措施。
    4. 结对编程;也可自己在idea和虚拟机间进行传输;idea本身也可以进行服务器与客户端的传输。

    返回目录


    实验步骤

    1. 完成蓝墨云上实验五 网络编程与安全-1
    2. 完成蓝墨云上实验五 网络编程与安全-2
    3. 完成蓝墨云上实验五 网络编程与安全-3
    4. 完成蓝墨云上实验五 网络编程与安全-4
    5. 完成蓝墨云上实验五 网络编程与安全-5

    前期准备:

    1. 弄清自己的IP地址是什么:
      Linux下查找IP的命令:ifconfig -a

      Windows下查找IP的命令:ipconfig

      Windows下查找IP(笨方法):开始——设置——网络和Internet——WLAN——硬件属性

    需求分析:

    1. 需要在原Socket代码上加以理解并运用;
    2. 需要掌握、并会运用实验三java密码学所学的知识。

    返回目录


    代码实现及解释

    本次实验一共分为五个提交点:

    • 任务1:

    • 结对实现中缀表达式转后缀表达式的功能 MyBC.java;
      结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java

    • 分别运用四则运算时的中缀转后缀、后缀求值的方法即可:

    • MyBC.java;MyDC.java

    • 截图如下:

    • 任务2:

    • 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器
      服务器接收到后缀表达式,调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端。

    • 弄懂Socket的两个代码,将传输信息的内容换掉即可。

    • SocketClient_2.java;SocketServer_2.java

    • 对客户端代码的修改:

    String info1 = "12 15 8 100 25 34 19";
    

       变为

     //客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入中缀表达式");
            String info1 = scanner.nextLine();
            info1 = MyBC.infixToSuffix(info1);
    
    • 对服务器代码的修改:
     String info=null;
            if (!((info = bufferedReader.readLine()) ==null)){
                System.out.println("我是服务器,用户信息为:" + info);
            }
    
            //给客户一个响应
            //String reply=Output;
            String reply = "welcome";
            printWriter.write(reply);
    

       变为

     String info=null;
            if (!((info = bufferedReader.readLine()) ==null)){
                System.out.println("我是服务器,用户信息为:" + info);
            }
    
            //服务器接收到后缀表达式,调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
            String reply = MyDC.suffixToArithmetic(info);
    
            printWriter.write(reply);
    
    • 运行结果如下:

    • 任务3:

    • 让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
      服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端。

    • 运用java密码学里的3DES算法;先对文件SEnc.java(加密)和SDec.java(解密)进行修改,使其从void变为String方法,返回密、明文;在客户端与服务器分别对需要传输的信息运用加解密方法。

    • 客户端:

     //客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入中缀表达式");
            String info1 = scanner.nextLine();
            info1 = MyBC.infixToSuffix(info1);
    
            //把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
            try {
                info1 = SEnc.encrypt(info1);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            String info = new String(info1.getBytes("GBK"),"utf-8");
            //     printWriter.write(info);
            //     printWriter.flush();
            outputStreamWriter.write(info);
            outputStreamWriter.flush();
            socket.shutdownOutput();
    
    • 服务器:
     //4.读取用户输入信息
            String info=null;
            if (!((info = bufferedReader.readLine()) ==null)){
                System.out.println("我是服务器,用户信息为:" + info);
            }
    
            //接收到后缀表达式表达式后,进行解密
            try {
                info = SDec.decode(info);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            //调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
            String reply = MyDC.suffixToArithmetic(info);
    
            printWriter.write(reply);
            printWriter.flush();
    
    • 运行结果:

    • 任务4:

    • 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文发送给服务器
      客户端和服务器用DH算法进行3DES或AES算法的密钥交换
      服务器接收到后缀表达式表达式后,进行解密,然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端。

    • 修改java密码学中的Key_DH.java的代码,运行后分别生成客户端与服务器的公私钥;

    • Key_DH_Client.java;Key_DH_Server.java

    • 运行结果如图:

    • 对客户端的代码修改:

    //客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入中缀表达式");
            String info1 = scanner.nextLine();
            info1 = MyBC.infixToSuffix(info1);
    
            //把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
            try {
                info1 = SEnc.encrypt(info1);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            // 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
            try{
                // 读取对方的DH公钥
                FileInputStream f1=new FileInputStream("Bpub.dat");
                ObjectInputStream b1=new ObjectInputStream(f1);
                PublicKey  pbk=(PublicKey)b1.readObject( );
                //读取自己的DH私钥
                FileInputStream f2=new FileInputStream("Apri.dat");
                ObjectInputStream b2=new ObjectInputStream(f2);
                PrivateKey  prk=(PrivateKey)b2.readObject( );
                // 执行密钥协定
                KeyAgreement ka=KeyAgreement.getInstance("DH");
                ka.init(prk);
                ka.doPhase(pbk,true);
                System.out.println("
    " + "公钥为:");
                //生成共享信息
                byte[ ] sb=ka.generateSecret();
                for(int i=0;i<sb.length;i++){
                    System.out.print(sb[i]+",");
                }
                SecretKeySpec k=new  SecretKeySpec(sb,"DESede");
            } catch (Exception e) {
                e.printStackTrace();
            }
    
    
            String info = new String(info1.getBytes("GBK"),"utf-8");
    
    • 对服务器的代码修改:
    String info=null;
            if (!((info = bufferedReader.readLine()) ==null)){
                System.out.println("我是服务器,用户信息为:" + info);
            }
    
            //接收到后缀表达式表达式后,进行解密
            try {
                info = SDec.decode(info);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            // 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
            try{
                // 读取对方的DH公钥
                FileInputStream f1=new FileInputStream("Apub.dat");
                ObjectInputStream b1=new ObjectInputStream(f1);
                PublicKey pbk=(PublicKey)b1.readObject( );
                //读取自己的DH私钥
                FileInputStream f2=new FileInputStream("Bpri.dat");
                ObjectInputStream b2=new ObjectInputStream(f2);
                PrivateKey prk=(PrivateKey)b2.readObject( );
                // 执行密钥协定
                KeyAgreement ka=KeyAgreement.getInstance("DH");
                ka.init(prk);
                ka.doPhase(pbk,true);
                System.out.println("
    " + "公钥为:");
                //生成共享信息
                byte[ ] sb=ka.generateSecret();
                for(int i=0;i<sb.length;i++){
                    System.out.print(sb[i]+",");
                }
                SecretKeySpec k=new  SecretKeySpec(sb,"DESede");
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            //调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
            String reply = MyDC.suffixToArithmetic(info);
    
    • 运行结果截图:

    • 任务5:

    • 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文和明文的MD5値发送给服务器
      客户端和服务器用DH算法进行3DES或AES算法的密钥交换
      服务器接收到后缀表达式表达式后,进行解密,解密后计算明文的MD5值,和客户端传来的MD5进行比较,一致则调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端

    • 对客户端代码进行的修改:

           //客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式
            String a1,a2,a3,a4;
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入中缀表达式");
            String info1 = scanner.nextLine();
            info1 = MyBC.infixToSuffix(info1);  // 转后缀
            a1 = info1 + "###";
            String suffix = new String(a1.getBytes("GBK"),"utf-8");
            outputStreamWriter.write(suffix);
            outputStreamWriter.flush();
            String cleartext = "",ciphertext = "";
    
            //把后缀表达式用3DES或AES算法加密后通过网络把密文和明文的MD5値发送给服务器
            try {
                 cleartext = DigestPass.MD5(info1); // 明文MID5
                a2 = cleartext + "###";
                String info_cleartext = new String(a2.getBytes("GBK"),"utf-8");
                outputStreamWriter.write(info_cleartext);
                outputStreamWriter.flush();
                info1 = SEnc.encrypt(info1);  // 加密
                a3 = info1 + "###";
                String encrypt = new String(a3.getBytes("GBK"),"utf-8");
                outputStreamWriter.write(encrypt);
                outputStreamWriter.flush();
                 ciphertext = DigestPass.MD5(info1); // 密文MID5
    
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            // 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
            try{
                // 读取对方的DH公钥
                FileInputStream f1=new FileInputStream("Bpub.dat");
                ObjectInputStream b1=new ObjectInputStream(f1);
                PublicKey  pbk=(PublicKey)b1.readObject( );
                //读取自己的DH私钥
                FileInputStream f2=new FileInputStream("Apri.dat");
                ObjectInputStream b2=new ObjectInputStream(f2);
                PrivateKey  prk=(PrivateKey)b2.readObject( );
                // 执行密钥协定
                KeyAgreement ka=KeyAgreement.getInstance("DH");
                ka.init(prk);
                ka.doPhase(pbk,true);
                System.out.println("
    " + "公钥为:");
                //生成共享信息
                byte[ ] sb=ka.generateSecret();
                for(int i=0;i<sb.length;i++){
                    System.out.print(sb[i]+",");
                }
                SecretKeySpec k=new  SecretKeySpec(sb,"DESede");
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            String info_ciphertext = new String(ciphertext.getBytes("GBK"),"utf-8");
            //     printWriter.write(info);
            //     printWriter.flush();
    
            outputStreamWriter.write(info_ciphertext);
    
    • 对服务器代码进行的修改:
    //4.读取用户输入信息
            String info,info1,info2,info3,info4,info5 = null,reply = null;
            info = bufferedReader.readLine();
            System.out.println("我是服务器,用户信息为:" + info);
            String[] history = info.split("###");
            info1 = history[0];
                System.out.println("我是服务器,用户明文为:" + info1);
            info2 = history[1];
            System.out.println("我是服务器,用户明文MID5值为:" + info2);
            info3 = history[2];
            System.out.println("我是服务器,用户密文为:" + info3);
            info4 = history[3];
            System.out.println("我是服务器,用户密文MID5值为:" + info4);
    
            //接收到后缀表达式表达式后,进行解密并计算器MID5值
            try {
                info3 = SDec.decode(info3);
                info5 = DigestPass.MD5(info3);
                System.out.println("解密后求得的MID5:" + info5);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            // 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
            try{
                // 读取对方的DH公钥
                FileInputStream f1=new FileInputStream("Apub.dat");
                ObjectInputStream b1=new ObjectInputStream(f1);
                PublicKey pbk=(PublicKey)b1.readObject( );
                //读取自己的DH私钥
                FileInputStream f2=new FileInputStream("Bpri.dat");
                ObjectInputStream b2=new ObjectInputStream(f2);
                PrivateKey prk=(PrivateKey)b2.readObject( );
                // 执行密钥协定
                KeyAgreement ka=KeyAgreement.getInstance("DH");
                ka.init(prk);
                ka.doPhase(pbk,true);
                System.out.println("
    " + "公钥为:");
                //生成共享信息
                byte[ ] sb=ka.generateSecret();
                for(int i=0;i<sb.length;i++){
                    System.out.print(sb[i]+",");
                }
                SecretKeySpec k=new  SecretKeySpec(sb,"DESede");
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            //调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
            if (info2.equals(info5)) {
                 reply = MyDC.suffixToArithmetic(info1);
            }
            else {
                reply = "抱歉,二者的MID5值不一致!";
            }
            printWriter.write(reply);
    
    • 运行结果截图:

    返回目录


    测试过程及遇到的问题

    • 问题1:'ipconfig' 不是内部或外部命令,也不是可运行的程序或批处理文件。

    • 解决:起初为了试验能进行,采用了需求分析里的笨方法,后来发现是环境变量的问题,参考解决'不是内部或外部命令,也不是可运行的程序即可解决。

    • 问题2:我作为客户端,伙伴作为服务器可以正常传输,而交换则显示connect timed out

    • 解决:当时电脑出现关于IDEA的警告,我允许了其行为,但并没有真正关掉防火墙,所以导致链接超时;
      开始——设置——更新和安全——windows安全——防火墙和保护——关掉公共网络的防火墙即可

    • 问题3:DH算法进行传输时两边的密钥不对等

    • 解决:刚开始我对Key_DH里的方法做了修改:

    • 分别运用到服务器和客户端中,结果:


      很明显生成的公钥是不一样的,这明显不符合DH算法的原理;
      下面针对客户端与服务器的代码进行分析:

      可以明显看出执行到try之后,已经使用了Key_DH.java中的client方法生成关于客户端的公私钥,这里显然没什么问题,
      但要小心,此时服务器的公钥Bpub.dat是读不到的,因为还没有任何操作进行相应的生成,之后当数据传输给服务器时,
      其实客户端只读取了客户端自己的私钥,而传给服务器的,仅仅是用私钥进行运算后的;
      再看服务器:

      一样的道理,在向客户端传回数据前并没有读到客户端的公钥Apub.dat,因此等同客户端,只进行了私钥的运算就传输了,
      所以二者才不一样。
    • 最后,将原文件Key_DH.java扩展成两个文件,直接运行生成二者的公私钥,在服务器与客户端不再进行生成操作,而是直接读取。

    返回目录


    分析总结

    • 本次实验,内容基本相关连,每一个都是在前者的基础上进行扩充,虽然看似简单,但其实也不太容易;回顾了java密码学的相关知识,学会了几种算法的基本应用,还学会如何在不同机器间进行传输。

    返回目录


    代码链接

    返回目录


    参考资料

    Intellj IDEA 简易教程
    Android开发简易教程
    java 密码学

    返回目录

  • 相关阅读:
    CodeForces 156B Suspects(枚举)
    CodeForces 156A Message(暴力)
    CodeForces 157B Trace
    CodeForces 157A Game Outcome
    HDU 3578 Greedy Tino(双塔DP)
    POJ 2609 Ferry Loading(双塔DP)
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛十六进制转换成十进制
  • 原文地址:https://www.cnblogs.com/Tangcaiming/p/9200848.html
Copyright © 2011-2022 走看看