1. 程式人生 > >20165321 實驗五 網絡編程與安全

20165321 實驗五 網絡編程與安全

功能 sock || clas CI 信息 cti tput decrypt

任務1

任務詳情

兩人一組結對編程:

  1. 參考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA
  2. 結對實現中綴表達式轉後綴表達式的功能 MyBC.java
  3. 結對實現從上面功能中獲取的表達式中實現後綴表達式求值的功能,調用MyDC.java
  4. 上傳測試代碼運行結果截圖和碼雲鏈接

代碼

由於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人負責客戶端,一人負責服務器

  1. 註意責任歸宿,要會通過測試證明自己沒有問題
  2. 基於Java Socket實現客戶端/服務器功能,傳輸方式用TCP
  3. 客戶端讓用戶輸入中綴表達式,然後把中綴表達式調用MyBC.java的功能轉化為後綴表達式,把後綴表達式通過網絡發送給服務器
  4. 服務器接收到後綴表達式,調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
  5. 客戶端顯示服務器發送過來的結果
  6. 上傳測試結果截圖和碼雲鏈接

我完成的是服務器部分

運行截圖(服務器部分)

客戶端部分的截圖在我的結對搭檔的博客裏面
技術分享圖片

代碼

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人負責客戶端,一人負責服務器

  1. 註意責任歸宿,要會通過測試證明自己沒有問題
  2. 基於Java Socket實現客戶端/服務器功能,傳輸方式用TCP
  3. 客戶端讓用戶輸入中綴表達式,然後把中綴表達式調用MyBC.java的功能轉化為後綴表達式,把後綴表達式用3DES或AES算法加密後通過網絡把密文發送給服務器
  4. 服務器接收到後綴表達式表達式後,進行解密(和客戶端協商密鑰,可以用數組保存),然後調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
  5. 客戶端顯示服務器發送過來的結果
  6. 上傳測試結果截圖和碼雲鏈接

截圖

技術分享圖片
技術分享圖片

代碼

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人負責客戶端,一人負責服務器

  1. 註意責任歸宿,要會通過測試證明自己沒有問題
  2. 基於Java Socket實現客戶端/服務器功能,傳輸方式用TCP
  3. 客戶端讓用戶輸入中綴表達式,然後把中綴表達式調用MyBC.java的功能轉化為後綴表達式,把後綴表達式用3DES或AES算法加密通過網絡把密文發送給服務器
  4. 客戶端和服務器用DH算法進行3DES或AES算法的密鑰交換
  5. 服務器接收到後綴表達式表達式後,進行解密,然後調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
  6. 客戶端顯示服務器發送過來的結果
  7. 上傳測試結果截圖和碼雲鏈接

代碼

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人負責客戶端,一人負責服務器

  1. 註意責任歸宿,要會通過測試證明自己沒有問題
  2. 基於Java Socket實現客戶端/服務器功能,傳輸方式用TCP
  3. 客戶端讓用戶輸入中綴表達式,然後把中綴表達式調用MyBC.java的功能轉化為後綴表達式,把後綴表達式用3DES或AES算法加密通過網絡把密文和明文的MD5値發送給服務器
  4. 客戶端和服務器用DH算法進行3DES或AES算法的密鑰交換
  5. 服務器接收到後綴表達式表達式後,進行解密,解密後計算明文的MD5值,和客戶端傳來的MD5進行比較,一致則調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
  6. 客戶端顯示服務器發送過來的結果
  7. 上傳測試結果截圖和碼雲鏈接

代碼

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);
        }
    }
}

20165321 實驗五 網絡編程與安全