简体   繁体   中英

DataOutputStream only sends on close

When I run this code without the close method the server cannot receive the message!

client:

        Socket con = new Socket(InetAddress.getByName("localhost"), 12345);

        InputStream is = con.getInputStream();
        OutputStream os = con.getOutputStream();

        byte[] key = new byte[]{5};

        DataOutputStream dos = EncryptIO.getEncryptedOutputStream(key, os);
        DataInputStream dis = EncryptIO.getEncryptedInputStream(key, is);

        dos.writeUTF("Player 2");
        dos.close(); //with this the server receives the message
        String opUsername = dis.readUTF();

server:

        ServerSocket serverSocket = new ServerSocket(12345);
        Socket con = serverSocket.accept();

        InputStream is = con.getInputStream();
        OutputStream os = con.getOutputStream();

        byte[] key = new byte[]{5};

        DataOutputStream dos = EncryptIO.getEncryptedOutputStream(key, os);
        DataInputStream dis = EncryptIO.getEncryptedInputStream(key, is);

        String opUsername = dis.readUTF();
        System.out.println(opUsername);

        dos.writeUTF("Player 1"); //this line isn't reached because DataInputStream waits for the data

Under the DataOutput/InputStream are Cipherstreams underlying without them it works!

EncryptIO code:

public static DataInputStream getEncryptedInputStream(byte[] key, InputStream is) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchPaddingException {
    try {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, EncryptIO.getAESKey(key), EncryptIO.getIV(key));
        CipherInputStream cis = new CipherInputStream(is, cipher);
        return new DataInputStream(cis);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(EncryptIO.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
}

public static DataOutputStream getEncryptedOutputStream(byte[] key, OutputStream os) throws InvalidKeyException, NoSuchPaddingException, InvalidAlgorithmParameterException {
    try {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, EncryptIO.getAESKey(key), EncryptIO.getIV(key));
        CipherOutputStream cos = new CipherOutputStream(os, cipher);
        return new DataOutputStream(cos);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(EncryptIO.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
}

How can I get it DataOutputStream to send the data with the encryption and without closing?

Thanks in advance

From

Cipher.getInstance("AES/CBC/PKCS5Padding")

you're using an AES cipher in CBC mode with PKCS5Padding. Per the Java Cryptography Architecture Standard Algorithm Name Documentation for JDK 8 (reformatted, with links per the original):

AES

Advanced Encryption Standard as specified by NIST in FIPS 197 . Also known as the Rijndael algorithm by Joan Daemen and Vincent Rijmen, AES is a 128-bit block cipher supporting keys of 128, 192, and 256 bits.

To use the AES cipher with only one valid key size, use the format AES_, where can be 128, 192, or 256.

and

CBC

Cipher Block Chaining Mode, as defined in FIPS PUB 81 .

and

PKCS5Padding

The padding scheme described in RSA Laboratories, "PKCS #5: Password-Based Encryption Standard," version 1.5, November 1993 .

So, a block cipher, likely at 128 bits (16 bytes), with padding.

Note this from Cipher Algorithm Modes :

CFB, CFBx

Cipher Feedback Mode, as defined in FIPS PUB 81 .

Using modes such as CFB and OFB, block ciphers can encrypt data in units smaller than the cipher's actual block size. When requesting such a mode, you may optionally specify the number of bits to be processed at a time by appending this number to the mode name as shown in the "DES/CFB8/NoPadding" and "DES/OFB32/PKCS5Padding" transformations. If no such number is specified, a provider-specific default is used. (For example, the SunJCE provider uses a default of 64 bits for DES.) Thus, block ciphers can be turned into byte-oriented stream ciphers by using an 8-bit mode such as CFB8 or OFB8 .

So "AES/CFB8/NoPadding" or similar should work as a non-blocked stream cipher. You may still have to flush() the stream, however. And there will likely be a performance impact.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM