我正在编写一个代码,用于将加密文件从客户端发送到服务器 但首先客户端将文件的加密消息摘要发送到服务器,然后发送文件的名称,最后它将发送加密文件的字节, 但在服务器端,它将所有这些变量读作一个变量,即摘要,
当服务器尝试解密摘要时,它会抛出Illegal Block Size Exception
我的问题是服务器如何读取并将它们保存在不同的变量中?
客户
// set mode to encrypt
AesCipher.init(Cipher.ENCRYPT_MODE, key);
DataOutputStream toServer = new DataOutputStream(socket.getOutputStream());
// get the digest of the file
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest(bytes);
// encrypt digest and write it to file
byte [] encryptedHash = AesCipher.doFinal(hash);
toServer.write(encryptedHash);
// write file name to server
toServer.writeUTF(fileName);
//encrypt file
byte[] encryptedByte = AesCipher.doFinal(bytes);
// write file to server
toServer.write(encryptedByte);
toServer.flush();
socket.close();
服务器
// read digest of the file
byte [] digest =IOUtils.toByteArray(fromClient);
// decrypt it
AesCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedDigest = AesCipher.doFinal(digest);
// read file name to be received
String fileName = fromClient.readUTF();
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName);
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
// read file bytes from client
byte[] fileBytes = IOUtils.toByteArray(fromClient);
AesCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedByte = AesCipher.doFinal(fileBytes);
bos.write(decryptedByte, 0, decryptedByte.length);
bos.close();
我也试过这段代码,但它也没有用呢
// read digest of the file
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[1024];
while ((nRead = fromClient.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
byte[] digest = buffer.toByteArray();
// decrypt it
AesCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedDigest = AesCipher.doFinal(digest);
// read file name to be received
String fileName = fromClient.readUTF();
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName);
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
// read file bytes from client
byte[] fileBytes = IOUtils.toByteArray(fromClient);
AesCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedByte = AesCipher.doFinal(fileBytes);
bos.write(decryptedByte, 0, decryptedByte.length);
bos.close();
答案 0 :(得分:2)
IOUtils.toByteArray(InputStream)
读取整个流。因此,不是只获取哈希字节,而是获得整个流,并且没有任何内容用于文件名或密文,并且哈希没有检查。
您不需要外部库。您可以使用DataInputStream
和DataOutputStream
完成所有操作。但是你确实需要在散列之前发送散列的长度。
客户端:
// set mode to encrypt
AesCipher.init(Cipher.ENCRYPT_MODE, key);
DataOutputStream toServer = new DataOutputStream(socket.getOutputStream());
// get the digest of the file
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest(bytes);
// encrypt digest and write it to file
byte [] encryptedHash = AesCipher.doFinal(hash);
toServer.writeInt(encryptedHash.length);
toServer.write(encryptedHash);
// write file name to server
toServer.writeUTF(fileName);
//encrypt file
byte[] encryptedByte = AesCipher.doFinal(bytes);
// write file to server
toServer.writeInt(encryptedByte.length);
toServer.write(encryptedByte);
socket.close();
服务器:
// read digest of the file
int digestLength = fromClient.readInt();
byte[] digest = new byte[digestLength];
fromClient.readFully(digest);
// decrypt it
AesCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedDigest = AesCipher.doFinal(digest);
// read file name to be received
String fileName = fromClient.readUTF();
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName);
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
// read file bytes from client
int fileLength = fromClient.readInt();
byte[] fileBytes = new byte[fileLength];
fromClient.readFully(fileBytes);
AesCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedByte = AesCipher.doFinal(fileBytes);
bos.write(decryptedByte, 0, decryptedByte.length);
bos.close();
然而,使用CipherInputStream
和CipherOutputStream
可以更好地完成加密和解密部分。您不应将整个文件加载到内存中。
请注意,file.createNewFile()
之前new FileOutputStream(...)
来电是多余的。
为什么加密消息摘要是另一个谜。您应该将其用作最后一步,以便在解密后与本地生成的摘要进行比较。