代码改变世界

20165321 实验五 网络编程与安全

2018-06-03 10:50  Ze6Pui3Loeng4  阅读(239)  评论(1编辑  收藏  举报

任务1

任务详情

两人一组结对编程:
0. 参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA

  1. 结对实现中缀表达式转后缀表达式的功能 MyBC.java
  2. 结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java
  3. 上传测试代码运行结果截图和码云链接

代码

由于myDC.java与myBC.java都不是主类,没有办法运行,所以只有上代码了。

myDC.java

import java.util.*;

public class MyDC {
    /** 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 */
    private Stack<Integer> stack;

    public MyDC() {
        stack = new Stack<Integer>();
    }

    public int evaluate (String expr) {//expr是算数表达式
        int op1, op2, result = 0;
        String token;
        StringTokenizer tokenizer = new StringTokenizer (expr);

        while (tokenizer.hasMoreTokens()) {
            token = tokenizer.nextToken();//识别运算符
            //补充代码31-40行
            //如果是运算符,调用isOperator
            if (isOperator(token))//如果是运算符,调用isOperator
            {
                char c[]=token.toCharArray();
                op2=stack.pop();//从栈中弹出操作数2
                op1=stack.pop();//从栈中弹出操作数1
                result=evalSingleOp(c[0],op1,op2);//根据运算符和两个操作数调用evalSingleOp计算result;
                stack.push(result);//计算result入栈;
            }
            else//如果是操作数
            {
                stack.push(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;
            default:

        }
        return result;
    }
}

myBC.java

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;
                break;
            default:
                value = 0;
                break;
        }
        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;
            default:
                break;
        }
        return result;
    }
}

任务2

任务详情

结对编程:1人负责客户端,一人负责服务器
0. 注意责任归宿,要会通过测试证明自己没有问题

  1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
  2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器
  3. 服务器接收到后缀表达式,调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
  4. 客户端显示服务器发送过来的结果
  5. 上传测试结果截图和码云链接

我完成的是服务器部分

运行截图(服务器部分)

客户端部分的截图在我的结对搭档的博客里面

代码

Server_2.java

import java.io.*;
import java.net.*;
import java.util.*;

public class Server_2 {
    public static void main(String[] args) {
        final int port=5353;
        ServerSocket Server_2forClient_2=null;
        Socket SocketOnServer_2=null;
        DataOutputStream Server_2out=null;
        DataInputStream Server_2in=null;
        try {
            Server_2forClient_2=new ServerSocket(port);
        }
        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 s=Server_2in.readUTF();
            System.out.println("服务器接收到表达式:"+s);
            String expr;
            int result;
            MyBC mybc=new MyBC();
            mybc.setExpression(s);
            expr=mybc.changedWay();
            result=mybc.evaluate(expr);
            Server_2out.writeUTF("中缀表达式“"+s+"”转后缀表达式“"+expr+",运算结果为:"+result);
            //Thread.sleep(500);
        }
        catch (Exception e2) {
            System.out.println("客户端已断开"+e2);
        }
    }
}

Client_2.java

import java.io.*;
import java.net.*;
import java.util.*;

public class Client_2 {
    public static void main(String[] args) {
        final int port=5353;
        final String host="172.30.4.50";
        Socket Client_2Socket;
        DataInputStream Client_2in=null;
        DataOutputStream Client_2out=null;
        String expr;
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入表达式:");
        expr=scanner.nextLine();
        try {
            Client_2Socket=new Socket(host,port);
            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("服务器回复:\n"+s);
        }
        catch (Exception e) {
            System.out.println("服务器已断开"+e);
        }
    }
}

任务3

任务详情

加密结对编程:1人负责客户端,一人负责服务器
0. 注意责任归宿,要会通过测试证明自己没有问题

  1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
  2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
  3. 服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
  4. 客户端显示服务器发送过来的结果
  5. 上传测试结果截图和码云链接

截图


代码

Server_3.java

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);
            //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 CipherText=Server_2in.readUTF();
            String expr;
            byte []data=Base64.getDecoder().decode(CipherText);
            System.out.println("服务器接收到密文:"+data);
            expr=AES.DecryptionAES(data);
            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);
        }
    }
}

Client_3.java

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("10.1.1.175",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("服务器回复:\n"+s);
        }
        catch (Exception e) {
            System.out.println("服务器已断开"+e);
        }
    }
}

任务4

任务详情

密钥分发结对编程:1人负责客户端,一人负责服务器
0. 注意责任归宿,要会通过测试证明自己没有问题

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

代码

Server_4.java

import java.io.*;
import java.net.*;
import java.util.*;

