20165203實驗五 網絡編程與安全

20165203實驗五 網絡編程與安全

任務一

兩人一組結對編程:html

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

1、實驗過程:java

1.根據婁老師的博客,咱們先了解前綴表示法、中綴表示法和後綴表示法的概念:git

表達式Exp = S1 + OP + S2(S1 ,S2是兩個操做數,OP爲運算符)有三種標識方法:算法

OP + S1 + S2 爲前綴表示法
S1 + OP + S2 爲中綴表示法
S1 + S2 + OP 爲後綴表示法
例如:Exp = a * b + (c - d / e) * fexpress

前綴式: + * a b * - c / d e f
中綴式: a * b + c - d / e * f
後綴式: a b * c d e / - f * +編程

2.中綴表達式轉化成後綴表達式的過程:數組

  • 設立一個棧,存放運算符,首先棧爲空;
  • 從左到右掃描中綴式,若遇到操做數,直接輸出,並輸出一個空格做爲兩個操做數的分隔符;
  • 若遇到運算符,則與棧頂比較,比棧頂級別高則進棧,不然退出棧頂元素並輸出,而後輸出一個空格做分隔符;
  • 若遇到左括號,進棧;若遇到右括號,則一直退棧輸出,直到退到左括號止。
  • 當棧變成空時,輸出的結果即爲後綴表達式。

3.中綴表達式轉化成後綴表達式代碼實現:安全

import java.util.*;

public class NewMyBC {
    String beforeExpression;//未轉化的中綴表達式
    String afterExpression = "";//轉化後的後綴表達式
    int left = 0;//定義左括號數
    int right = 0;//定義右括號數


    //判斷符號的級別
    public int judgeGrade(char chi) {
        int grade = 0;
        switch (chi) {
            //左括號是第一級
            case '(':
                grade = 1;
                break;
            //+和-是第二級
            case '+':
            case '-':
                grade = 2;
                break;
            //*和÷是第三級
            case '*':
            case '÷':
                grade = 3;
                break;
            // "/"是第四級
            case '/':
                grade = 4;
                break;
            //右括號是第五級
            case ')':
                grade = 5;
                break;
            default:
                grade = 0;
        }
        return grade;
    }

    public void setBeforeExpression(String exp) {
        beforeExpression=exp;
    }

    public String transformWay() {
        Stack stack = new Stack();//新建一個空棧
        int i = 0;
        char op;
        while (i < beforeExpression.length()) {
            op = beforeExpression.charAt(i);//op存放從中綴表達式中取到的元素
            if (op >= '0' && op <= '9') {
                afterExpression = afterExpression + op;//若是是數字,則直接輸出至後綴表達式
            } else if (op == '+' || op == '-' || op == '*' || op == '÷') {
                afterExpression = afterExpression + ' ';//有運算符,在數字之間加空格
                // 若是棧爲空,則運算符直接入棧
                if (stack.empty()) {
                    stack.push(op);
                }
                //根據符號的級別判斷操做
                else if (judgeGrade(op) > judgeGrade((char) stack.peek())) {
                    stack.push(op);//比棧頂級別高或相等,直接入棧
                } else {
                    afterExpression = afterExpression + String.valueOf(stack.pop()) + ' ';//不然直接輸出
                    i--;
                }

            } else if (op == '(') {
                left++;
                stack.push(op);//左括號直接入棧
            } else if (op == ')') {
                afterExpression += " ";
                right++;
                while ((char) stack.peek() != '(') {//右括號,出棧,直到左括號爲止
                    afterExpression = afterExpression + String.valueOf(stack.pop()) + " ";
                }
                stack.pop();
            }
            i++;
        }
        afterExpression += " ";
        while(!stack.empty()){
            afterExpression=afterExpression+String.valueOf(stack.pop())+" ";
        }
        if (left != right) {
            System.out.println("括號有誤");
            System.exit(0);
        }
        return afterExpression;
    }
}

4.後綴表達式求值的步驟:服務器

  • 設置一個操做數棧,開始棧爲空;
  • 從左到右掃描後綴表達式,遇操做數,進棧;
  • 若遇運算符,則從棧中退出兩個元素,先退出的放到運算符的右邊,後退出的放到運算符左邊,運算後的結果再進棧,直到後綴表達式掃描完畢。
    此時,棧中僅有一個元素,即爲運算的結果。

5.求值代碼:網絡

import java.util.Stack;

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) {
        int op1, op2, result = 0;
        String token;
        StringTokenizer tokenizer = new StringTokenizer(expr);//劃分表達式

        while (tokenizer.hasMoreTokens()) {
            token = tokenizer.nextToken();//將算數表達式分解的

            if (isOperator(token))//見下方isOperateor方法,當是運算符的時候進入if語句
            {
                op2 = (stack.pop()).intValue();
                op1 = (stack.pop()).intValue();//彈出最上面兩個操做數
                result = evalSingleOp(token.charAt(0), op1, op2);//見下方evaSingleOp方法
                stack.push(new Integer(result));//將計算結果壓棧
            } else{
                stack.push(new Integer(Integer.parseInt(token)));//操做數入棧
            }
        }

        return result;//輸出結果
    }

    private boolean isOperator(String token)//判斷是否爲運算符,注意用equal語句比較字符串
    {
        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;
    }
}

