Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从InputStream JAVA读取不同的输入_Java_Android_Sockets - Fatal编程技术网

从InputStream JAVA读取不同的输入

从InputStream JAVA读取不同的输入,java,android,sockets,Java,Android,Sockets,我正在编写一个代码,将加密文件从客户端发送到服务器 但首先客户端将文件的加密消息摘要发送到服务器,然后发送文件名,最后发送加密文件的字节, 但在服务器端,它将所有这些变量作为一个变量读取,即摘要 当服务器试图解密摘要时,会抛出非法块大小异常 我这里的问题是服务器如何读取并将它们保存在不同的变量中 客户 // set mode to encrypt AesCipher.init(Cipher.ENCRYPT_MODE, key);

我正在编写一个代码,将加密文件从客户端发送到服务器 但首先客户端将文件的加密消息摘要发送到服务器,然后发送文件名,最后发送加密文件的字节, 但在服务器端,它将所有这些变量作为一个变量读取,即摘要

当服务器试图解密摘要时,会抛出
非法块大小异常
我这里的问题是服务器如何读取并将它们保存在不同的变量中

客户

            // 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();
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()
调用在
newfileoutputstream(…)
之前是多余的


为什么要加密邮件摘要是另一个谜。您应该将其作为解密后与本地生成的摘要进行比较的最后一步。

在服务器端,您不尝试读取为每个片段写入的相同字节数,而是读取写入
摘要的全部字节数。如果一个片段是16字节,那么您需要读取16字节。如果您不知道previor的长度是多少字节,那么您需要将片段的长度作为前缀添加到片段本身。@JamesKPolk i=i如何才能知道加密摘要后有多少字节?您必须先发送其长度。@EJP我在client to server.writeInt(encryptedHash.length)中编写了这篇文章;和int size=fromClient.readInt();字节[]数据=新字节[大小];在服务器中,但它也不起作用!!您应该发送一个数字,表示下次发送的字节数。谢谢,我刚刚发布了生成错误的代码,客户端将加密MD发送到服务器,以便服务器在解密后将其与本地生成的摘要进行比较。但您不需要加密MD。这不是秘密。