20155213 實驗五《網絡編程與安全》實驗報告

20155213 實驗五《網絡編程與安全》實驗報告

實驗內容

  1. 瞭解計算機網絡基礎
  2. 掌握Java Socket編程
  3. 理解混合密碼系統
  4. 掌握Java 密碼技術相關API的使用

實驗步驟與結果

任務一

  1. 參考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA
  2. 結對實現中綴表達式轉後綴表達式的功能 MyBC.java
  3. 結對實現從上面功能中獲取的表達式中實現後綴表達式求值的功能,調用MyDC.java
  • 棧的介紹
    • 只容許在表尾插入和刪除的線性表
    • 容許插入和刪除的一端稱爲棧頂(top),另外一端稱爲棧底(bottom)
    • 後進先出 (LIFO)
  • 後綴式的運算規則
    • 運算符在式中出現的順序恰爲表達式的運算順序;
    • 每一個運算符和在它以前出現且緊靠它的兩個操做數構成一個最小表達式。
  • 原表達式求得後綴式
    • 設立一個棧,存放運算符,首先棧爲空;
      編譯程序從左到右掃描原表達式,若遇到操做 數,直接輸出,並輸出一個空格做爲兩個操做 數的分隔符;
    • 若遇到運算符,則與棧頂比較,比棧頂級別高 則進棧,不然退出棧頂元素並輸出,而後輸出 一個空格做分隔符;
    • 若遇到左括號,進棧;若遇到右括號,則一直 退棧輸出,直到退到左括號止。
    • 當棧變成空時,輸出的結果即爲後綴表達式。

  • 代碼難點解決
    • 如何壓棧
while (tokenizer.hasMoreTokens())
        {
            token = tokenizer.nextToken();

            //若是是運算符,調用isOperator
            if (this.isOperator(token))
            {
                if(token.charAt(0)==')')
                    while (Nch!='(')
                    {
                        Nch=this.stack.pop();
                        if(Nch!='(')
                            Nextexpr=Nextexpr+" "+Nch;
                    }
                Nch=' ';
                ch=this.stack.pop();
                this.stack.push(ch);
                if(('*'==token.charAt(0)&&(ch=='+'||ch=='-'))||('*'==token.charAt(0)&&ch==' ')||('*'==token.charAt(0)&&ch=='(')||
                        ('/'==token.charAt(0)&&(ch=='+'||ch=='-'))||('/'==token.charAt(0)&&ch==' ')||('/'==token.charAt(0)&&ch=='(')
                        ||('-'==token.charAt(0)&&(ch=='('||ch==' '))
                        ||('+'==token.charAt(0)&&(ch=='('||ch==' '))
                        || '('==token.charAt(0))
                    this.stack.push(token.charAt(0));
                else if(token.charAt(0)!=')'){
                    Nextexpr=Nextexpr+" "+this.stack.pop();
                    ch=this.stack.pop();
                    this.stack.push(ch);
                    if(!(('*'==token.charAt(0)&&(ch=='+'||ch=='-'))||('*'==token.charAt(0)&&ch==' ')||('*'==token.charAt(0)&&ch=='(')||
                            ('/'==token.charAt(0)&&(ch=='+'||ch=='-'))||('/'==token.charAt(0)&&ch==' ')||('/'==token.charAt(0)&&ch=='(')
                            ||('-'==token.charAt(0)&&(ch=='('||ch==' '))
                            ||('+'==token.charAt(0)&&(ch=='('||ch==' '))
                            || '('==token.charAt(0))){
                        Nextexpr=Nextexpr+" "+this.stack.pop();
                    }

                    this.stack.push(token.charAt(0));
                }
            }
            else//若是是操做數
            {
                Nextexpr=Nextexpr+" "+token;
            }

        }
        while(!this.stack.empty())
        {
            Nextexpr=Nextexpr+" "+this.stack.pop();
        }
  • 運行截圖

任務二

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

  1. 注意責任歸宿,要會經過測試證實本身沒有問題
  2. 基於Java Socket實現客戶端/服務器功能,傳輸方式用TCP
  3. 客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式經過網絡發送給服務器
  4. 服務器接收到後綴表達式,調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
  5. 客戶端顯示服務器發送過來的結果
  • socket一般也稱做"套接字",用於描述IP地址和端口,是一個通訊鏈的句柄。應用程序一般經過"套接字"向網絡發出請求或者應答網絡請求
  • 在調用了socket以後其實也就只須要IP和端口號要和服務器一致就好
  • 我負責的是客戶端java

  • 端口號和IP設置代碼android

Socket socket = new Socket("192.168.43.252",5204);
    System.out.println("客戶端啓動成功");
  • 運行截圖

任務三

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

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

  • 密碼介紹
  • 對稱密碼(symmetric cryptography)是指在加密和解密時使用同一密鑰的方式。
  • 公鑰密碼(public-key cryptography)則是指在加密和解密時使用不一樣密鑰的方式,公鑰密碼又稱爲非對稱密碼(asymmetric cryptography)。
  • 本實驗用到的對稱密碼算法3DES
  • 具體步驟參考java密碼學
  • 運行截圖

