zoukankan      html  css  js  c++  java
  • 20165324 Java实验五 网络编程与安全

    20165324 Java实验五 网络编程与安全

    一、实验报告封面

    课程:Java程序设计 班级:1653班 姓名:何春江 学号:20165324

    指导教师:娄嘉鹏 实验日期:2018年5月28日

    实验时间:13:45 - 15:25 实验序号:24

    实验名称:网络编程与安全

    二、实验内容

    任务一:两人一组结对编程:

    1. 参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA
    2. 结对实现中缀表达式转后缀表达式的功能 MyBC.java
    3. 结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java
    4. 上传测试代码运行结果截图和码云链接

    实现中缀表达式转后缀表达式

    import java.util.Stack;
    import java.util.StringTokenizer;
    
    public class MyBC {
        /** constant for addition symbol */
        private final char ADD = '+';
        /** constant for subtraction symbol */
        private final char SUBTRACT = '-';
        /** constant for multiplication symbol */
        private final char MULTIPLY = '*';
        /** constant for division symbol */
        private final char DIVIDE = '/';
        /** the stack */
        Stack<Integer> stack=new Stack<Integer>();;
    
        String expression;
        public void setExpression(String str) {
            expression=str;
        }
        public  String changedWay() {
            String changedExpression = "";
            Stack signStack = new Stack();// 操作符栈
            for (int i = 0; i < expression.length(); i++) {
                char c = expression.charAt(i);
                if (c >= '0' && c <= '9') {
                    changedExpression=changedExpression+c;
                }
                else if (c == '+' || c == '-' || c == '*' || c == '/') {
                    changedExpression=changedExpression+" ";//分隔数字
                    if (signStack.empty()) {
                        signStack.push(c);
                    }
                    else if (judgeValue(c) >= judgeValue((Character) signStack.peek())) {//优先级高于或等于,运算符号均进栈
                        signStack.push(c);
                    }
                    else {
                        changedExpression=changedExpression+(char)signStack.pop();
                        signStack.push(c);
                    }
                }
                else if (c=='(') {
                    signStack.push(c);
                }
                else if (c==')') {
                    while((char)signStack.peek()!='(') {
                        changedExpression=changedExpression+" "+signStack.pop();
                    }
                    signStack.pop();
                }
            }
            while(!signStack.empty()){
                changedExpression=changedExpression+" "+String.valueOf(signStack.pop());
            }
            return changedExpression;
        }
    
        private static int judgeValue(char c) {
            int value = 0;
            switch (c) {
                case '(':
                    value = 1;
                    break;
                case '+':
                case '-':
                    value = 2;
                    break;
                case '*':
                case '/':
                    value = 3;
                    break;
                case ')':
                    value = 4;
                default:
                    value = 0;
            }
            return value;
        }
        public int evaluate (String expr)
        {//后缀表达式的运算方法
            int op1, op2, result = 0;
            String token;
            StringTokenizer tokenizer = new StringTokenizer (expr);//使用StringTokenizer类分解String对象的字符序列,默认为空格符...
            //此时tokenizer为一个分析器
            while (tokenizer.hasMoreTokens()) {
                token = tokenizer.nextToken();
                if (isOperator(token))
                {
                    op2 = (stack.pop()).intValue();//出栈
                    op1 = (stack.pop()).intValue();//出栈
                    result = evalSingleOp (token.charAt(0), op1, op2);//String对象第一个字符转换为char类型的方法为:str.charAt(0)
                    stack.push (new Integer(result));//进栈
                }
                else {
                    stack.push(new Integer(Integer.parseInt(token)));//进栈
                }
            }
            return result;
        }
        private boolean isOperator (String token)
        {
            return ( token.equals("+") || token.equals("-") ||
                    token.equals("*") || token.equals("/") );
        }
        private int evalSingleOp (char operation, int op1, int op2)
        {
            int result = 0;
            switch (operation)
            {
                case ADD:
                    result = op1 + op2;
                    break;
                case SUBTRACT:
                    result = op1 - op2;
                    break;
                case MULTIPLY:
                    result = op1 * op2;
                    break;
                case DIVIDE:
                    result = op1 / op2;
            }
            return result;
        }
    }
    
    

    参考资料:

    任务二:两人一组结对编程:

    1. 参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA
    2. 结对实现中缀表达式转后缀表达式的功能 MyBC.java
    3. 结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java
    4. 上传测试代码运行结果截图和码云链接
    • 获取本机IP地址:DESKTOP-HN1B8O2/172.30.2.248
    InetAddress address_3=InetAddress.getLocalHost();
    System.out.println(address_3.toString());
    
    • 结对伙伴的IP为:172.30.4.50 所选端口为:1111
    • 负责客服端的构建,实现代码为:
    • 选用AES加密算法
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.net.Socket;
    import java.util.*;
    
    public class Client_2Socket {
        public static void main(String[] args) {
            Socket Client_2Socket;
            DataInputStream Client_2in=null;
            DataOutputStream Client_2out=null;
            String expr,str;
            Scanner scanner=new Scanner(System.in);
            System.out.println("请输入表达式:");
            str=scanner.nextLine();
            MyBC mybc=new MyBC();
            mybc.setExpression(str);
            expr=mybc.changedWay();
            try {
                Client_2Socket=new Socket("172.30.2.248",5353);
                Client_2in=new DataInputStream(Client_2Socket.getInputStream());
                Client_2out=new DataOutputStream(Client_2Socket.getOutputStream());
                Client_2out.writeUTF(expr);
                String s=Client_2in.readUTF();
                System.out.println("服务器回复:
    "+s);
            }
            catch (Exception e) {
                System.out.println("服务器已断开"+e);
            }
        }
    }
    
    • 结对伙伴负责的服务器端代码为:
    import java.io.*;
    import java.net.*;
    import java.util.*;
    
    public class Server_2 {
        public static void main(String[] args) {
            ServerSocket Server_2forClient_2=null;
            Socket SocketOnServer_2=null;
            DataOutputStream Server_2out=null;
            DataInputStream Server_2in=null;
            try {
                Server_2forClient_2=new ServerSocket(5353);
            }
            catch (IOException e1) {
                System.out.println(e1);
                //e1.printStackTrace();
            }
            try {
                System.out.println("等待客户端呼叫……");
                SocketOnServer_2=Server_2forClient_2.accept();
                Server_2out=new DataOutputStream(SocketOnServer_2.getOutputStream());
                Server_2in=new DataInputStream(SocketOnServer_2.getInputStream());
                String expr=Server_2in.readUTF();
                System.out.println("服务器接收到表达式:"+expr);
                int result;
                MyBC mybc=new MyBC();
                result=mybc.evaluate(expr);
                Server_2out.writeUTF("后缀表达式:"+expr+",运算结果为:"+result);
                Thread.sleep(500);
            }
            catch (Exception e2) {
                System.out.println("客户端已断开"+e2);
            }
        }
    }
    
    
    • 实验截图

    任务三:加密结对编程:1人负责客户端,一人负责服务器

    1. 注意责任归宿,要会通过测试证明自己没有问题
    2. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
    3. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
    4. 服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
    5. 客户端显示服务器发送过来的结果
    6. 上传测试结果截图和码云链接
    • 思路:密文通过TCP传输,而AES密钥通过机密通道传输。
    • 负责客服端的构建,代码为:
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.net.Socket;
    import java.util.*;
    
    public class Client_3 {
        public static void main(String[] args) {
            Socket Client_2Socket;
            DataInputStream Client_2in=null;
            DataOutputStream Client_2out=null;
            String expr=null;
            String str=null;
            String Ciphertext=null;
            Scanner scanner=new Scanner(System.in);
            System.out.println("请输入表达式:");
            str=scanner.nextLine();
            MyBC mybc=new MyBC();
            mybc.setExpression(str);
            expr=mybc.changedWay();
            try {
                AES.produceAESKey();//生成AES密钥
                byte[]cc= AES.EncryptionAES(expr);//需要传输的密文,数组形式传输。
                Ciphertext = Base64.getEncoder().encodeToString(cc);//将加密后的密文由byte[]转换为String类型
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                Client_2Socket=new Socket("172.30.2.248",5300);
                Client_2in=new DataInputStream(Client_2Socket.getInputStream());
                Client_2out=new DataOutputStream(Client_2Socket.getOutputStream());
                Client_2out.writeUTF(Ciphertext);
                String s=Client_2in.readUTF();
                System.out.println("服务器回复:
    "+s);
            }
            catch (Exception e) {
                System.out.println("服务器已断开"+e);
            }
        }
    }
    
    
    • 结对伙伴负责构建服务器,代码为:
    import sun.security.krb5.internal.crypto.Aes128;
    
    import java.io.*;
    import java.net.*;
    import java.util.*;
    
    public class Server_3 {
        public static void main(String[] args) {
            ServerSocket Server_2forClient_2=null;
            Socket SocketOnServer_2=null;
            DataOutputStream Server_2out=null;
            DataInputStream Server_2in=null;
            try {
                Server_2forClient_2=new ServerSocket(5300);
            }
            catch (IOException e1) {
                System.out.println(e1);
            }
            try {
                System.out.println("等待客户端呼叫……");
                SocketOnServer_2=Server_2forClient_2.accept();
                Server_2out=new DataOutputStream(SocketOnServer_2.getOutputStream());
                Server_2in=new DataInputStream(SocketOnServer_2.getInputStream());
                String Ciphertext=Server_2in.readUTF();//密文
                byte[] data= Base64.getDecoder().decode(Ciphertext);
                String expr= AES.DecryptionAES(data);
                System.out.println("服务器接收到表达式:"+expr);
                int result;
                MyBC mybc=new MyBC();
                result=mybc.evaluate(expr);
                Server_2out.writeUTF("后缀表达式:"+expr+",运算结果为:"+result);
                Thread.sleep(500);
            }
            catch (Exception e2) {
                System.out.println("客户端已断开"+e2);
            }
        }
    }
    
    
    • 实验截图

    任务四:密钥分发结对编程:1人负责客户端,一人负责服务器

    1. 注意责任归宿,要会通过测试证明自己没有问题
    2. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
    3. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文发送给服务器
    4. 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
    5. 服务器接收到后缀表达式表达式后,进行解密,然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
    6. 客户端显示服务器发送过来的结果
    7. 上传测试结果截图和码云链接

    DH算法相关链接:

    • DH算法原理

    • 密钥交换算法DH(Java实现)

    • 密钥交换实现过程:

      1. 由消息发送的一方构建密钥,这里由甲方构建密钥。
      2. 由构建密钥的一方向对方公布其公钥,这里由甲方向乙方发布公钥。
      3. 由消息接收的一方通过对方公钥构建自身密钥,这里由乙方使用甲方公钥构建乙方密钥。
      4. 由消息接收的一方向对方公布其公钥,这里由乙方向甲方公布公钥。
    • 使用密钥协定创建共享密钥截图:

    • 使用创建的共享密钥就可以对AES的密钥进行加解密。因为生成的共享密钥为DESede密钥类型,则使用DESede加解密模式,密钥为共享密钥其余不变。即将共享密钥保存于文件Key_DESede_DH.dat中即可。

    • 实现关键代码:

            SecretKeySpec k=new  SecretKeySpec(sb,"DESede");
            FileOutputStream  f=new FileOutputStream("A_Key_DESede_DH.dat");//指定产生密钥输出流文件
            ObjectOutputStream b=new  ObjectOutputStream(f);//将对象序列化,以流的方式进行处理
            b.writeObject(k);//通过以对象序列化方式将密钥保存在文件中
            
    
    • 问题一:生成的共享密钥文件既然是DESede密钥类型,而DESede的长度密钥长度可以是112或168位。但生成的共享密钥的长度不为DESede规定的位数出现错误:java.security.InvalidKeyException: Invalid key length: 128 bytes
    • 问题一解决方法:使用AES密码机也不行..........产生同样的错误。

    任务五:完整性校验结对编程:1人负责客户端,一人负责服务器

    1. 注意责任归宿,要会通过测试证明自己没有问题
    2. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
    3. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文和明文的MD5値发送给服务器
    4. 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
    5. 服务器接收到后缀表达式表达式后,进行解密,解密后计算明文的MD5值,和客户端传来的MD5进行比较,一致则调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
    6. 客户端显示服务器发送过来的结果
    7. 上传测试结果截图和码云链接
    • 实验截图:

  • 相关阅读:
    【转】MFC中png格式图片贴图的实现
    【转】Windows 中不规则窗体的编程实现
    【转】MFC添加背景图片方法的三种方法
    【转】mfc win7获得管理员权限 使用WIN7风格 使用当前系统风格
    【转】双缓冲讲解及界面贴图
    【转】[内核/驱动]驱动中获取进程全路径和注册表全路径
    【转】Visual C++中DDB与DIB位图编程全攻略(转)
    【转】vs2010中添加splashScreen
    【转】一个在内存里搜索QQ号码的源码,源自看雪论坛
    输出JSON
  • 原文地址:https://www.cnblogs.com/20165324hcj/p/9093283.html
Copyright © 2011-2022 走看看