• 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 密码学

    返回目录

  • 相关阅读:
    [LeetCode] Best Time to Buy and Sell Stock III
    [LeetCode] Implement strStr()
    [LeetCode] Wildcard Matching
    [LeetCode] Gray Code
    [LeetCode] Divide Two Integers
    [LeetCode] Flatten Binary Tree to Linked List
    [LeetCode] Binary Tree Maximum Path Sum
    [TopCoder][SRM] SRM 562 DIV 2
    推荐博客文章
    检测两点所确定直线上的像素坐标
  • 原文地址:https://www.cnblogs.com/Tangcaiming/p/9200848.html
Copyright © 2020-2023  润新知