任務四

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

  1. 注意責任歸宿,要會經過測試證實本身沒有問題
  2. 基於Java Socket實現客戶端/服務器功能,傳輸方式用TCP
  3. 客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式用3DES或AES算法加密經過網絡把密文發送給服務器
  4. 客戶端和服務器用DH算法進行3DES或AES算法的密鑰交換
  5. 服務器接收到後綴表達式表達式後,進行解密,而後調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
  6. 客戶端顯示服務器發送過來的結果
  • DH算法介紹
  • DH算法是創建在DH公鑰和私鑰的基礎上的,A須要和B共享密鑰時,A和B各自生成DH公鑰和私鑰,公鑰對外公佈而私鑰各自祕密保存。本實例將介紹Java中如何建立並部署DH公鑰和私鑰,以便後面一小節利用它建立共享密鑰。
  • 創建兩個目錄A和B,模擬須要祕密通訊的A、B雙方,因爲DH算法須要A和B各自生成DH公鑰和私鑰,所以在這兩個目錄下都拷貝編譯後文件Key_DH。算法

  • 首先由A建立本身的公鑰和私鑰,即在A目錄下輸入「java Key_DH Apub.dat Apri.dat」運行程序,這時在目錄A下將產生文件Apub.dat和Apri.dat,前者保存着A的公鑰,後者保存着A的私鑰。
  • 而後由B建立本身的公鑰和私鑰,即在B目錄下輸入「java Key_DH Bpub.dat Bpri.dat」運行程序,這時在目錄B下將產生文件Bpub.dat和Bpri.dat,前者保存着B的公鑰,後者保存着B的私鑰。
  • 最後發佈公鑰,A將Apub.dat拷貝到B目錄,B將Bpub.dat拷貝到A的目錄。
    這樣,A、B雙方的DH公鑰和私鑰已經建立並部署完畢。編程

  • 運行截圖數組

任務五

完整性校驗結對編程:1人負責客戶端,一人負責服務器安全

  1. 注意責任歸宿,要會經過測試證實本身沒有問題
  2. 基於Java Socket實現客戶端/服務器功能,傳輸方式用TCP
  3. 客戶端讓用戶輸入中綴表達式,而後把中綴表達式調用MyBC.java的功能轉化爲後綴表達式,把後綴表達式用3DES或AES算法加密經過網絡把密文和明文的MD5値發送給服務器
  4. 客戶端和服務器用DH算法進行3DES或AES算法的密鑰交換
  5. 服務器接收到後綴表達式表達式後,進行解密,解密後計算明文的MD5值,和客戶端傳來的MD5進行比較,一致則調用MyDC.java的功能計算後綴表達式的值,把結果發送給客戶端
  6. 客戶端顯示服務器發送過來的結果
  • MD5介紹
import java.security.*;
public class DigestPass{
     public static void main(String args[ ]) throws Exception{
         String x=args[0];
         MessageDigest m=MessageDigest.getInstance("MD5");
         m.update(x.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);
         }
         System.out.println(result);
      }   
}
  • 運行截圖

任務六

  • Android 開發:
  • 客戶端功能用Android實現,完成有加分
  • 這是我和20155303一塊兒利用三天假期完成的,特別感謝她的幫助以及細心(´▽`ʃƪ);
  • 這裏的客戶端就是手機上的APP,而服務器依舊是IDEA上運行的服務器端
  • 手機上的具體實現代碼
package com.example.dell.webapp;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.UnknownHostException;

public class MainActivity extends AppCompatActivity {
    private TextView text1;
    private Button but1;
    private TextView text2;
    private EditText edit1;
    private final String DEBUG_TAG="mySocketAct";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        text1 = (TextView)findViewById(R.id.text1);
        text2 = (TextView)findViewById(R.id.text2);
        but1 = (Button)findViewById(R.id.but1);
        edit1 = (EditText) findViewById(R.id.edit);

        but1.setOnClickListener(new Button.OnClickListener()
        {
            @Override
            public void onClick(View v){
                Socket socket = null;
                String mesg = edit1.getText().toString();
                Log.e("dddd","set id");
                text1.setText(mesg);
                MyBC mybc=new MyBC();
                MyDC mydc=new MyDC();
                String Np="";
                String mesg1=mybc.evaluate(mesg);

                for(int i=2;i<mesg1.length();i++)
                    Np+=mesg1.charAt(i);

                int a= mydc.evaluate(Np);
                String str=a+"";
                text2.setText(str);




                try{
                     //text2.setText("結果");
                    socket = new Socket("172.16.2.107",5216);
                    PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);

                    mesg1 = mybc.evaluate(mesg);
                    //
                    for(int i=2;i<mesg1.length();i++)
                        Np+=mesg1.charAt(i);

                    out.println(Np);
                    out.flush();

                    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    String mstr = br.readLine();
                    if(mstr!=null){

                        text2.setText(mstr);
                    }else{
                        text2.setText("數據錯誤");
                    }
                    out.close();
                    br.close();
                    socket.close();
                }catch (UnknownHostException e){
                    e.printStackTrace();
                }catch (IOException e){
                    e.printStackTrace();
                }catch (Exception e){
                    Log.e(DEBUG_TAG, e.toString());
                }
            }
        });
    }
}
  • 運行截圖

出現的問題及解決

  • 問題
  • 客戶端的顯示:
    can not listen to:java.net.SocketException: Connection reset
    服務器

  • 服務器端顯示:Error.javax.crypto.BadPaddingException: Given final block not properly padded

  • 問題解決

  • 這每每是從客戶端傳來的密文不符合編碼要求致使的,在查閱了不少相關問題解決的網站後,總結出,在傳送密文時,須要將編碼改成ISO-8859-1,而不是一慣的UTF8,改完後就能夠正常運行了;

實驗體會

此次實驗讓我對結對編程有了更深的認識,兩我的一塊兒能夠很好的各自發揮本身的長處,能夠更加有效,更加快速的解決問題,真的感謝20155303同窗的幫助。

碼雲連接

參考文獻

PSP(Personal Software Process)時間

步驟 耗時(min) 百分比
需求分析 20 20
設計 30 30
代碼實現 30 30
測試 10 10
分析總結 10 10
相關文章
相關標籤/搜索