20135313_exp5
課程:Java程序與設計?????班級:1353 姓 名:吳子怡? 學號:20135313
小組成員:?20135113肖昱
成績:?????????????指導教師:婁嘉鵬???????實驗日期:2015.6.9
實驗密級:????????? 預習程度:?????????實驗時間:15:30-18:00
儀器組次:??????????必修/選修:選修????????實驗序號:5
實驗名稱:Java網絡編程及安全??????????????????????????????????????
實驗目的與要求:結對編程,實現客戶端和服務器之間數據的發送與接收,實現加解密和驗證Hash函數值。
實驗儀器:
?
| 名稱 | 型號 | 數量 |
| PC | DELL | 1 |
| Eclipse | ? | 1 |
?
?
?
一、實驗內容
?
1.用TCP代碼,實現服務器與客戶端。
2.客戶端與服務器連接
3.客戶端中輸入明文,利用DES算法加密,DES的秘鑰用RSA公鑰密碼中服務器的公鑰加密.
4.客戶端用RSA公鑰密碼中服務器的私鑰解密DES的,秘鑰,用秘鑰對密文進行解密,得出明文。
?
二.實驗過程。
1.客戶端 與服務器的連接。
服務器代碼:?
?
import java.io.BufferedInputStream;?
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.net.ServerSocket; import java.net.Socket; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; public class ServerTest { int port = 8821; void start() { Socket s = null; try { ServerSocket ss = new ServerSocket(port); ? //創建一個ServerSocket套接字對象,并綁定在8821端口上 while (true) { // 選擇進行傳輸的文件 String filePath = "C:\\Users\\wzy\\Desktop\\服務器\\jiami.txt"; File fi = new File(filePath); ?//通過將給定路徑名字符串轉換為抽象路徑名來創建一個新 File 實例 System.out.println("文件長度:" + (int) fi.length()); s = ss.accept(); System.out.println("建立socket鏈接"); DataInputStream dis = new DataInputStream(new BufferedInputStream(s.getInputStream())); ? //DataInputStream:使用指定的底層 InputStream 創建一個 DataInputStream; dis.readByte(); ?//返回此輸入流的下一個字節,以有符號 8 位 byte 的形式表示。 DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath))); DataOutputStream ps = new DataOutputStream(s.getOutputStream());//創建一個新的數據輸出流,將數據寫入指定基礎輸出流 ps.writeUTF(fi.getName()); ps.flush(); ps.writeLong((long) fi.length()); ps.flush(); int bufferSize = 8192; //緩沖區,1k byte[] buf = new byte[bufferSize]; while (true) { int read = 0; if (fis != null) { read = fis.read(buf); } if (read == -1) { break; } ps.write(buf, 0, read); } ps.flush();// 直到socket超時,導致數據不完整。 ? ? ? ? ? ? ? ? fis.close(); s.close(); ? ? ? ? ? ? ? ? System.out.println("文件傳輸完成"); } } catch (Exception e) { e.printStackTrace(); } } public static void main(String arg[]) { new ServerTest().start(); } }?客戶端Socket代碼:
import java.net.*; import java.io.*; public class ClientSocket { private String ip; private int port; private Socket socket = null; DataOutputStream out = null; DataInputStream getMessageStream = null; public ClientSocket(String ip, int port) { this.ip = ip; this.port = port; } /** *//** * 創建socket連接 *? * @throws Exception * ? ? ? ? ? ? exception */ public void CreateConnection() throws Exception { try { socket = new Socket(ip, port); } catch (Exception e) { e.printStackTrace(); if (socket != null) socket.close(); throw e; } finally { } } public void sendMessage(String sendMessage) throws Exception { try { out = new DataOutputStream(socket.getOutputStream()); if (sendMessage.equals("Windows")) { out.writeByte(0x1); out.flush(); return; } if (sendMessage.equals("Unix")) { out.writeByte(0x2); out.flush(); return; } if (sendMessage.equals("Linux")) { out.writeByte(0x3); out.flush(); } else { out.writeUTF(sendMessage); out.flush(); } } catch (Exception e) { e.printStackTrace(); if (out != null) out.close(); throw e; } finally { } } public DataInputStream getMessageStream() throws Exception { try { getMessageStream = new DataInputStream(new BufferedInputStream(socket.getInputStream())); return getMessageStream; } catch (Exception e) { e.printStackTrace(); if (getMessageStream != null) getMessageStream.close(); throw e; } finally { } } public void shutDownConnection() { try { if (out != null) out.close(); if (getMessageStream != null) getMessageStream.close(); if (socket != null) socket.close(); } catch (Exception e) { } } }?客戶端Test代碼:
?
import java.io.BufferedOutputStream;?
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileOutputStream; public class ClientTest { private ClientSocket cs = null; private String ip = "192.168.253.1";// 設置成服務器IP private int port = 8821; private String sendMessage = "Windwos"; public ClientTest() { try { if (createConnection()) { sendMessage(); getMessage(); } } catch (Exception ex) { ex.printStackTrace(); } } private boolean createConnection() { cs = new ClientSocket(ip, port); try { cs.CreateConnection(); System.out.print("連接服務器成功!" + "\n"); return true; } catch (Exception e) { System.out.print("連接服務器失敗!" + "\n"); return false; } } private void sendMessage() { if (cs == null) return; try { cs.sendMessage(sendMessage); } catch (Exception e) { System.out.print("發送消息失敗!" + "\n"); } } private void getMessage() { if (cs == null) return; DataInputStream inputStream = null; try { inputStream = cs.getMessageStream(); } catch (Exception e) { System.out.print("接收消息緩存錯誤\n"); return; } try { //本地保存路徑,文件名會自動從服務器端繼承而來。 String savePath = "E:\\客戶端\\"; int bufferSize = 8192; byte[] buf = new byte[bufferSize]; int passedlen = 0; long len=0; savePath += inputStream.readUTF(); DataOutputStream fileOut = new DataOutputStream(new BufferedOutputStream(new BufferedOutputStream(new FileOutputStream(savePath)))); len = inputStream.readLong(); System.out.println("文件的長度為:" + len + "\n"); System.out.println("開始接收文件!" + "\n"); while (true) { int read = 0; if (inputStream != null) { read = inputStream.read(buf); } passedlen += read; if (read == -1) { break; } //下面進度條本為圖形界面的prograssBar做的,這里如果是打文件,可能會重復打印出一些相同的百分比 System.out.println("文件接收了" + ?(passedlen * 100/ len) + "%\n"); fileOut.write(buf, 0, read); } System.out.println("接收完成,文件存為" + savePath + "\n"); fileOut.close(); } catch (Exception e) { System.out.println("接收消息錯誤" + "\n"); return; } } public static void main(String arg[]) { new ClientTest(); } }?
在這只做簡單代碼展示,具體傳輸文件見下述步驟。
2.用DES加密明文,并傳輸給服務器密文。
DES加密代碼:?
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; public class DESJiaMi { public static void main(String[] args) throws Exception { // DES算法要求有一個可信任的隨機數源 SecureRandom sr = new SecureRandom(); // 獲得密匙數據 FileInputStream fi = new FileInputStream(new File("key.txt")); byte rawKeyData[] = new byte[fi.available()]; fi.read(rawKeyData); fi.close(); // 從原始密匙數據創建DESKeySpec對象 DESKeySpec dks = new DESKeySpec(rawKeyData); // 創建一個密匙工廠,然后用它把DESKeySpec轉換成一個SecretKey對象 SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(dks); // Cipher對象實際完成加密操作 Cipher cipher = Cipher.getInstance("DES"); // 用密匙初始化Cipher對象 cipher.init(Cipher.ENCRYPT_MODE, key, sr); // 現在,獲取要加密的文件數據 FileInputStream fi2 = new FileInputStream(new File("lib.txt")); byte data[] = new byte[fi2.available()]; fi2.read(data); fi2.close(); // 正式執行加密操作 byte encryptedData[] = cipher.doFinal(data); // 用加密后的數據文件 FileOutputStream fo = new FileOutputStream(new File("jiami.txt")); fo.write(encryptedData); fo.close(); new ServerTest().start(); } }?DES解密代碼:
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; public class DESJieMi { public static void main(String[] args) throws Exception { new ClientTest(); // DES算法要求有一個可信任的隨機數源 SecureRandom sr = new SecureRandom(); // 獲得密匙數據 FileInputStream fi = new FileInputStream(new File("key.txt")); byte rawKeyData[] = new byte[fi.available()];// = new byte[5]; fi.read(rawKeyData); fi.close(); // 從原始密匙數據創建一個DESKeySpec對象 DESKeySpec dks = new DESKeySpec(rawKeyData); // 創建一個密匙工廠,然后用它把DESKeySpec對象轉換成一個 SecretKey對象 SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(dks); // Cipher對象實際完成解密操作 Cipher cipher = Cipher.getInstance("DES"); // 用密匙初始化Cipher對象 cipher.init(Cipher.DECRYPT_MODE, key, sr); // 現在,獲取數據并解密 FileInputStream fi2 = new FileInputStream(new File("jiami.txt")); byte encryptedData[] = new byte[fi2.available()]; fi2.read(encryptedData); fi2.close(); // 正式執行解密操作 byte decryptedData[] = cipher.doFinal(encryptedData); // 這時把數據還原成原有的類文件 FileOutputStream fo = new FileOutputStream(new File("jiemi.txt")); fo.write(decryptedData); } } 密鑰 key.txt?lib.txt表示明文?
通過服務器與客戶端相連,服務器將加密后的文件jiami.txt傳輸給客戶端待用。
加密后的密文 jiami.txt
?3.RSA加密密鑰,傳輸,RSA解密獲得密鑰。
服務器使用已給出的代碼加密密鑰。原理相近,不作截圖展示。
代碼為老師上課在Java學習群中給出的代碼包,也不作截圖展示。
?將所加密內容發給客戶端。并進行解密,得到客戶端解密后的密鑰。
?
?4.用密鑰解密密文。
解密代碼所生成的jiemi.txt。
?
?
?
【實驗體會】
?本次實驗中大部分代碼都是老師既定給好的,而我們的主要任務是對要實現的傳輸、加解密、連接等進行處理銜接,讓我們從編程一躍提升到有目的性的實戰。這次實驗主要分為三個部分,一是多線程客戶端和服務器的連接,而是RSA公鑰加密,三是DES加密。我認為,這些內容都是要跨科目實現的,不管是密碼學還是計網,都在這過程中起著很大的作用。然而,實驗中也遇到不少問題,也較為瑣碎。和搭檔討論后,對方給了我很多指導,也逐漸能夠看到實驗結果離我越來越近。以后還是需要更多地尋找實驗操作,多和在Java方面學習更深入的同學探討來提升自己的能力。
?
| 步驟 | 耗時 | 百分比 |
| 需求分析 | ?30m | ?30% |
| 設計 | 10m | ?10% |
| 代碼實現 | 10m | ?10% |
| 測試 | 40m | ?40% |
| 分析總結 | ?10m | ?10% |
轉載于:https://www.cnblogs.com/paperfish/p/4575956.html
總結
以上是生活随笔為你收集整理的20135313_exp5的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Value Investment
- 下一篇: [hdu5270]按位统计,容斥,归并