public class Server_4 {
    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(5200);
        }
        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);
            byte[] hh=AES_DH.DecryptionDES(data);
            Server_2out.writeUTF("接受到使用DH算法生成的共享密钥加密AES密钥生成的密文为:");
            for (int i=0;i<hh.length;i++) {
                System.out.print(hh[i]+" ");
            }
            Thread.sleep(500);
        }
        catch (Exception e2) {
            System.out.println("客户端已断开"+e2);
        }
    }
}

Client_4.java

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.*;

public class Client_4 {
    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;
        System.out.println("传输使用DH算法生成的共享密钥加密AES密钥生成的密文");
        try {
            AES.produceAESKey();//生成AES密钥
            byte[]c= AES.changeWay();//AES密钥,数组形式传输。

            byte[]cc=AES_DH.EncryptionDES(c);//需要传输的使用DH算法生成的共享密钥加密AES密钥生成的密文,数组形式传输。
            Ciphertext = Base64.getEncoder().encodeToString(cc);//将加密后的密文由byte[]转换为String类型

        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Client_2Socket=new Socket("172.30.2.248",5200);
            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("服务器回复:\n"+s);
        }
        catch (Exception e) {
            System.out.println("服务器已断开"+e);
        }
    }
}

AES_DH.java

import javax.crypto.Cipher;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.security.Key;

public class AES_DH {
    //AES加密,返回密文。
    public static byte[] EncryptionDES(byte[]data) throws Exception {
        FileInputStream f = new FileInputStream("A_Key_DESede_DH.dat");
        ObjectInputStream b = new ObjectInputStream(f);
        Key k = (Key) b.readObject();//从文件中获取密钥
        Cipher cp = Cipher.getInstance("AES");//创建密码器
        cp.init(Cipher.ENCRYPT_MODE, k);//初始化密码器,第一个参数指定密码器准备进行加密还是解密,第二个参数则传入加密或解密所使用的密钥。
        byte ctext[] = cp.doFinal(data);//执行Cipher对象的doFinal()方法,该方法的参数中传入待加密的明文,从而按照前面设置的算法与模式对明文加密。
        System.out.println("共享密钥加密完成!");
        //FileOutputStream f2 = new FileOutputStream("Ciphertext.txt");//将密文保存于Ciphertext.dat中。
        //f2.write(ctext);//处理加密结果
        return ctext;
    }
    //DESede解密,信息保存。
    public static byte[] DecryptionDES(byte[]data) throws Exception{
        FileInputStream f = new FileInputStream("A_Key_DESede_DH.dat");
        ObjectInputStream b = new ObjectInputStream(f);
        Key k = (Key) b.readObject();//从文件中获取密钥
        Cipher cp = Cipher.getInstance("AES");//创建密码器
        cp.init(Cipher.DECRYPT_MODE,k);
        byte ctext[]=cp.doFinal(data);
        //FileOutputStream ff=new FileOutputStream("Plaintext.txt");//将明文保存于Plaintext.dat中。
        //ff.write(ctext);
        System.out.println("共享密钥解密完成!");
        return ctext;
    }
}

任务5

任务详情

实验五 网络编程与安全-5
完整性校验结对编程:1人负责客户端,一人负责服务器
0. 注意责任归宿,要会通过测试证明自己没有问题

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

代码

Server_5.java

import java.io.*;
import java.net.*;
import java.util.*;

public class Server_5 {
    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(5555);
        }
        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("匹配成功");
            Thread.sleep(5000);
        }
        catch (Exception e2) {
            System.out.println("客户端已断开"+e2);
        }
    }
}

Client_5.java

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.security.MessageDigest;
import java.util.*;

public class Client_5 {
    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 {
            MessageDigest m=MessageDigest.getInstance("MD5");//生成MessageDigest对象,使用静态方法
            m.update(expr.getBytes("UTF8"));//x为需要计算的字符串,update传入的参数是字节类型或字节类型数组,对于字符串,需要先使用getBytes( )方法生成字符串数组。
            byte ss[ ]=m.digest( );//计算的结果通过字节类型的数组返回。
            String result="";
            for (int i=0; i<ss.length; i++){
                //处理计算结果
                result+=Integer.toHexString((0x000000ff & ss[i]) |
                        0xffffff00).substring(6);
            }
            Client_2Socket=new Socket("172.30.2.248",5555);
            Client_2in=new DataInputStream(Client_2Socket.getInputStream());
            Client_2out=new DataOutputStream(Client_2Socket.getOutputStream());
            Client_2out.writeUTF(result);
            String s=Client_2in.readUTF();
            System.out.println("服务器回复:\n"+s);
        }
        catch (Exception e) {
            System.out.println("服务器已断开"+e);
        }
    }
}