1-1トムとジェリーがJavaUDPを使用してチャットしていると仮定して、彼らのためのプログラムを作成してください。詳細は次のとおりです。
(1)トムとジェリーのチャットには送信者と受信者が必要です。
(2)DatagramSocketとDatagramPacketを使用します。
(3)java.lang.Runnableクラスを実装し、run()メソッドを書き直します。
(4)トムは対称/非対称暗号化アルゴリズム(キーは個別に割り当てることができ、当局が配布する必要はありません)を使用して、送信されるコンテンツ(送信されるコンテンツは学生自身の名前+学生の学生ID)を暗号化します。次に、暗号化された暗号文をJerryに送信します。Jerryは受信した暗号文を復号化し、プレーンテキストコンテンツ(つまり、学生の名前+学生の学生ID)に復元します。
死の実験では、対称暗号化を作成するのに長い時間がかかりました。純粋な初心者、多くの間違いがあるかもしれません、私は大物が時間内にコメントエリアで指摘することを願っています!
まず、AESアルゴリズムと対称暗号化の概念については、ここでは詳しく説明しません。詳細については、この大物のブログを参照してください。https://www.cnblogs.com/wushaopei/p/11979154.html
環境構成
まず、Apache Commons Codec jarパッケージをダウンロードし、次のアドレスにbinファイルをダウンロードします。
http://commons.apache.org/proper/commons-codec/download_codec.cgi
そしてEclipseにインポートしました。ここにインポートした後にエラーを報告しています。コーデックのjarパッケージをクラスパスにインポートすることに注意してください。
以下に示す構成
次の具体的な実現
AESアルゴリズムの暗号化
AESクラスを使用して、キーの生成、キーの取得、暗号化、および復号化のプロセスを実装しました。
実装プロセスで発生する最大の問題は、送信スレッドがランダムにキーを生成した後、生成されたキーを受信スレッドに送信する方法です。
他の人のブログを読んでいる過程で、多くのビッグウィッグが初期化中に初期シードを渡していたことがわかりました。論理的に言えば、渡される初期値が同じである場合、生成されるキーは同じである必要があります。
ただし、実際の操作は成功しませんでした。復号化されたコードのこの行は、指定された最終ブロックが適切に埋め込まれていない
エラーを常に報告します。エラーの理由は、生成されたキーが異なるためです。ただし、具体的な理由は明確ではありません。そのため、別の方法でしか実行できません。生成されたキーをpkey.txtファイルに保存し、復号化するときに直接読み取ることを選択します。
AESクラスコードは次のとおりです。
package Chat_UDP;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
//import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
//import org.bouncycastle.util.encoders.Base64;
public class AES {
static String string = "杨丽冰 201831064402";
//key
KeyGenerator keyGenerator;
//密钥对象
SecretKey secretKey;
//密钥
byte[] keyBytes;
//key
Key key;
//生成密钥
public Key AESInit() throws NoSuchAlgorithmException, IOException {
//生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
//设置密钥长度
keyGenerator.init(128);
//生成密钥对象
SecretKey secretKey = keyGenerator.generateKey();
//获取密钥
byte[] keyBytes = secretKey.getEncoded();
//key转换
key = new SecretKeySpec(keyBytes,"AES");
//将密钥存入文件pkey.txt
File file=new File("pkey.txt");
OutputStream outputStream=new FileOutputStream(file);
outputStream.write(keyBytes);
outputStream.close();
return key;
}
//得到密钥
public Key getKey() throws NoSuchAlgorithmException, IOException {
//从文件中取出密钥
File file=new File("pkey.txt");
InputStream inputStream = new FileInputStream(file);
keyBytes = inputStream.readAllBytes();
key = new SecretKeySpec(keyBytes,"AES");
return key;
}
public String encryptAES(byte[] s,Key key){
byte[] result = null;
try {
//加密
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
//初始化,设置为加密
cipher.init(Cipher.ENCRYPT_MODE, key);
result = cipher.doFinal(s);
System.out.println("AES对称算法加密后的密文为: " + Base64.encodeBase64String(result));
} catch (Exception e) {
e.printStackTrace();
}
return Base64.encodeBase64String(result);
}
public String decryptAES(byte[] s,Key key){
byte[] result = null;
try {
//加密
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
//初始化,设置为解密
cipher.init(Cipher.DECRYPT_MODE, key);
result = cipher.doFinal(s);
System.out.println("AES对称算法解密后的明文为:" + new String(result));
} catch (Exception e) {
e.printStackTrace();
}
return new String(result);
}
}
次のコードテストを通じて、AESの暗号化と復号化機能をテストでき、JAVAが対称暗号化AESアルゴリズムで暗号化するように正常に実装され、UDP通信のプロセスに暗号化と復号化を書き込むだけであることがわかります。
テストクラスTest.java
package Chat_UDP;
import java.io.IOException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Base64;
public class Test {
public static void main(String []args) throws NoSuchAlgorithmException, IOException {
AES aes = new AES();
Key key = aes.AESInit();
Key key1 = aes.getKey();
if(key.equals(key1))
System.out.println("YES!密钥一致!" );
String s ="201831064402 杨丽冰";
String result = null;
//加密
result = aes.encryptAES(s.getBytes(), key);
//解密
s= aes.decryptAES(Base64.decodeBase64(result),key1 );
}
}
UDP通信を暗号化する
次に、AESメソッドを呼び出してデータを暗号化し、サーバーまたはクライアントでキーを初期化し、送信スレッドでデータを暗号化してから暗号文を送信し、受信スレッドで暗号文をプレーンテキストに復号化するだけです。 。
发送线程
```java
package Chat_UDP;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;
public class Send_Thread extends Thread{
//发送的socket端
private DatagramSocket sender = null;
//待发送的目标地址
private InetSocketAddress address = null;
//从键盘输入
Scanner scan = new Scanner(System.in);
public Send_Thread(DatagramSocket sender,InetSocketAddress address)
{
this.sender = sender;
this.address = address;
}
@Override
public void run() {
// TODO Auto-generated method stub
try
{
while(true)
{
//输入待发送的内容
String input = scan.nextLine();
if(input.equals("exit"))
break;
AES aes = new AES();
Key key = aes.getKey();
System.out.println("生成的密钥key是" + key);
//对输入数据进行加密
input=aes.encryptAES(input.getBytes(), key);
byte[] data = input.getBytes();
data = input.getBytes("UTF-8");
//创建UDP数据报,发送的是加密后的信息
DatagramPacket pack = new DatagramPacket(data, data.length,address);
sender.send(pack);
}
System.out.println("Exit!");
}catch(IOException | NoSuchAlgorithmException e)
{
System.out.println("IOException");
}
}
}
受信スレッド
package Chat_UDP;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
public class Receive_Thread extends Thread {
private static final int MAX_RECEIVE_BUFFER = 1024;
private DatagramSocket server;
private DatagramPacket packet;
byte[] buffer = new byte[MAX_RECEIVE_BUFFER];
public Receive_Thread(DatagramSocket server)
{
this.server = server;
packet = new DatagramPacket(buffer, buffer.length);
}
@Override
public void run() {
try
{
while(true)
{
//接收数据包
server.receive(packet);
AES aes = new AES();
Key key = aes.getKey();
System.out.println("密钥key是" + key);
String s = new String(packet.getData(),packet.getOffset(),packet.getLength(),"UTF-8");
System.out.println("接收到的信息为: " + s);
//对接收的数据解密
s = aes.decryptAES(Base64.decodeBase64(s), key);
Date day=new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if(packet.getPort() == 10001)
System.out.println("Tom"+packet.getAddress()+" 说:"+s+"\t"+df.format(day));
else{
System.out.println("Jerry"+packet.getAddress()+" 说 :"+s+"\t"+df.format(day));
}
packet.setLength(buffer.length);
}
}
catch(IOException | NoSuchAlgorithmException e)
{
System.out.println("IOException");
}
}
}
サーバー(TOM)
package Chat_UDP;
//杨丽冰 201831064402
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class Chat_Server {
//Tom
private static final int DEST_PORT = 8888;
private static final int SEND_PORT = 10001;
private static final int RECE_PORT = 9000;
private static final String IP = "127.0.0.1";
public static void main(String[] args)
{
try{
System.out.println("TOM");
Send_Thread send_thread = null;
Receive_Thread rece_thread = null;
InetSocketAddress address = null;
//生成密钥
AES aes = new AES();
aes.AESInit();
//创建待接受数据包的目的机的端口号和IP地址
address = new InetSocketAddress(IP, DEST_PORT);
//创建发送的Socket端
DatagramSocket sendsocket = new DatagramSocket(SEND_PORT);
//创建接受的Socket端
DatagramSocket recesocket = new DatagramSocket(RECE_PORT);
//发送线程建立
send_thread = new Send_Thread(sendsocket, address);
//接受线程的建立
rece_thread = new Receive_Thread(recesocket);
send_thread.start();
rece_thread.start();
}catch(Exception e)
{
System.out.println("Exception!");
}
}
}
クライアント(ジェリー)
package Chat_UDP;
//杨丽冰 201831064402
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class Chat_Client {
//Jerry
//声明端口号
//201831064402 杨丽冰
private static final int DEST_PORT = 9000;
private static final int SEND_PORT = 10000;
private static final int RECE_PORT = 8888;
private static final String IP = "127.0.0.1";
public static void main(String[] args)
{
try{
System.out.println("Jerry");
Send_Thread send_thread = null;
Receive_Thread rece_thread = null;
InetSocketAddress address = null;
//创建待接受数据包的目的机的端口号和IP地址
address = new InetSocketAddress(IP, DEST_PORT);
//创建发送的Socket端
DatagramSocket sendsocket = new DatagramSocket(SEND_PORT);
//创建接受的Socket端
DatagramSocket recesocket = new DatagramSocket(RECE_PORT);
//发送线程建立
send_thread = new Send_Thread(sendsocket, address);
//接受线程的建立
rece_thread = new Receive_Thread(recesocket);
send_thread.start();
rece_thread.start();
}catch(Exception e)
{
System.out.println("Exception!");
}
}
}