【发布时间】:2020-08-25 08:52:42
【问题描述】:
我在尝试通过 CipherOutputStream 发送对象以使用 AES 对其进行加密并使用 CipherInputStream 接收以对其进行解密时遇到问题。
问题是服务器无法接收到对象:
Client > INFO > created ObjectOutputStream
Client > INFO > sent a Person object through ObjectOutputStream
Server > INFO > created cipherInputStream
Server > INFO > created ObjectInputStream
(在此之前它会阻塞:)
Person p = (Person) objectInputStream.readObject();
System.out.println("Server > INFO > received a Person object: " + p.toString());
如果我直接使用了 ObjectOutputStream 和 ObjectInputStream 而不是客户端中的 CipherOutputStream 和服务器中的 CipherInputStream ,那么它会正确接收它(我知道,因为我试过了)。
您是否有任何替代方法可以建议发送 AES 加密对象或如何解决问题的想法?
提前致谢。
主要
public class Main {
public static void main (String[] args) {
Server s = new Server();
Client c = new Client(s.serverSocket.getInetAddress().getHostName());
}
}
客户
import javax.crypto.*;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.security.*;
import java.util.Arrays;
public class Client {
private final int port = 3535;
private PublicKey publicKey;
private PrivateKey privateKey;
private SecretKey aesKey;
public Client(String hostname) {
try {
Socket socket = new Socket(hostname, port);
System.out.println("Client > INFO > Connected to server: " + socket.toString());
KeyPair keyPair = Cryptography.rsaKey();
if(keyPair == null) {
System.out.println("Client > ERROR > keyPair is null!");
return;
}
publicKey = keyPair.getPublic();
privateKey = keyPair.getPrivate();
//System.out.println("Client > publicKey > " + publicKey.toString());
//System.out.println("Client > privateKey created");
aesKey = Cryptography.aesKey();
if(aesKey == null) {
System.out.println("Client > ERROR > aesKey is null!");
return;
}
System.out.println("Client > INFO > aesKey > " + Arrays.toString(aesKey.getEncoded()));;
new Thread(new Runnable() {
@Override
public void run() {
try {
// Receiving the RSA - PublicKey
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
System.out.println("Client > INFO > created objectInputStream: " + objectInputStream.toString());
PublicKey publicKey1 = (PublicKey) objectInputStream.readObject();
System.out.println("Client > INFO > publicKey received from server: " + publicKey1.toString());
// Creating a Cipher object
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// Initializing the Cipher object for encrypting
rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey1);
byte[] encryptedKey = rsaCipher.doFinal(aesKey.getEncoded());
//System.out.println("Client > INFO > sending encrypted aesKey: " + Arrays.toString(encryptedKey));
// Sending the AES - SecretKey encrypted with the RSA - PublicKey
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataOutputStream.writeInt(encryptedKey.length);
dataOutputStream.flush();
dataOutputStream.write(encryptedKey);
dataOutputStream.flush();
// Creating an ObjectOutputStream over a CipherOutputStream
Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
aesCipher.init(Cipher.ENCRYPT_MODE, aesKey);
Person p = new Person();
p.setName("John");
p.setSurname("Smith");
CipherOutputStream cipherOutputStream = new CipherOutputStream(socket.getOutputStream(), aesCipher);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(cipherOutputStream);
System.out.println("Client > INFO > created ObjectOutputStream");
objectOutputStream.writeObject(p);
objectOutputStream.flush();
System.out.println("Client > INFO > sent a Person object through ObjectOutputStream");
} catch (IOException | ClassNotFoundException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务器
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.*;
import java.util.Arrays;
public class Server {
private final int port = 3535;
public ServerSocket serverSocket;
private PublicKey publicKey;
private PrivateKey privateKey;
public Server() {
try {
serverSocket = new ServerSocket(port);
KeyPair keyPair = Cryptography.rsaKey();
if(keyPair == null) {
System.out.println("Server > ERROR > keyPair is null!");
return;
}
publicKey = keyPair.getPublic();
privateKey = keyPair.getPrivate();
System.out.println("Server > publicKey > " + publicKey.toString());
System.out.println("Server > privateKey created");
ServerSocket finalServerSocket = serverSocket;
new Thread(new Runnable() {
@Override
public void run() {
Socket socket;
try {
socket = finalServerSocket.accept();
System.out.println("Server > INFO > A client connected: " + socket.toString());
// Sending the RSA - PublicKey
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
System.out.println("Server > INFO > created objectOutputStream: " + objectOutputStream.toString());
objectOutputStream.writeObject(publicKey);
objectOutputStream.flush();
// Receiving the encrypted AES - SecretKey
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
int length = dataInputStream.readInt();
System.out.println("Server > INFO > received encrypted aesKey's length: " + length);
byte[] encryptedKey;
if(length > 0) {
encryptedKey = new byte[length];
dataInputStream.readFully(encryptedKey, 0, encryptedKey.length);
} else {
System.out.println("Server > ERROR > length received is <= 0");
return;
}
System.out.println("Server > INFO > received encrypted aesKey: " + Arrays.toString(encryptedKey));
// Decrypting the encrypted AES - SecretKey
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsaCipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedKey = rsaCipher.doFinal(encryptedKey);
// Converting the decrypted AES - SecretKey to a SecretKey
SecretKey aesKey = new SecretKeySpec(decryptedKey, 0, decryptedKey.length, "AES");
System.out.println("Server > INFO > converted decrypted aesKey: " + Arrays.toString(aesKey.getEncoded()));
Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
aesCipher.init(Cipher.DECRYPT_MODE, aesKey);
// Creating an ObjectInputStream over a CipherInputStream
CipherInputStream cipherInputStream = new CipherInputStream(socket.getInputStream(), aesCipher);
System.out.println("Server > INFO > created cipherInputStream");
ObjectInputStream objectInputStream = new ObjectInputStream(cipherInputStream);
System.out.println("Server > INFO > created ObjectInputStream");
Person p = (Person) objectInputStream.readObject();
System.out.println("Server > INFO > received a Person object: " + p.toString());
} catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | ClassNotFoundException ex) {
ex.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
人
import java.io.Serializable;
public class Person implements Serializable {
private String name;
private String surname;
public Person() {}
public void setName(String name) {
this.name = name;
}
public void setSurname(String surname) {
this.surname = surname;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", surname='" + surname + '\'' +
'}';
}
}
密码学
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
public class Cryptography {
public static KeyPair rsaKey() {
try {
// Creating a Signature object
Signature sign = Signature.getInstance("SHA256withRSA");
// Creating KeyPair generator object
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// Initializing the key pair generator
keyPairGen.initialize(2048);
// Generating the pair of keys
return keyPairGen.generateKeyPair();
} catch (NoSuchAlgorithmException ignored) {}
return null;
}
public static SecretKey aesKey() {
try {
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(128); // The AES key size in number of bits
return generator.generateKey();
} catch (NoSuchAlgorithmException ignored) {}
return null;
}
}
【问题讨论】:
标签: java sockets object cryptography aes