6.測試代碼以下:

import java.util.Scanner;

public class MyDCTest {
    public static void main(String[] args) {
        String expression, again;
        int result;
        try {
            Scanner in = new Scanner(System.in);
            do {
                MyDC evaluator = new MyDC();
                System.out.println("Enter a valid postfix expression: ");
                expression = in.nextLine();
                result = evaluator.evaluate(expression);
                System.out.println();
                System.out.println("That expression equals " + result);

                System.out.print("Evaluate another expression [Y/N]? ");
                again = in.nextLine();
                System.out.println();
            }
            while (again.equalsIgnoreCase("y"));
        } catch (Exception IOException) {
            System.out.println("Input exception reported");
        }
    }
}

2、實驗截圖:

3、碼雲連接

任務二

結對編程:1人負責客戶端,一人負責服務器

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

1、實驗過程:

1.通過與搭檔協商,我負責客戶端(Client.java)部分,搭檔負責服務端(Server.java)部分。

2.客戶端部分的代碼以下:

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

public class Client {
    public static void main(String[] args) {
        Socket socket;//套接字對象
        DataInputStream in=null;//輸入流
        DataOutputStream out=null;//輸出流
        //中綴表達式的輸入
        String str;
        Scanner scanner=new Scanner(System.in);
        System.out.println("請輸入中綴表達式:");
        str=scanner.nextLine();
        try {
            socket=new Socket("localhost",5203);
            in=new DataInputStream(socket.getInputStream());
            out=new DataOutputStream(socket.getOutputStream());
            out.writeUTF(str);
            String s=in.readUTF();
            System.out.println("結果爲:\n"+s);
        }
        catch (Exception e) {
            System.out.println("服務器已斷開"+e);
        }
    }
}

2、實驗截圖:

3、碼雲連接

任務三

加密結對編程:1人負責客戶端,一人負責服務器

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

1、實驗過程:

1.我負責客戶端,負責編寫Client.java.

2.根據婁老師的密碼學算法博客,我和搭檔所共同完成的DES算法代碼以下:

import java.io.*;
import javax.crypto.*;
public class Skey_DES{
    public static void main(String args[]) throws Exception{
        KeyGenerator kg=KeyGenerator.getInstance("DESede");
        kg.init(168);
        SecretKey k=kg.generateKey( );
        FileOutputStream  f=new FileOutputStream("key1.dat");
        ObjectOutputStream b=new  ObjectOutputStream(f);
        b.writeObject(k);
    }
}

3.Client.java代碼以下:

在以前的代碼上,增長以下代碼:

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

public class Client {
    public static void main(String[] args) {
        String mess;
        Scanner scanner=new Scanner(System.in);
        System.out.println("請輸入問題");
        mess=scanner.nextLine();
        String key="";
        int n=-1;
        byte [] a=new byte[128];
        try{  File f=new File("key1.dat");
            InputStream in = new FileInputStream(f);
            while((n=in.read(a,0,100))!=-1) {
                key=key+new String (a,0,n);
            }
            in.close();
        }
        catch(IOException e) {
            System.out.println("File read Error"+e);
        }
        System.out.println("客戶端提出的問題爲:"+mess);
        NewMyBC mybc=new NewMyBC();
        String str;
        mybc.setBeforeExpression(mess);
        str=mybc.transformWay();
        String mi=EncryptDecrypt.AESEncode(key,str);
        System.out.println("客戶端加密後密文爲:"+mi);
        Socket socket;
        DataInputStream in=null;
        DataOutputStream out=null;
        try{  socket=new Socket("localhost",5006);
            in=new DataInputStream(socket.getInputStream());
            out=new DataOutputStream(socket.getOutputStream());
            BufferedReader in1=new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter writer=new PrintWriter(socket.getOutputStream());
            out.writeUTF(mi);
            String  s=in.readUTF();   //in讀取信息,堵塞狀態
            System.out.println("客戶收到服務器的回答爲:"+s);
            Thread.sleep(500);
        }
        catch(Exception e) {
            System.out.println("服務器已斷開"+e);
        }
    }
}

2、實驗截圖:

3、碼雲連接

任務四

密鑰分發結對編程:1人負責客戶端,一人負責服務器

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

1、實驗過程:

1.我負責客戶端,搭檔負責服務器端。

2.根據婁老師的密碼學算法博客,我和搭檔共同完成的DES算法代碼以下:

import java.security.PublicKey;
import java.security.PrivateKey;
import java.io.*;
import javax.crypto.KeyAgreement;
import javax.crypto.spec.*;

public class KeyAgree{
    public static void main(String args[ ]) throws Exception{
        // 讀取對方的DH公鑰
        File file=new File("Ckey.dat");
        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);
        //生成共享信息
        byte[ ] sb=ka.generateSecret();
        for(int i=0;i<sb.length;i++){
            System.out.print(sb[i]+",");
        }
        OutputStream out=new FileOutputStream(file);
        out.write(sb);
        out.close();
        SecretKeySpec k=new  SecretKeySpec(sb,"AES");
    }
}
public class Dapart {
    String dapartstring(String str){
        String s="";
        char c[]=str.toCharArray();
        for(int i=0;i<c.length;i++){
            s=s+c[i]+" ";
        }
        return s;
    }
}

部分代碼,具體代碼見碼雲連接
3.客戶端的代碼在實驗二的基礎上增長以下代碼:

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

public class Client {
    public static void main(String[] args)throws IOException{
        String key="";
        int n=-1;
        byte [] a=new byte[128];
        try{  File f=new File("Ckey.dat");
            InputStream in = new FileInputStream(f);
            while((n=in.read(a,0,100))!=-1) {
                key=key+new String (a,0,n);
            }
            in.close();
        }
        catch(IOException e) {
            System.out.println("File read Error"+e);
        }
        String mess;
        Scanner scanner=new Scanner(System.in);
        System.out.println("請輸入問題:");
        mess=scanner.nextLine();
        NewMyBC mybc=new NewMyBC();
        String str;
        mybc.setBeforeExpression(mess);
        str=mybc.transformWay();
        String m=EncryptDecrypt.AESEncode(key, str);
        System.out.println("客戶加密以後的密文爲:"+m);
        Socket mysocket;
        DataInputStream in=null;
        DataOutputStream out=null;
        try{  mysocket=new Socket("localhost",6006);
            in=new DataInputStream(mysocket.getInputStream());
            out=new DataOutputStream(mysocket.getOutputStream());
            out.writeUTF(m);
            String  s=in.readUTF();   //in讀取信息,堵塞狀態
            System.out.println("客戶收到服務器的回答爲:"+s);
            Thread.sleep(500);
        }
        catch(Exception e) {
            System.out.println("服務器已斷開"+e);
        }
    }
}

2、實驗截圖:

3、碼雲連接

任務五

實驗五 網絡編程與安全-5
完整性校驗結對編程:1人負責客戶端,一人負責服務器

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

1、實驗過程:

1.我負責客戶端,搭檔負責服務器端。

2.根據婁老師的密碼學算法博客,我和搭檔共同完成的算法代碼以下:

import java.security.*;
public class DigestPass{
    static String md5(String str) throws Exception{
        MessageDigest m=MessageDigest.getInstance("MD5");
        m.update(str.getBytes("UTF8"));
        byte s[ ]=m.digest( );
        String result="";
        for (int i=0; i<s.length; i++){
            result+=Integer.toHexString((0x000000ff & s[i]) |
                    0xffffff00).substring(6);
        }
        return result;
    }
}

3.客戶端代碼以下:

就以前實驗二的代碼添加以下代碼:

import java.net.*;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws Exception {
        String key = "";
        int n = -1;
        byte[] a = new byte[128];
        try {
            File f = new File("Ckey.dat");
            InputStream in = new FileInputStream(f);
            while ((n = in.read(a, 0, 100)) != -1) {
                key = key + new String(a, 0, n);
            }
            in.close();
        } catch (IOException e) {
            System.out.println("File read Error" + e);
        }
        String mess;
        Scanner scanner = new Scanner(System.in);
        System.out.println("請輸入問題爲:");
        mess = scanner.nextLine();
        NewMyBC mybc = new NewMyBC();
        String str;
        mybc.setBeforeExpression(mess);
        str = mybc.transformWay();
        String md5 = DigestPass.md5(str);
        String mw = EncryptDecrypt.AESEncode(key, str);
        System.out.println("客戶端提供的MD—5爲:" + md5);
        System.out.println("客戶加密以後的密文爲:" + mw);
        Socket mysocket;
        DataInputStream in = null;
        DataOutputStream out = null;
        try {
            mysocket = new Socket("localhost", 2010);
            in = new DataInputStream(mysocket.getInputStream());
            out = new DataOutputStream(mysocket.getOutputStream());
            out.writeUTF(mw);
            out.writeUTF(md5);
            String answer = in.readUTF();   //in讀取信息,堵塞狀態
            System.out.println("客戶收到服務器的回答爲:" + answer);
            Thread.sleep(500);
        } catch (Exception e) {
            System.out.println("服務器已斷開" + e);
        }
    }
}

部分代碼,具體代碼見碼雲連接

2、實驗截圖:

3、碼雲連接

實驗過程當中遇到的問題及解決辦法

Q:在運行代碼時,提示Error:(1, 1) java: 非法字符: '\ufeff',該怎麼作?

A:我百度了一下,找到了一篇博客,根據博客裏的步驟,解決了問題。

步驟 耗時(h) 百分比
設計 2 20%
代碼實現 5 50%
測試 5 20%
分析總結 1 10%

實驗體會總結

本次實驗,我主要負責客戶端代碼,搭檔負責服務器端代碼,許多算法也是咱們根據婁老師的博客共同研究出來的。本次實驗是最後一次實驗了,本學期的確受Java折磨很多,可是仍是感謝婁老師給咱們提供了不少新的學習方法,相信之後Java會幫助咱們不少的。

相關文章
相關標籤/搜索