1. 程式人生 > 其它 >假設Tom和Jerry利用Java UDP進行聊天,請為他們編寫程式。

假設Tom和Jerry利用Java UDP進行聊天,請為他們編寫程式。

技術標籤:加密解密密碼學資訊保安多執行緒rsa

假設Tom和Jerry利用Java UDP進行聊天,請為他們編寫程式。具體如下:
(1)、Tom和Jerry聊天的雙方都應該具有傳送端和接收端;
(2)、利用DatagramSocket與DatagramPacket;
(3)、實現 java.lang.Runnable類,重寫 run()方法。
(4)、Tom對傳送的內容(傳送的內容為 學生本人的名字+學生本人的學號)使用對稱/非對稱加密演算法(金鑰可以自主分配,不需要權威機構來分配)來加密,然後將加密後的密文傳送給Jerry;Jerry對收到的密文進行解密,還原成明文內容(即 學生本人的名字+學生本人的學號)

RSA加密類:

package RSA;
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
 
//RSA非對稱加密演算法工具類
public class RSA {
    
    private static final String KEY_ALGORITHM = "RSA";//非對稱金鑰演算法
private static final int KEY_SIZE = 512;//金鑰長度,在512到65536位之間,建議不要太長,否則速度很慢,生成的加密資料很長 private static final String CHARSET = "UTF-8";//字元編碼格式 //生成KeyPair金鑰對 public static KeyPair getKeyPair() throws Exception { return getKeyPair(null); } //生成金鑰對的密碼password public static KeyPair getKeyPair
(String password) throws Exception { //例項化金鑰生成器 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM); //初始化金鑰生成器 if(password == null){ keyPairGenerator.initialize(KEY_SIZE); }else { SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); secureRandom.setSeed(password.getBytes(CHARSET)); keyPairGenerator.initialize(KEY_SIZE, secureRandom); } //生成金鑰對 return keyPairGenerator.generateKeyPair(); } //取得私鑰byte[] public static byte[] getPrivateKeyBytes(KeyPair keyPair) { return keyPair.getPrivate().getEncoded(); } //取得Base64編碼的私鑰byte[] public static String getPrivateKey(KeyPair keyPair) { Return Base64.getEncoder().encodeToString(getPrivateKeyBytes(keyPair)); } //取得公鑰byte[] public static byte[] getPublicKeyBytes(KeyPair keyPair) { return keyPair.getPublic().getEncoded(); } public static String getPublicKey(KeyPair keyPair) { return Base64.getEncoder().encodeToString(getPublicKeyBytes(keyPair)); } //將私鑰進行加密 public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception { //例項化金鑰工廠 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); //生成私鑰 PrivateKey key = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey)); //資料加密 Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, key); return cipher.doFinal(data); } //私鑰加密 public static String encryptByPrivateKey(String data, String privateKey) throws Exception { byte[] key = Base64.getDecoder().decode(privateKey); return Base64.getEncoder().encodeToString(encryptByPrivateKey(data.getBytes(CHARSET), key)); } //公鑰加密 public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { //例項化金鑰工廠 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); //生成公鑰 PublicKey key = keyFactory.generatePublic(new X509EncodedKeySpec(publicKey)); //資料加密 Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, key); return cipher.doFinal(data); } //公鑰加密 public static String encryptByPublicKey(String data, String publicKey) throws Exception { byte[] key = Base64.getDecoder().decode(publicKey); return Base64.getEncoder().encodeToString(encryptByPublicKey(data.getBytes(CHARSET), key)); } //私鑰解密 public static byte[] decryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception { //例項化金鑰工廠 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); //生成私鑰 PrivateKey key = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey)); //資料解密 Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, key); return cipher.doFinal(data); } //私鑰解密 public static String decryptByPrivateKey(String data, String privateKey) throws Exception { byte[] key = Base64.getDecoder().decode(privateKey); return new String(decryptByPrivateKey(Base64.getDecoder().decode(data), key), CHARSET); } //公鑰解密 public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { //例項化金鑰工廠 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); //產生公鑰 PublicKey key = keyFactory.generatePublic(new X509EncodedKeySpec(publicKey)); //資料解密 Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, key); return cipher.doFinal(data); } //公鑰解密 public static String decryptByPublicKey(String data, String publicKey) throws Exception { byte[] key = Base64.getDecoder().decode(publicKey); return new String(decryptByPublicKey(Base64.getDecoder().decode(data), key), CHARSET); } }

xiaozou的主類:

UDPSocket_zou
package xiaozou;
public class UDPSocket_zou {
    public static void main(String[] args) throws Exception {
       
        //分別啟動傳送資訊執行緒和接收訊息執行緒
        Thread thread1 = new Thread(new UDPSocketZouReceivethread());
        Thread thread2 = new Thread(new 
UDPSocketZouSendthread());
        thread1.start();
        thread2.start();
    }
}

xiaozou的接收類

UDPSocketZouReceivethread
package xiaozou;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.security.KeyPair;
import RSA.RSA;
//xiaozou的接收類,生成公鑰私鑰,把公鑰通過檔案操作儲存在檔案中,用自己的私鑰解密收到的資料
public class UDPSocketZouReceivethread implements Runnable {
//接收方的套接字必須和對面傳送方指定的packet埠號相同
	    DatagramSocket tianSocket;

	    {
	        try {
	        	tianSocket = new DatagramSocket(8088);
	        } catch (SocketException e) {
	            e.printStackTrace();
	        }
	    }

	    byte[] ibuf = new byte[1024];
	    //接收的資料
	    DatagramPacket tianPacket = new DatagramPacket(ibuf, ibuf.length);
@Override
	    public void run() {
	    	//生成金鑰對
	        KeyPair keyPair = null;
			try {
				keyPair = RSA.getKeyPair();
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
 			//公鑰			 
String publicKey = RSA.getPublicKey(keyPair); 
//私鑰
String privateKey = RSA.getPrivateKey(keyPair);
System.out.println("公鑰:\n" + publicKey);
	       System.out.println("私鑰:\n" + privateKey);
	        
	        
	        File file = new File("text.txt");
            BufferedWriter out = null;
    //FileWriter()向檔案寫入資料
			try {
 				out = new BufferedWriter(new FileWriter(file));
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}         
           
            	
            	try {
//將公鑰寫入檔案中
					out.write(publicKey);
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
            	try {
					out.flush();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}	//重新整理緩衝流
            	// 手動把快取區內容儲存到檔案,不然會造成資料的丟失            	
            	
	        
	        while (true) {
	            try {
	            	tianSocket.receive(tianPacket);
	            } catch (IOException e) {
	                e.printStackTrace();
	            }
	            String s1 = new String(tianPacket.getData(), 0, tianPacket.getLength());
	            String s2 = null;
				try {
					 s2 = RSA.decryptByPrivateKey(s1, privateKey);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
	            System.out.println("加密後的資料:" + s1);
	            System.out.println("解密後的資料:" + s2);
	        }
	    }
	}

xiaozou的傳送類

UDPSocketZouSendthread
package xiaozou;
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
//實現runnable介面
public class UDPSocketZouSendthread implements Runnable {
	//接收方的套接字必須和對面傳送方指定的packet埠號相同
byte[] ibuf = new byte[1024];
	    String message;
	    Scanner scanner = new Scanner(System.in);
	    //該類的例項物件就相當於一個集裝箱,用於封裝UDP通訊中傳送或者接收的資料。
	    //建立傳送型別的資料報 
	    DatagramPacket tianPacket;

	    {
	        try {
	        	tianPacket = new DatagramPacket(ibuf, ibuf.length, InetAddress.getByName("127.0.0.1"), 2020);//指定對面接收方的埠h號
	        } catch (UnknownHostException e) {
	            e.printStackTrace();
	        }
	    }
	    //這個類的例項物件就可以傳送和接收DatagramPacket資料包
	   // 建立傳送方的套接字,並制定埠號和IP地址  
	    DatagramSocket ds;

	    {
	        try {
	            ds = new DatagramSocket(8087, InetAddress.getByName("127.0.0.1"));//自己的埠號為8087,也可以不指定,會自動分配
	        } catch (SocketException | UnknownHostException e) {
	            e.printStackTrace();
	        }
	    }

	    @Override
	    public void run() {
	        while (true) {
	        	//輸入
	            message = scanner.nextLine();
	           
	            tianPacket.setData(message.getBytes());
	            try {
	            	//傳送
	                assert ds != null;
	                ds.send(tianPacket);
	            } catch (IOException e) {
	                e.printStackTrace();
	            }
	        }
	    }
	}

xiaotian的主類:

UDPSocket_tian
package xiaotian;
public class UDPSocket_tian {
public static void main(String[] args) {
        //分別啟動傳送訊息執行緒和接收訊息執行緒
        Thread thread1 = new Thread(new UDPSocketTianReceivethread());
        Thread thread2 = new Thread(new UDPSocketTianSendthread());
        thread1.start();
        thread2.start();
    }
}

xiaotian的傳送類 ,用xiaozou的公鑰加密:

UDPSocketTianSendthread
package xiaotian;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.security.KeyPair;
import java.util.Scanner;
import RSA.RSA;//引入加密類
//同xiaozou
public class UDPSocketTianSendthread implements Runnable{
	
    byte[] ibuf = new byte[1024];
    String message;
    Scanner scanner = new Scanner(System.in);
    DatagramPacket tianPacket;

    {
        try {
tianPacket = new DatagramPacket(ibuf, ibuf.length, InetAddress.getByName("127.0.0.1"), 8088);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
    DatagramSocket ds;
    {
        try {
       ds = new DatagramSocket(8089, InetAddress.getByName("127.0.0.1"));
        } catch (SocketException | UnknownHostException e) {
            e.printStackTrace();
        }
    }
    
    @Override
    public void run() {
    	String txtLine = null;
    	try{
			File file1 = new File("text.txt");
			FileInputStream fis = new FileInputStream(file1);
			//例項化FileInputStream()物件,並直接傳入已開啟檔案的File物件
			InputStreamReader is = new InputStreamReader(fis);
			//InputStreamReader用於將位元組流中的位元組碼解碼成字元
			BufferedReader br = new BufferedReader(is);
			//BufferedReader類從字元輸入流中讀取文字並緩衝字元
			//以便有效地讀取字元、陣列和行
			 //讀取檔案資料,儲存zou的公鑰
			while((txtLine=br.readLine())!=null){	//按行讀取字串	
				 while (true) {
					    System.out.println("請輸入要傳送的資料");
			            message = scanner.nextLine();
			         	 String s1 = null;
						try {
							 //公鑰加密
s1=RSA.encryptByPublicKey(message,txtLine );
						} catch (Exception e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
						}
						System.out.println("加密前的資料:" + message);
			            System.out.println("加密後的資料:" + s1);
			            
			            tianPacket.setData(s1.getBytes());
			            try {
			                assert ds != null;
			                ds.send(tianPacket);
			            } catch (IOException e) {
			                e.printStackTrace();
			            }
			        }
			}
			br.close();
			
		}
       catch (FileNotFoundException e1) {	//異常處理
	         System.err.println("File not found!");
		}
        catch(Exception e2){
			e2.printStackTrace();
		}
    	
       
    }
}

xiaotian的接收類

UDPSocketTianReceivethread
package xiaotian;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
//同xiaozou
public class UDPSocketTianReceivethread implements Runnable{
        DatagramSocket tianSocket;
    {
        try {
        	tianSocket = new DatagramSocket(2020);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }
        byte[] ibuf = new byte[1024];
        DatagramPacket tianPacket = new DatagramPacket(ibuf, ibuf.length);


    @Override
    public void run() {
        while(true){
            try {
            	tianSocket.receive(tianPacket);
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("xiaotian:"+new String(tianPacket.getData(),0,tianPacket.getLength()));
        }
    }
}

結果截圖:
在這裡插入圖片描述
在這裡插入圖片描述